blob: 0e603facfb27fc522db434139a79b8f16d6d8bd7 [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>
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +010029#include <osmocom/vty/vty.h>
Neels Hofmeyr909e9722017-12-07 03:54:01 +010030
Neels Hofmeyrf14aaa42019-04-23 18:37:37 +020031#include <osmocom/mgcp_client/mgcp_client_endpoint_fsm.h>
Pau Espin Pedrole2490452018-03-17 01:16:54 +010032
Neels Hofmeyr909e9722017-12-07 03:54:01 +010033#include <osmocom/bsc/abis_rsl.h>
34#include <osmocom/bsc/debug.h>
35#include <osmocom/bsc/bsc_subscriber.h>
Neels Hofmeyr31f525e2018-05-14 18:14:15 +020036#include <osmocom/bsc/lchan_select.h>
37#include <osmocom/bsc/lchan_fsm.h>
Neels Hofmeyr909e9722017-12-07 03:54:01 +010038#include <osmocom/bsc/handover_decision.h>
39#include <osmocom/bsc/system_information.h>
Neels Hofmeyr31f525e2018-05-14 18:14:15 +020040#include <osmocom/bsc/handover.h>
Neels Hofmeyr909e9722017-12-07 03:54:01 +010041#include <osmocom/bsc/handover_cfg.h>
42#include <osmocom/bsc/handover_decision_2.h>
Neels Hofmeyr909e9722017-12-07 03:54:01 +010043#include <osmocom/bsc/bss.h>
Neels Hofmeyr81a49632018-07-24 18:10:05 +020044#include <osmocom/bsc/gsm_08_08.h>
Neels Hofmeyr909e9722017-12-07 03:54:01 +010045#include <osmocom/bsc/osmo_bsc.h>
Harald Welte3561bd42018-01-28 03:04:16 +010046#include <osmocom/bsc/bsc_subscr_conn_fsm.h>
Neels Hofmeyr31f525e2018-05-14 18:14:15 +020047#include <osmocom/bsc/timeslot_fsm.h>
48#include <osmocom/bsc/lchan_fsm.h>
Neels Hofmeyr31f525e2018-05-14 18:14:15 +020049#include <osmocom/bsc/handover_fsm.h>
50#include <osmocom/bsc/bsc_msc_data.h>
Pau Espin Pedrol388ed582020-07-15 20:53:16 +020051#include <osmocom/bsc/bts.h>
Neels Hofmeyr86ce1052020-09-18 02:49:32 +020052#include <osmocom/bsc/paging.h>
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +010053#include <osmocom/bsc/vty.h>
54
55#include "../../bscconfig.h"
Neels Hofmeyr909e9722017-12-07 03:54:01 +010056
Neels Hofmeyre3416182018-03-05 05:31:14 +010057void *ctx;
58
Neels Hofmeyr909e9722017-12-07 03:54:01 +010059struct gsm_network *bsc_gsmnet;
60
Neels Hofmeyrf14aaa42019-04-23 18:37:37 +020061/* override, requires '-Wl,--wrap=osmo_mgcpc_ep_ci_request'.
Harald Welte3561bd42018-01-28 03:04:16 +010062 * Catch modification of an MGCP connection. */
Neels Hofmeyrf14aaa42019-04-23 18:37:37 +020063void __real_osmo_mgcpc_ep_ci_request(struct osmo_mgcpc_ep_ci *ci,
Neels Hofmeyr31f525e2018-05-14 18:14:15 +020064 enum mgcp_verb verb, const struct mgcp_conn_peer *verb_info,
65 struct osmo_fsm_inst *notify,
66 uint32_t event_success, uint32_t event_failure,
67 void *notify_data);
Neels Hofmeyrf14aaa42019-04-23 18:37:37 +020068void __wrap_osmo_mgcpc_ep_ci_request(struct osmo_mgcpc_ep_ci *ci,
Neels Hofmeyr31f525e2018-05-14 18:14:15 +020069 enum mgcp_verb verb, const struct mgcp_conn_peer *verb_info,
70 struct osmo_fsm_inst *notify,
71 uint32_t event_success, uint32_t event_failure,
72 void *notify_data)
Harald Welte3561bd42018-01-28 03:04:16 +010073{
Neels Hofmeyr31f525e2018-05-14 18:14:15 +020074 struct mgcp_conn_peer fake_data = {};
75 /* All MGCP shall be successful */
76 if (!notify)
77 return;
78 osmo_fsm_inst_dispatch(notify, event_success, &fake_data);
Harald Welte3561bd42018-01-28 03:04:16 +010079}
80
Neels Hofmeyr909e9722017-12-07 03:54:01 +010081/* measurement report */
82
83uint8_t meas_rep_ba = 0, meas_rep_valid = 1, meas_valid = 1, meas_multi_rep = 0;
Neels Hofmeyr909e9722017-12-07 03:54:01 +010084uint8_t meas_ul_rxlev = 0, meas_ul_rxqual = 0;
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +010085uint8_t meas_tx_power_ms = 0, meas_tx_power_bs = 0;
Neels Hofmeyr909e9722017-12-07 03:54:01 +010086uint8_t meas_dtx_ms = 0, meas_dtx_bs = 0, meas_nr = 0;
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +010087char *codec_tch_f = NULL;
88char *codec_tch_h = NULL;
Neels Hofmeyr909e9722017-12-07 03:54:01 +010089
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +010090struct neighbor_meas {
91 uint8_t rxlev;
92 uint8_t bsic;
93 uint8_t bcch_f;
94};
95
96static void gen_meas_rep(struct gsm_lchan *lchan,
97 uint8_t rxlev, uint8_t rxqual, uint8_t ta,
98 int neighbors_count, struct neighbor_meas *neighbors)
Neels Hofmeyr909e9722017-12-07 03:54:01 +010099{
100 struct msgb *msg = msgb_alloc_headroom(256, 64, "RSL");
101 struct abis_rsl_dchan_hdr *dh;
102 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
103 uint8_t ulm[3], l1i[2], *buf;
104 struct gsm48_hdr *gh;
105 struct gsm48_meas_res *mr;
106
107 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
108 dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
109 dh->c.msg_type = RSL_MT_MEAS_RES;
110 dh->ie_chan = RSL_IE_CHAN_NR;
111 dh->chan_nr = chan_nr;
112
113 msgb_tv_put(msg, RSL_IE_MEAS_RES_NR, meas_nr++);
114
115 ulm[0] = meas_ul_rxlev | (meas_dtx_bs << 7);
116 ulm[1] = meas_ul_rxlev;
117 ulm[2] = (meas_ul_rxqual << 3) | meas_ul_rxqual;
118 msgb_tlv_put(msg, RSL_IE_UPLINK_MEAS, sizeof(ulm), ulm);
119
120 msgb_tv_put(msg, RSL_IE_BS_POWER, meas_tx_power_bs);
121
122 l1i[0] = 0;
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100123 l1i[1] = ta;
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100124 msgb_tv_fixed_put(msg, RSL_IE_L1_INFO, sizeof(l1i), l1i);
125
126 buf = msgb_put(msg, 3);
127 buf[0] = RSL_IE_L3_INFO;
128 buf[1] = (sizeof(*gh) + sizeof(*mr)) >> 8;
129 buf[2] = (sizeof(*gh) + sizeof(*mr)) & 0xff;
130
131 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
132 mr = (struct gsm48_meas_res *) msgb_put(msg, sizeof(*mr));
133
134 gh->proto_discr = GSM48_PDISC_RR;
135 gh->msg_type = GSM48_MT_RR_MEAS_REP;
136
137 /* measurement results */
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100138 mr->rxlev_full = rxlev;
139 mr->rxlev_sub = rxlev;
140 mr->rxqual_full = rxqual;
141 mr->rxqual_sub = rxqual;
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100142 mr->dtx_used = meas_dtx_ms;
143 mr->ba_used = meas_rep_ba;
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100144 mr->meas_valid = 0; /* 0 = valid */
145 mr->no_nc_n_hi = neighbors_count >> 2;
146 mr->no_nc_n_lo = neighbors_count & 3;
147
148 mr->rxlev_nc1 = neighbors[0].rxlev;
149 mr->rxlev_nc2_hi = neighbors[1].rxlev >> 1;
150 mr->rxlev_nc2_lo = neighbors[1].rxlev & 1;
151 mr->rxlev_nc3_hi = neighbors[2].rxlev >> 2;
152 mr->rxlev_nc3_lo = neighbors[2].rxlev & 3;
153 mr->rxlev_nc4_hi = neighbors[3].rxlev >> 3;
154 mr->rxlev_nc4_lo = neighbors[3].rxlev & 7;
155 mr->rxlev_nc5_hi = neighbors[4].rxlev >> 4;
156 mr->rxlev_nc5_lo = neighbors[4].rxlev & 15;
157 mr->rxlev_nc6_hi = neighbors[5].rxlev >> 5;
158 mr->rxlev_nc6_lo = neighbors[5].rxlev & 31;
159 mr->bsic_nc1_hi = neighbors[0].bsic >> 3;
160 mr->bsic_nc1_lo = neighbors[0].bsic & 7;
161 mr->bsic_nc2_hi = neighbors[1].bsic >> 4;
162 mr->bsic_nc2_lo = neighbors[1].bsic & 15;
163 mr->bsic_nc3_hi = neighbors[2].bsic >> 5;
164 mr->bsic_nc3_lo = neighbors[2].bsic & 31;
165 mr->bsic_nc4 = neighbors[3].bsic;
166 mr->bsic_nc5 = neighbors[4].bsic;
167 mr->bsic_nc6 = neighbors[5].bsic;
168 mr->bcch_f_nc1 = neighbors[0].bcch_f;
169 mr->bcch_f_nc2 = neighbors[1].bcch_f;
170 mr->bcch_f_nc3 = neighbors[2].bcch_f;
171 mr->bcch_f_nc4 = neighbors[3].bcch_f;
172 mr->bcch_f_nc5_hi = neighbors[4].bcch_f >> 1;
173 mr->bcch_f_nc5_lo = neighbors[4].bcch_f & 1;
174 mr->bcch_f_nc6_hi = neighbors[5].bcch_f >> 2;
175 mr->bcch_f_nc6_lo = neighbors[5].bcch_f & 3;
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100176
177 msg->dst = lchan->ts->trx->bts->c0->rsl_link;
178 msg->l2h = (unsigned char *)dh;
179 msg->l3h = (unsigned char *)gh;
180
181 abis_rsl_rcvmsg(msg);
182}
183
Neels Hofmeyre3eb67c2020-11-12 22:53:59 +0100184enum gsm_phys_chan_config pchan_from_str(const char *str)
185{
Neels Hofmeyrcfbf11f2020-11-12 23:12:48 +0100186 enum gsm_phys_chan_config pchan;
187 if (!strcmp(str, "dyn"))
188 return GSM_PCHAN_TCH_F_TCH_H_PDCH;
189 if (!strcmp(str, "c+s4"))
190 return GSM_PCHAN_CCCH_SDCCH4;
191 if (!strcmp(str, "-"))
192 return GSM_PCHAN_NONE;
193 pchan = gsm_pchan_parse(str);
Neels Hofmeyre3eb67c2020-11-12 22:53:59 +0100194 if (pchan < 0) {
195 fprintf(stderr, "Invalid timeslot pchan type: %s\n", str);
196 exit(1);
197 }
198 return pchan;
199}
200
201const char * const bts_default_ts[] = {
Neels Hofmeyrcfbf11f2020-11-12 23:12:48 +0100202 "c+s4", "TCH/F", "TCH/F", "TCH/F", "TCH/F", "TCH/H", "TCH/H", "-",
Neels Hofmeyre3eb67c2020-11-12 22:53:59 +0100203};
204
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100205static struct gsm_bts *_create_bts(int num_trx, const char * const *ts_args, int ts_args_count)
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100206{
Neels Hofmeyr2f58de52020-11-12 22:51:11 +0100207 static int arfcn = 870;
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100208 struct gsm_bts *bts;
209 struct e1inp_sign_link *rsl_link;
210 int i;
Neels Hofmeyrdd7b7102020-11-12 22:54:58 +0100211 int trx_i;
Neels Hofmeyre3eb67c2020-11-12 22:53:59 +0100212 struct gsm_bts_trx *trx;
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100213
Neels Hofmeyrcfbf11f2020-11-12 23:12:48 +0100214 fprintf(stderr, "- Creating BTS %d, %d TRX\n", bsc_gsmnet->num_bts, num_trx);
Neels Hofmeyrcfbf11f2020-11-12 23:12:48 +0100215
Vadim Yanitskiy4f3a6412020-05-31 01:56:20 +0700216 bts = bsc_bts_alloc_register(bsc_gsmnet, GSM_BTS_TYPE_UNKNOWN, 0x3f);
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100217 if (!bts) {
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100218 fprintf(stderr, "No resource for bts1\n");
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100219 return NULL;
220 }
221
222 bts->location_area_code = 23;
Neels Hofmeyr2f58de52020-11-12 22:51:11 +0100223 bts->c0->arfcn = arfcn++;
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100224
225 bts->codec.efr = 1;
226 bts->codec.hr = 1;
227 bts->codec.amr = 1;
228
Neels Hofmeyre3416182018-03-05 05:31:14 +0100229 rsl_link = talloc_zero(ctx, struct e1inp_sign_link);
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100230 rsl_link->trx = bts->c0;
231 bts->c0->rsl_link = rsl_link;
232
Neels Hofmeyrdd7b7102020-11-12 22:54:58 +0100233 for (trx_i = 0; trx_i < num_trx; trx_i++) {
234 while (!(trx = gsm_bts_trx_num(bts, trx_i)))
235 gsm_bts_trx_alloc(bts);
Neels Hofmeyre3eb67c2020-11-12 22:53:59 +0100236
Neels Hofmeyrdd7b7102020-11-12 22:54:58 +0100237 trx->mo.nm_state.operational = NM_OPSTATE_ENABLED;
238 trx->mo.nm_state.availability = NM_AVSTATE_OK;
239 trx->mo.nm_state.administrative = NM_STATE_UNLOCKED;
240 trx->bb_transc.mo.nm_state.operational = NM_OPSTATE_ENABLED;
241 trx->bb_transc.mo.nm_state.availability = NM_AVSTATE_OK;
242 trx->bb_transc.mo.nm_state.administrative = NM_STATE_UNLOCKED;
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100243
Neels Hofmeyrdd7b7102020-11-12 22:54:58 +0100244 /* 4 full rate and 4 half rate channels */
245 for (i = 0; i < 8; i++) {
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100246 int arg_i = trx_i * 8 + i;
247 const char *ts_arg;
248 if (arg_i >= ts_args_count)
249 ts_arg = bts_default_ts[i];
250 else
251 ts_arg = ts_args[arg_i];
252 fprintf(stderr, "\t%s", ts_arg);
253 trx->ts[i].pchan_from_config = pchan_from_str(ts_arg);
Neels Hofmeyrdd7b7102020-11-12 22:54:58 +0100254 if (trx->ts[i].pchan_from_config == GSM_PCHAN_NONE)
255 continue;
256 trx->ts[i].mo.nm_state.operational = NM_OPSTATE_ENABLED;
257 trx->ts[i].mo.nm_state.availability = NM_AVSTATE_OK;
258 trx->ts[i].mo.nm_state.administrative = NM_STATE_UNLOCKED;
259 }
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100260 fprintf(stderr, "\n");
Neels Hofmeyr31f525e2018-05-14 18:14:15 +0200261
Neels Hofmeyrcfbf11f2020-11-12 23:12:48 +0100262 for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
Neels Hofmeyrdd7b7102020-11-12 22:54:58 +0100263 /* make sure ts->lchans[] get initialized */
Neels Hofmeyrcfbf11f2020-11-12 23:12:48 +0100264 osmo_fsm_inst_dispatch(trx->ts[i].fi, TS_EV_RSL_READY, 0);
265 osmo_fsm_inst_dispatch(trx->ts[i].fi, TS_EV_OML_READY, 0);
266
267 /* Unused dyn TS start out as used for PDCH */
268 switch (trx->ts[i].pchan_on_init) {
269 case GSM_PCHAN_TCH_F_TCH_H_PDCH:
270 case GSM_PCHAN_TCH_F_PDCH:
271 trx->ts[i].pchan_is = GSM_PCHAN_PDCH;
272 break;
273 default:
274 break;
275 }
Neels Hofmeyrdd7b7102020-11-12 22:54:58 +0100276 }
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100277 }
Neels Hofmeyr780f0282020-11-12 22:51:58 +0100278
279 for (i = 0; i < bsc_gsmnet->num_bts; i++) {
280 if (gsm_generate_si(gsm_bts_num(bsc_gsmnet, i), SYSINFO_TYPE_2) <= 0)
281 fprintf(stderr, "Error generating SI2\n");
282 }
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100283 return bts;
284}
285
Neels Hofmeyr43666542020-11-13 01:12:34 +0100286const char *ts_use_str(struct gsm_bts_trx_ts *ts)
287{
288 switch (ts->pchan_is) {
289 case GSM_PCHAN_CCCH_SDCCH4:
290 return "c+s4";
291
292 case GSM_PCHAN_NONE:
293 return "-";
294
295 case GSM_PCHAN_TCH_F:
296 if (lchan_state_is(&ts->lchan[0], LCHAN_ST_ESTABLISHED))
297 return "TCH/F";
298 else
299 return "-";
300
301 case GSM_PCHAN_TCH_H:
302 if (lchan_state_is(&ts->lchan[0], LCHAN_ST_ESTABLISHED)
303 && lchan_state_is(&ts->lchan[1], LCHAN_ST_ESTABLISHED))
304 return "TCH/HH";
305 if (lchan_state_is(&ts->lchan[0], LCHAN_ST_ESTABLISHED))
306 return "TCH/H-";
307 if (lchan_state_is(&ts->lchan[1], LCHAN_ST_ESTABLISHED))
308 return "TCH/-H";
309 return "-";
310
311 default:
312 return gsm_pchan_name(ts->pchan_is);
313 }
314}
315
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100316bool _expect_ts_use(struct gsm_bts *bts, struct gsm_bts_trx *trx, const char * const *ts_use)
Neels Hofmeyr43666542020-11-13 01:12:34 +0100317{
Neels Hofmeyr43666542020-11-13 01:12:34 +0100318 int i;
319 int mismatching_ts = -1;
Neels Hofmeyr43666542020-11-13 01:12:34 +0100320
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100321 fprintf(stderr, "bts %d trx %d: expect:", bts->nr, trx->nr);
Neels Hofmeyr43666542020-11-13 01:12:34 +0100322 for (i = 0; i < 8; i++)
323 fprintf(stderr, "\t%s", ts_use[i]);
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100324 fprintf(stderr, "\nbts %d trx %d: got:", bts->nr, trx->nr);
Neels Hofmeyr43666542020-11-13 01:12:34 +0100325
326 for (i = 0; i < 8; i++) {
327 struct gsm_bts_trx_ts *ts = &trx->ts[i];
328 const char *use = ts_use_str(ts);
329
330 fprintf(stderr, "\t%s", use);
331
332 if (!strcmp(ts_use[i], "*"))
333 continue;
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100334 if (strcasecmp(ts_use[i], use) && mismatching_ts < 0)
Neels Hofmeyr43666542020-11-13 01:12:34 +0100335 mismatching_ts = i;
336 }
337 fprintf(stderr, "\n");
338
339 if (mismatching_ts >= 0) {
340 fprintf(stderr, "Test failed: mismatching TS use in bts %d trx %d ts %d\n",
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100341 bts->nr, trx->nr, mismatching_ts);
Neels Hofmeyr43666542020-11-13 01:12:34 +0100342 return false;
343 }
344 return true;
345}
346
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100347void create_conn(struct gsm_lchan *lchan)
348{
Neels Hofmeyrbb6c13b2018-05-24 18:43:58 +0200349 static unsigned int next_imsi = 0;
350 char imsi[sizeof(lchan->conn->bsub->imsi)];
351 struct gsm_network *net = lchan->ts->trx->bts->network;
Harald Welte3561bd42018-01-28 03:04:16 +0100352 struct gsm_subscriber_connection *conn;
Neels Hofmeyr31f525e2018-05-14 18:14:15 +0200353 struct mgcp_client *fake_mgcp_client = (void*)talloc_zero(net, int);
Neels Hofmeyrbb6c13b2018-05-24 18:43:58 +0200354
355 conn = bsc_subscr_con_allocate(net);
Harald Welte3561bd42018-01-28 03:04:16 +0100356
Neels Hofmeyrf14aaa42019-04-23 18:37:37 +0200357 conn->user_plane.mgw_endpoint = osmo_mgcpc_ep_alloc(conn->fi,
Neels Hofmeyr31f525e2018-05-14 18:14:15 +0200358 GSCON_EV_FORGET_MGW_ENDPOINT,
Neels Hofmeyrf14aaa42019-04-23 18:37:37 +0200359 fake_mgcp_client,
360 net->mgw.tdefs,
361 "test",
Neels Hofmeyr31f525e2018-05-14 18:14:15 +0200362 "fake endpoint");
Alexander Chemeris69ba8be2020-05-10 22:48:01 +0300363 conn->sccp.msc = osmo_msc_data_alloc(net, 0);
Harald Welte3561bd42018-01-28 03:04:16 +0100364
365 lchan->conn = conn;
366 conn->lchan = lchan;
Neels Hofmeyrbb6c13b2018-05-24 18:43:58 +0200367
368 /* Make up a new IMSI for this test, for logging the subscriber */
369 next_imsi ++;
370 snprintf(imsi, sizeof(imsi), "%06u", next_imsi);
Neels Hofmeyr86a1dca2020-09-15 01:03:58 +0000371 lchan->conn->bsub = bsc_subscr_find_or_create_by_imsi(net->bsc_subscribers, imsi, BSUB_USE_CONN);
Neels Hofmeyrbb6c13b2018-05-24 18:43:58 +0200372
Harald Welte3561bd42018-01-28 03:04:16 +0100373 /* kick the FSM from INIT through to the ACTIVE state */
Neels Hofmeyrd1e7d392020-09-27 23:34:57 +0200374 osmo_fsm_inst_dispatch(conn->fi, GSCON_EV_MO_COMPL_L3, NULL);
Harald Welte3561bd42018-01-28 03:04:16 +0100375 osmo_fsm_inst_dispatch(conn->fi, GSCON_EV_A_CONN_CFM, NULL);
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100376}
377
Neels Hofmeyr5531fae2020-11-13 03:43:57 +0100378struct gsm_lchan *lchan_act(struct gsm_lchan *lchan, int full_rate, const char *codec)
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100379{
Neels Hofmeyr31f525e2018-05-14 18:14:15 +0200380 /* serious hack into osmo_fsm */
381 lchan->fi->state = LCHAN_ST_ESTABLISHED;
382 lchan->ts->fi->state = TS_ST_IN_USE;
Neels Hofmeyr5531fae2020-11-13 03:43:57 +0100383 lchan->type = full_rate ? GSM_LCHAN_TCH_F : GSM_LCHAN_TCH_H;
Neels Hofmeyrfb6d9dc2020-11-13 01:13:20 +0100384
385 if (lchan->ts->pchan_on_init == GSM_PCHAN_TCH_F_TCH_H_PDCH)
386 lchan->ts->pchan_is = full_rate ? GSM_PCHAN_TCH_F : GSM_PCHAN_TCH_H;
387 if (lchan->ts->pchan_on_init == GSM_PCHAN_TCH_F_PDCH) {
388 OSMO_ASSERT(full_rate);
389 lchan->ts->pchan_is = GSM_PCHAN_TCH_F;
390 }
391
Neels Hofmeyr31f525e2018-05-14 18:14:15 +0200392 LOG_LCHAN(lchan, LOGL_DEBUG, "activated by handover_test.c\n");
393
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100394 create_conn(lchan);
395 if (!strcasecmp(codec, "FR") && full_rate)
396 lchan->tch_mode = GSM48_CMODE_SPEECH_V1;
397 else if (!strcasecmp(codec, "HR") && !full_rate)
398 lchan->tch_mode = GSM48_CMODE_SPEECH_V1;
399 else if (!strcasecmp(codec, "EFR") && full_rate)
400 lchan->tch_mode = GSM48_CMODE_SPEECH_EFR;
Philipp Maiereda6bfa2019-03-11 14:10:26 +0100401 else if (!strcasecmp(codec, "AMR")) {
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100402 lchan->tch_mode = GSM48_CMODE_SPEECH_AMR;
Philipp Maiereda6bfa2019-03-11 14:10:26 +0100403 lchan->activate.info.s15_s0 = 0x0002;
404 } else {
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100405 fprintf(stderr, "Given codec unknown\n");
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100406 exit(EXIT_FAILURE);
407 }
408
409 lchan->conn->codec_list = (struct gsm0808_speech_codec_list){
410 .codec = {
411 { .fi=true, .type=GSM0808_SCT_FR1, },
412 { .fi=true, .type=GSM0808_SCT_FR2, },
413 { .fi=true, .type=GSM0808_SCT_FR3, },
414 { .fi=true, .type=GSM0808_SCT_HR1, },
415 { .fi=true, .type=GSM0808_SCT_HR3, },
416 },
417 .len = 5,
418 };
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100419
420 return lchan;
421}
422
Neels Hofmeyr5531fae2020-11-13 03:43:57 +0100423struct gsm_lchan *create_lchan(struct gsm_bts *bts, int full_rate, const char *codec)
424{
425 struct gsm_lchan *lchan;
426
427 lchan = lchan_select_by_type(bts, (full_rate) ? GSM_LCHAN_TCH_F : GSM_LCHAN_TCH_H);
428 if (!lchan) {
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100429 fprintf(stderr, "No resource for lchan\n");
Neels Hofmeyr5531fae2020-11-13 03:43:57 +0100430 exit(EXIT_FAILURE);
431 }
432
433 return lchan_act(lchan, full_rate, codec);
434}
435
436static void lchan_clear(struct gsm_lchan *lchan)
437{
438 lchan_release(lchan, true, false, 0);
439}
440
441static void ts_clear(struct gsm_bts_trx_ts *ts)
442{
443 struct gsm_lchan *lchan;
444 ts_for_each_lchan(lchan, ts) {
445 if (lchan_state_is(lchan, LCHAN_ST_UNUSED))
446 continue;
447 lchan_clear(lchan);
448 }
449}
450
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100451bool _set_ts_use(struct gsm_bts *bts, struct gsm_bts_trx *trx, const char * const *ts_use)
Neels Hofmeyr5531fae2020-11-13 03:43:57 +0100452{
Neels Hofmeyr5531fae2020-11-13 03:43:57 +0100453 int i;
Neels Hofmeyr5531fae2020-11-13 03:43:57 +0100454
455 fprintf(stderr, "Setting TS use:");
456 for (i = 0; i < 8; i++)
457 fprintf(stderr, "\t%s", ts_use[i]);
458 fprintf(stderr, "\n");
459
460 for (i = 0; i < 8; i++) {
461 struct gsm_bts_trx_ts *ts = &trx->ts[i];
462 const char *want_use = ts_use[i];
463 const char *is_use = ts_use_str(ts);
464
465 if (!strcmp(want_use, "*"))
466 continue;
467
468 /* If it is already as desired, don't change anything */
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100469 if (!strcasecmp(want_use, is_use))
Neels Hofmeyr5531fae2020-11-13 03:43:57 +0100470 continue;
471
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100472 if (!strcasecmp(want_use, "tch/f")) {
Neels Hofmeyr5531fae2020-11-13 03:43:57 +0100473 if (!ts_is_capable_of_pchan(ts, GSM_PCHAN_TCH_F)) {
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100474 fprintf(stderr, "Error: bts %d trx %d ts %d cannot be used as TCH/F\n",
475 bts->nr, trx->nr, i);
Neels Hofmeyr5531fae2020-11-13 03:43:57 +0100476 return false;
477 }
478 ts_clear(ts);
479
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100480 lchan_act(&ts->lchan[0], true, codec_tch_f ? : "AMR");
481 } else if (!strcasecmp(want_use, "tch/h-")
482 || !strcasecmp(want_use, "tch/hh")
483 || !strcasecmp(want_use, "tch/-h")) {
Neels Hofmeyr5531fae2020-11-13 03:43:57 +0100484 bool act[2];
485 int j;
486
487 if (!ts_is_capable_of_pchan(ts, GSM_PCHAN_TCH_H)) {
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100488 fprintf(stderr, "Error: bts %d trx %d ts %d cannot be used as TCH/H\n",
489 bts->nr, trx->nr, i);
Neels Hofmeyr5531fae2020-11-13 03:43:57 +0100490 return false;
491 }
492
493 if (ts->pchan_is != GSM_PCHAN_TCH_H)
494 ts_clear(ts);
495
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100496 act[0] = (want_use[4] == 'h' || want_use[4] == 'H');
497 act[1] = (want_use[5] == 'h' || want_use[5] == 'H');
Neels Hofmeyr5531fae2020-11-13 03:43:57 +0100498
499 for (j = 0; j < 2; j++) {
500 if (lchan_state_is(&ts->lchan[j], LCHAN_ST_UNUSED)) {
501 if (act[j])
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100502 lchan_act(&ts->lchan[j], false, codec_tch_h ? : "AMR");
Neels Hofmeyr5531fae2020-11-13 03:43:57 +0100503 } else if (!act[j])
504 lchan_clear(&ts->lchan[j]);
505 }
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100506 } else if (!strcmp(want_use, "-") || !strcasecmp(want_use, "PDCH")) {
Neels Hofmeyr5531fae2020-11-13 03:43:57 +0100507 ts_clear(ts);
508 }
509 }
510 return true;
511}
512
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100513/* parse channel request */
514
515static int got_chan_req = 0;
516static struct gsm_lchan *chan_req_lchan = NULL;
517
518static int parse_chan_act(struct gsm_lchan *lchan, uint8_t *data)
519{
520 chan_req_lchan = lchan;
521 return 0;
522}
523
524static int parse_chan_rel(struct gsm_lchan *lchan, uint8_t *data)
525{
526 chan_req_lchan = lchan;
527 return 0;
528}
529
530/* parse handover request */
531
532static int got_ho_req = 0;
533static struct gsm_lchan *ho_req_lchan = NULL;
534
535static int parse_ho_command(struct gsm_lchan *lchan, uint8_t *data, int len)
536{
537 struct gsm48_hdr *gh = (struct gsm48_hdr *) data;
538 struct gsm48_ho_cmd *ho = (struct gsm48_ho_cmd *) gh->data;
539 int arfcn;
540 struct gsm_bts *neigh;
541
542 switch (gh->msg_type) {
543 case GSM48_MT_RR_HANDO_CMD:
544 arfcn = (ho->cell_desc.arfcn_hi << 8) | ho->cell_desc.arfcn_lo;
545
546 /* look up trx. since every dummy bts uses different arfcn and
547 * only one trx, it is simple */
548 llist_for_each_entry(neigh, &bsc_gsmnet->bts_list, list) {
549 if (neigh->c0->arfcn != arfcn)
550 continue;
551 ho_req_lchan = lchan;
552 return 0;
553 }
554 break;
555 case GSM48_MT_RR_ASS_CMD:
556 ho_req_lchan = lchan;
557 return 0;
558 break;
559 default:
560 fprintf(stderr, "Error, expecting HO or AS command\n");
561 return -EINVAL;
562 }
563
564 return -1;
565}
566
567/* send channel activation ack */
568static void send_chan_act_ack(struct gsm_lchan *lchan, int act)
569{
570 struct msgb *msg = msgb_alloc_headroom(256, 64, "RSL");
571 struct abis_rsl_dchan_hdr *dh;
572
573 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
574 dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
575 dh->c.msg_type = (act) ? RSL_MT_CHAN_ACTIV_ACK : RSL_MT_RF_CHAN_REL_ACK;
576 dh->ie_chan = RSL_IE_CHAN_NR;
577 dh->chan_nr = gsm_lchan2chan_nr(lchan);
578
579 msg->dst = lchan->ts->trx->bts->c0->rsl_link;
580 msg->l2h = (unsigned char *)dh;
581
582 abis_rsl_rcvmsg(msg);
583}
584
Neels Hofmeyr31f525e2018-05-14 18:14:15 +0200585/* Send RLL Est Ind for SAPI[0] */
586static void send_est_ind(struct gsm_lchan *lchan)
587{
588 struct msgb *msg = msgb_alloc_headroom(256, 64, "RSL");
589 struct abis_rsl_rll_hdr *rh;
590 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
591
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100592 fprintf(stderr, "- Send EST IND for %s\n", gsm_lchan_name(lchan));
593
Neels Hofmeyr31f525e2018-05-14 18:14:15 +0200594 rh = (struct abis_rsl_rll_hdr *) msgb_put(msg, sizeof(*rh));
595 rh->c.msg_discr = ABIS_RSL_MDISC_RLL;
596 rh->c.msg_type = RSL_MT_EST_IND;
597 rh->ie_chan = RSL_IE_CHAN_NR;
598 rh->chan_nr = chan_nr;
599 rh->ie_link_id = RSL_IE_LINK_IDENT;
600 rh->link_id = 0x00;
601
602 msg->dst = lchan->ts->trx->bts->c0->rsl_link;
603 msg->l2h = (unsigned char *)rh;
604
605 abis_rsl_rcvmsg(msg);
606}
607
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100608/* send handover complete */
609static void send_ho_complete(struct gsm_lchan *lchan, bool success)
610{
611 struct msgb *msg = msgb_alloc_headroom(256, 64, "RSL");
612 struct abis_rsl_rll_hdr *rh;
613 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
614 uint8_t *buf;
615 struct gsm48_hdr *gh;
616 struct gsm48_ho_cpl *hc;
617
Neels Hofmeyr31f525e2018-05-14 18:14:15 +0200618 send_est_ind(lchan);
Neels Hofmeyrac85b342018-07-12 21:23:26 +0200619 osmo_fsm_inst_dispatch(lchan->fi, LCHAN_EV_RTP_READY, 0);
Neels Hofmeyr31f525e2018-05-14 18:14:15 +0200620
Neels Hofmeyr64982dd2020-12-10 16:05:35 +0100621 if (success)
622 fprintf(stderr, "- Send HO COMPLETE for %s\n", gsm_lchan_name(lchan));
623 else
624 fprintf(stderr, "- Send HO FAIL to %s\n", gsm_lchan_name(lchan));
625
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100626 rh = (struct abis_rsl_rll_hdr *) msgb_put(msg, sizeof(*rh));
627 rh->c.msg_discr = ABIS_RSL_MDISC_RLL;
628 rh->c.msg_type = RSL_MT_DATA_IND;
629 rh->ie_chan = RSL_IE_CHAN_NR;
630 rh->chan_nr = chan_nr;
631 rh->ie_link_id = RSL_IE_LINK_IDENT;
632 rh->link_id = 0x00;
633
634 buf = msgb_put(msg, 3);
635 buf[0] = RSL_IE_L3_INFO;
636 buf[1] = (sizeof(*gh) + sizeof(*hc)) >> 8;
637 buf[2] = (sizeof(*gh) + sizeof(*hc)) & 0xff;
638
639 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
640 hc = (struct gsm48_ho_cpl *) msgb_put(msg, sizeof(*hc));
641
642 gh->proto_discr = GSM48_PDISC_RR;
643 gh->msg_type =
644 success ? GSM48_MT_RR_HANDO_COMPL : GSM48_MT_RR_HANDO_FAIL;
645
646 msg->dst = lchan->ts->trx->bts->c0->rsl_link;
647 msg->l2h = (unsigned char *)rh;
648 msg->l3h = (unsigned char *)gh;
649
650 abis_rsl_rcvmsg(msg);
651}
652
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100653static void lchan_release_ack(struct gsm_lchan *lchan)
654{
655 if (lchan->fi && lchan->fi->state == LCHAN_ST_WAIT_BEFORE_RF_RELEASE) {
656 /* don't wait before release */
657 osmo_fsm_inst_state_chg(lchan->fi, LCHAN_ST_WAIT_RF_RELEASE_ACK, 0, 0);
658 /* ack the release */
659 osmo_fsm_inst_dispatch(lchan->fi, LCHAN_EV_RSL_RF_CHAN_REL_ACK, 0);
660 }
661}
662
Neels Hofmeyr1d7473c2018-03-05 21:53:18 +0100663/* override, requires '-Wl,--wrap=abis_rsl_sendmsg'.
664 * Catch RSL messages sent towards the BTS. */
665int __real_abis_rsl_sendmsg(struct msgb *msg);
666int __wrap_abis_rsl_sendmsg(struct msgb *msg)
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100667{
668 struct abis_rsl_dchan_hdr *dh = (struct abis_rsl_dchan_hdr *) msg->data;
669 struct e1inp_sign_link *sign_link = msg->dst;
670 int rc;
671 struct gsm_lchan *lchan = rsl_lchan_lookup(sign_link->trx, dh->chan_nr, &rc);
Neels Hofmeyrfb6d9dc2020-11-13 01:13:20 +0100672 struct gsm_lchan *other_lchan;
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100673
674 if (rc) {
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100675 fprintf(stderr, "rsl_lchan_lookup() failed\n");
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100676 exit(1);
677 }
678
679 switch (dh->c.msg_type) {
680 case RSL_MT_CHAN_ACTIV:
681 rc = parse_chan_act(lchan, dh->data);
682 if (rc == 0)
683 got_chan_req = 1;
684 break;
685 case RSL_MT_RF_CHAN_REL:
686 rc = parse_chan_rel(lchan, dh->data);
687 if (rc == 0)
688 send_chan_act_ack(chan_req_lchan, 0);
Neels Hofmeyrfb6d9dc2020-11-13 01:13:20 +0100689
690 /* send dyn TS back to PDCH if unused */
691 switch (chan_req_lchan->ts->pchan_on_init) {
692 case GSM_PCHAN_TCH_F_TCH_H_PDCH:
693 case GSM_PCHAN_TCH_F_PDCH:
694 switch (chan_req_lchan->ts->pchan_is) {
695 case GSM_PCHAN_TCH_H:
696 other_lchan = &chan_req_lchan->ts->lchan[
697 (chan_req_lchan == &chan_req_lchan->ts->lchan[0])?
698 1 : 0];
699 if (lchan_state_is(other_lchan, LCHAN_ST_ESTABLISHED))
700 break;
701 /* else fall thru */
702 case GSM_PCHAN_TCH_F:
703 chan_req_lchan->ts->pchan_is = GSM_PCHAN_PDCH;
704 break;
705 default:
706 break;
707 }
708 break;
709 default:
710 break;
711 }
712
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100713 break;
714 case RSL_MT_DATA_REQ:
715 rc = parse_ho_command(lchan, msg->l3h, msgb_l3len(msg));
716 if (rc == 0)
717 got_ho_req = 1;
718 break;
719 case RSL_MT_IPAC_CRCX:
720 break;
Neels Hofmeyr5b1a7d12018-11-06 22:24:07 +0100721 case RSL_MT_DEACTIVATE_SACCH:
722 break;
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100723 default:
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100724 fprintf(stderr, "unknown rsl message=0x%x\n", dh->c.msg_type);
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100725 }
726 return 0;
727}
728
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100729struct gsm_bts *bts_by_num_str(const char *num_str)
730{
731 struct gsm_bts *bts = gsm_bts_num(bsc_gsmnet, atoi(num_str));
732 OSMO_ASSERT(bts);
733 return bts;
734}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100735
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100736struct gsm_bts_trx *trx_by_num_str(struct gsm_bts *bts, const char *num_str)
737{
738 struct gsm_bts_trx *trx = gsm_bts_trx_num(bts, atoi(num_str));
739 OSMO_ASSERT(trx);
740 return trx;
741}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100742
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100743#define LCHAN_ARGS "lchan <0-255> <0-255> <0-7> <0-7>"
744#define LCHAN_ARGS_DOC "identify an lchan\nBTS nr\nTRX nr\nTimeslot nr\nSubslot nr\n"
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100745
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100746static struct gsm_lchan *parse_lchan_args(const char **argv)
747{
748 struct gsm_bts *bts = bts_by_num_str(argv[0]);
749 struct gsm_bts_trx *trx = trx_by_num_str(bts, argv[1]);
750 struct gsm_bts_trx_ts *ts = &trx->ts[atoi(argv[2])];
751 return &ts->lchan[atoi(argv[3])];
752}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100753
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100754#define TS_USE " (TCH/F|TCH/H-|TCH/-H|TCH/HH|PDCH" \
755 "|tch/f|tch/h-|tch/-h|tch/hh|pdch" \
756 "|-|*)"
757#define TS_USE_DOC "'TCH/F': one FR call\n" \
758 "'TCH/H-': HR TS with first subslot used as TCH/H, other subslot unused\n" \
759 "'TCH/HH': HR TS with both subslots used as TCH/H\n" \
760 "'TCH/-H': HR TS with only second subslot used as TCH/H\n" \
761 "'PDCH': TS used for PDCH (e.g. unused dynamic TS)\n" \
762 "'tch/f': one FR call\n" \
763 "'tch/h-': HR TS with first subslot used as TCH/H, other subslot unused\n" \
764 "'tch/hh': HR TS with both subslots used as TCH/H\n" \
765 "'tch/-h': HR TS with only second subslot used as TCH/H\n" \
766 "'pdch': TS used for PDCH (e.g. unused dynamic TS)\n" \
767 "'-': TS unused\n" \
768 "'*': TS allowed to be in any state\n"
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100769
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100770DEFUN(create_n_bts, create_n_bts_cmd,
771 "create-n-bts <1-255>",
772 "Create a number of BTS with four TCH/F and four TCH/H timeslots\n"
773 "Number of BTS to create\n")
774{
775 int i;
776 int n = atoi(argv[0]);
777 for (i = 0; i < n; i++)
778 _create_bts(1, NULL, 0);
779 return CMD_SUCCESS;
780}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100781
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100782DEFUN(create_bts, create_bts_cmd,
783 "create-bts trx-count <1-255> timeslots .TS_CFG",
784 "Create a new BTS with specific timeslot configuration\n"
785 "Create N TRX in the new BTS\n"
786 "TRX count\n"
787 "Timeslot config\n"
788 "Timeslot types for 8 * trx-count, each being one of CCCH+SDCCH4|SDCCH8|TCH/F|TCH/H|TCH/F_TCH/H_PDCH|...;"
789 " shorthands: cs+4 = CCCH+SDCCH4; dyn = TCH/F_TCH/H_PDCH\n")
790{
791 int num_trx = atoi(argv[0]);
792 _create_bts(num_trx, argv + 1, argc - 1);
793 return CMD_SUCCESS;
794}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100795
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100796DEFUN(create_ms, create_ms_cmd,
797 "create-ms bts <0-999> (TCH/F|TCH/H) (AMR|HR|EFR)",
798 "Create an MS using the next free matching lchan on a given BTS\n"
799 "BTS index to subscribe on\n"
800 "lchan type to select\n"
801 "codec\n")
802{
803 const char *bts_nr_str = argv[0];
804 const char *tch_type = argv[1];
805 const char *codec = argv[2];
806 struct gsm_lchan *lchan;
807 fprintf(stderr, "- Creating mobile at BTS %s on "
808 "%s with %s codec\n", bts_nr_str, tch_type, codec);
809 lchan = create_lchan(bts_by_num_str(bts_nr_str),
810 !strcmp(tch_type, "TCH/F"), codec);
811 if (!lchan) {
812 fprintf(stderr, "Failed to create lchan!\n");
813 return CMD_WARNING;
814 }
815 fprintf(stderr, " * New MS is at %s\n", gsm_lchan_name(lchan));
816 return CMD_SUCCESS;
817}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100818
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100819DEFUN(meas_rep, meas_rep_cmd,
820 "meas-rep " LCHAN_ARGS " rxlev <0-255> rxqual <0-7> ta <0-255>"
821 " [neighbors] [<0-255>] [<0-255>] [<0-255>] [<0-255>] [<0-255>] [<0-255>]",
822 "Send measurement report\n"
823 LCHAN_ARGS_DOC
824 "rxlev\nrxlev\n"
825 "rxqual\nrxqual\n"
826 "timing advance\ntiming advance\n"
827 "neighbors list of rxlev reported by each neighbor cell\n"
828 "neighbor 0 rxlev\n"
829 "neighbor 1 rxlev\n"
830 "neighbor 2 rxlev\n"
831 "neighbor 3 rxlev\n"
832 "neighbor 4 rxlev\n"
833 "neighbor 5 rxlev\n"
834 )
835{
836 struct gsm_lchan *lc;
837 uint8_t rxlev;
838 uint8_t rxqual;
839 uint8_t ta;
840 int i;
841 struct neighbor_meas nm[6] = {};
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100842
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100843 lc = parse_lchan_args(argv);
844 argv += 4;
845 argc -= 4;
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100846
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100847 rxlev = atoi(argv[0]);
848 rxqual = atoi(argv[1]);
849 ta = atoi(argv[2]);
850 argv += 3;
851 argc -= 3;
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100852
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100853 if (!lchan_state_is(lc, LCHAN_ST_ESTABLISHED)) {
854 fprintf(stderr, "Error: sending measurement report for %s which is in state %s\n",
855 gsm_lchan_name(lc), lchan_state_name(lc));
856 exit(1);
857 }
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100858
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100859 /* skip the optional [neighbors] keyword */
860 if (argc) {
861 argv++;
862 argc--;
863 }
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100864
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100865 fprintf(stderr, "- Sending measurement report from %s: rxlev=%u rxqual=%u ta=%u (%d neighbors)\n",
866 gsm_lchan_name(lc), rxlev, rxqual, ta, argc);
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100867
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100868 for (i = 0; i < 6; i++) {
869 int neighbor_bts_nr = i;
870 /* since our bts is not in the list of neighbor cells, we need to shift */
871 if (neighbor_bts_nr >= lc->ts->trx->bts->nr)
872 neighbor_bts_nr++;
873 nm[i] = (struct neighbor_meas){
874 .rxlev = argc > i ? atoi(argv[i]) : 0,
875 .bsic = 0x3f,
876 .bcch_f = i,
877 };
878 if (i < argc)
879 fprintf(stderr, " * Neighbor cell #%d, actual BTS %d: rxlev=%d\n", i, neighbor_bts_nr,
880 nm[i].rxlev);
881 }
882 got_chan_req = 0;
883 gen_meas_rep(lc, rxlev, rxqual, ta, argc, nm);
884 return CMD_SUCCESS;
885}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100886
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100887DEFUN(congestion_check, congestion_check_cmd,
888 "congestion-check",
889 "Trigger a congestion check\n")
890{
891 fprintf(stderr, "- Triggering congestion check\n");
892 got_chan_req = 0;
893 hodec2_congestion_check(bsc_gsmnet);
894 return CMD_SUCCESS;
895}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100896
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100897DEFUN(expect_no_chan, expect_no_chan_cmd,
898 "expect-no-chan",
899 "Expect that no channel request was sent from BSC to any cell\n")
900{
901 fprintf(stderr, "- Expecting no channel request\n");
902 if (got_chan_req) {
903 fprintf(stderr, " * Got channel request at %s\n", gsm_lchan_name(chan_req_lchan));
904 fprintf(stderr, "Test failed, because channel was requested\n");
905 exit(1);
906 }
907 fprintf(stderr, " * Got no channel request\n");
908 return CMD_SUCCESS;
909}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100910
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100911static void _expect_chan_activ(struct gsm_lchan *lchan)
912{
913 fprintf(stderr, "- Expecting channel request at %s\n",
914 gsm_lchan_name(lchan));
915 if (!got_chan_req) {
916 fprintf(stderr, "Test failed, because no channel was requested\n");
917 exit(1);
918 }
919 fprintf(stderr, " * Got channel request at %s\n", gsm_lchan_name(chan_req_lchan));
920 if (lchan != chan_req_lchan) {
921 fprintf(stderr, "Test failed, because channel was requested on a different lchan than expected\n"
922 "expected: %s got: %s\n",
923 gsm_lchan_name(lchan), gsm_lchan_name(chan_req_lchan));
924 exit(1);
925 }
926}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100927
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100928static void _ack_chan_activ(struct gsm_lchan *lchan)
929{
930 fprintf(stderr, "- Acknowledging channel request on %s\n", gsm_lchan_name(lchan));
931 got_ho_req = 0;
932 send_chan_act_ack(lchan, 1);
933}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100934
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100935static void _expect_ho_req(struct gsm_lchan *lchan)
936{
937 fprintf(stderr, "- Expecting handover/assignment request at %s\n",
938 gsm_lchan_name(lchan));
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100939
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100940 if (!got_ho_req) {
941 fprintf(stderr, "Test failed, because no handover was requested\n");
942 exit(1);
943 }
944 fprintf(stderr, " * Got handover/assignment request at %s\n", gsm_lchan_name(ho_req_lchan));
945 if (ho_req_lchan != lchan) {
946 fprintf(stderr, "Test failed, because handover/assignment was not commanded on the expected lchan\n");
947 exit(1);
948 }
949}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100950
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100951DEFUN(expect_chan, expect_chan_cmd,
952 "expect-chan " LCHAN_ARGS,
953 "Expect a channel request from BSC to a cell for a specific lchan\n"
954 LCHAN_ARGS_DOC)
955{
956 _expect_chan_activ(parse_lchan_args(argv));
957 return CMD_SUCCESS;
958}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100959
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100960DEFUN(ack_chan, ack_chan_cmd,
961 "ack-chan",
962 "ACK a previous Channel Request\n")
963{
964 OSMO_ASSERT(got_chan_req);
965 _ack_chan_activ(chan_req_lchan);
966 return CMD_SUCCESS;
967}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100968
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100969DEFUN(expect_ho_req, expect_ho_req_cmd,
970 "expect-ho-req " LCHAN_ARGS,
971 "Expect a handover of a given lchan\n"
972 LCHAN_ARGS_DOC)
973{
974 _expect_ho_req(parse_lchan_args(argv));
975 return CMD_SUCCESS;
976}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100977
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100978DEFUN(ho_complete, ho_complete_cmd,
979 "ho-complete",
980 "Send Handover Complete for the most recent HO target lchan\n")
981{
982 if (!got_chan_req) {
983 fprintf(stderr, "Cannot ack handover/assignment, because no chan request\n");
984 exit(1);
985 }
986 if (!got_ho_req) {
987 fprintf(stderr, "Cannot ack handover/assignment, because no ho request\n");
988 exit(1);
989 }
990 send_ho_complete(chan_req_lchan, true);
991 lchan_release_ack(ho_req_lchan);
992 return CMD_SUCCESS;
993}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100994
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100995DEFUN(expect_ho, expect_ho_cmd,
996 "expect-ho from " LCHAN_ARGS " to " LCHAN_ARGS,
997 "Expect a handover of a specific lchan to a specific target lchan;"
998 " shorthand for expect-chan, ack-chan, expect-ho, ho-complete.\n"
999 "lchan to handover from\n" LCHAN_ARGS_DOC
1000 "lchan that to handover to\n" LCHAN_ARGS_DOC)
1001{
1002 struct gsm_lchan *from = parse_lchan_args(argv);
1003 struct gsm_lchan *to = parse_lchan_args(argv+4);
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001004
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001005 _expect_chan_activ(to);
1006 _ack_chan_activ(to);
1007 _expect_ho_req(from);
1008 send_ho_complete(to, true);
1009 lchan_release_ack(from);
1010 return CMD_SUCCESS;
1011}
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001012
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001013DEFUN(ho_failed, ho_failed_cmd,
1014 "ho-failed",
1015 "Fail the most recent handover request\n")
1016{
1017 if (!got_chan_req) {
1018 fprintf(stderr, "Cannot fail handover, because no chan request\n");
1019 exit(1);
1020 }
1021 got_chan_req = 0;
1022 got_ho_req = 0;
1023 send_ho_complete(ho_req_lchan, false);
1024 lchan_release_ack(chan_req_lchan);
1025 return CMD_SUCCESS;
1026}
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001027
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001028DEFUN(expect_ts_use, expect_ts_use_cmd,
1029 "expect-ts-use trx <0-255> <0-255> states" TS_USE TS_USE TS_USE TS_USE TS_USE TS_USE TS_USE TS_USE,
1030 "Expect timeslots of a BTS' TRX to be in a specific state\n"
1031 "Indicate a BTS and TRX\n" "BTS nr\n" "TRX nr\n"
1032 "List of 8 expected TS states\n"
1033 TS_USE_DOC TS_USE_DOC TS_USE_DOC TS_USE_DOC TS_USE_DOC TS_USE_DOC TS_USE_DOC TS_USE_DOC)
1034{
1035 struct gsm_bts *bts = bts_by_num_str(argv[0]);
1036 struct gsm_bts_trx *trx = trx_by_num_str(bts, argv[1]);
1037 argv += 2;
1038 argc -= 2;
1039 if (!_expect_ts_use(bts, trx, argv))
1040 exit(1);
1041 return CMD_SUCCESS;
1042}
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001043
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001044DEFUN(codec_f, codec_f_cmd,
1045 "codec tch/f (AMR|EFR|FR)",
1046 "Define which codec should be used for new TCH/F lchans (for set-ts-use)\n"
1047 "Configure the TCH/F codec to use\nAMR\nEFR\nFR\n")
1048{
1049 osmo_talloc_replace_string(ctx, &codec_tch_f, argv[0]);
1050 return CMD_SUCCESS;
1051}
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001052
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001053DEFUN(codec_h, codec_h_cmd,
1054 "codec tch/h (AMR|HR)",
1055 "Define which codec should be used for new TCH/H lchans (for set-ts-use)\n"
1056 "Configure the TCH/H codec to use\nAMR\nHR\n")
1057{
1058 osmo_talloc_replace_string(ctx, &codec_tch_h, argv[0]);
1059 return CMD_SUCCESS;
1060}
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001061
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001062DEFUN(set_ts_use, set_ts_use_cmd,
1063 "set-ts-use trx <0-255> <0-255> states" TS_USE TS_USE TS_USE TS_USE TS_USE TS_USE TS_USE TS_USE,
1064 "Put timeslots of a BTS' TRX into a specific state\n"
1065 "Indicate a BTS and TRX\n" "BTS nr\n" "TRX nr\n"
1066 "List of 8 TS states to apply\n"
1067 TS_USE_DOC TS_USE_DOC TS_USE_DOC TS_USE_DOC TS_USE_DOC TS_USE_DOC TS_USE_DOC TS_USE_DOC)
1068{
1069 struct gsm_bts *bts = bts_by_num_str(argv[0]);
1070 struct gsm_bts_trx *trx = trx_by_num_str(bts, argv[1]);
1071 argv += 2;
1072 argc -= 2;
1073 if (!_set_ts_use(bts, trx, argv))
1074 exit(1);
1075 if (!_expect_ts_use(bts, trx, argv))
1076 exit(1);
1077 return CMD_SUCCESS;
1078}
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001079
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001080static void ho_test_vty_init()
1081{
1082 install_element(CONFIG_NODE, &create_n_bts_cmd);
1083 install_element(CONFIG_NODE, &create_bts_cmd);
1084 install_element(CONFIG_NODE, &create_ms_cmd);
1085 install_element(CONFIG_NODE, &meas_rep_cmd);
1086 install_element(CONFIG_NODE, &congestion_check_cmd);
1087 install_element(CONFIG_NODE, &expect_no_chan_cmd);
1088 install_element(CONFIG_NODE, &expect_chan_cmd);
1089 install_element(CONFIG_NODE, &ack_chan_cmd);
1090 install_element(CONFIG_NODE, &expect_ho_req_cmd);
1091 install_element(CONFIG_NODE, &ho_complete_cmd);
1092 install_element(CONFIG_NODE, &expect_ho_cmd);
1093 install_element(CONFIG_NODE, &ho_failed_cmd);
1094 install_element(CONFIG_NODE, &expect_ts_use_cmd);
1095 install_element(CONFIG_NODE, &codec_f_cmd);
1096 install_element(CONFIG_NODE, &codec_h_cmd);
1097 install_element(CONFIG_NODE, &set_ts_use_cmd);
1098}
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001099
1100static const struct log_info_cat log_categories[] = {
1101 [DHO] = {
1102 .name = "DHO",
1103 .description = "Hand-Over Process",
1104 .color = "\033[1;38m",
1105 .enabled = 1, .loglevel = LOGL_DEBUG,
1106 },
1107 [DHODEC] = {
1108 .name = "DHODEC",
1109 .description = "Hand-Over Decision",
1110 .color = "\033[1;38m",
1111 .enabled = 1, .loglevel = LOGL_DEBUG,
1112 },
1113 [DMEAS] = {
1114 .name = "DMEAS",
1115 .description = "Radio Measurement Processing",
1116 .enabled = 1, .loglevel = LOGL_DEBUG,
1117 },
1118 [DREF] = {
1119 .name = "DREF",
1120 .description = "Reference Counting",
1121 .enabled = 1, .loglevel = LOGL_DEBUG,
1122 },
1123 [DRSL] = {
1124 .name = "DRSL",
Keithd925c7c2018-04-16 13:40:07 +02001125 .description = "A-bis Radio Signalling Link (RSL)",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001126 .color = "\033[1;35m",
1127 .enabled = 1, .loglevel = LOGL_DEBUG,
1128 },
Neels Hofmeyr31f525e2018-05-14 18:14:15 +02001129 [DRR] = {
1130 .name = "DRR",
1131 .description = "RR",
1132 .color = "\033[1;35m",
1133 .enabled = 1, .loglevel = LOGL_DEBUG,
1134 },
1135 [DRLL] = {
1136 .name = "DRLL",
1137 .description = "RLL",
1138 .color = "\033[1;35m",
1139 .enabled = 1, .loglevel = LOGL_DEBUG,
1140 },
Harald Welte3561bd42018-01-28 03:04:16 +01001141 [DMSC] = {
1142 .name = "DMSC",
1143 .description = "Mobile Switching Center",
1144 .enabled = 1, .loglevel = LOGL_DEBUG,
1145 },
Neels Hofmeyr3c5612f2018-07-11 19:53:39 +02001146 [DCHAN] = {
1147 .name = "DCHAN",
1148 .description = "lchan FSM",
1149 .color = "\033[1;32m",
1150 .enabled = 1, .loglevel = LOGL_DEBUG,
1151 },
1152 [DTS] = {
1153 .name = "DTS",
1154 .description = "timeslot FSM",
1155 .color = "\033[1;31m",
1156 .enabled = 1, .loglevel = LOGL_DEBUG,
1157 },
1158 [DAS] = {
1159 .name = "DAS",
1160 .description = "assignment FSM",
1161 .color = "\033[1;33m",
1162 .enabled = 1, .loglevel = LOGL_DEBUG,
1163 },
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001164};
1165
1166const struct log_info log_info = {
1167 .cat = log_categories,
1168 .num_cat = ARRAY_SIZE(log_categories),
1169};
1170
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001171static struct vty_app_info vty_info = {
1172 .name = "ho_test",
1173 .copyright =
1174 "Copyright (C) 2020 sysmocom - s.f.m.c. GmbH\r\n"
1175 "License AGPLv3+: GNU AGPL version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n"
1176 "This is free software: you are free to change and redistribute it.\r\n"
1177 "There is NO WARRANTY, to the extent permitted by law.\r\n",
1178 .version = PACKAGE_VERSION,
1179 .usr_attr_desc = {
1180 [BSC_VTY_ATTR_RESTART_ABIS_OML_LINK] = \
1181 "This command applies on A-bis OML link (re)establishment",
1182 [BSC_VTY_ATTR_RESTART_ABIS_RSL_LINK] = \
1183 "This command applies on A-bis RSL link (re)establishment",
1184 [BSC_VTY_ATTR_NEW_LCHAN] = \
1185 "This command applies for newly created lchans",
1186 },
1187 .usr_attr_letters = {
1188 [BSC_VTY_ATTR_RESTART_ABIS_OML_LINK] = 'o',
1189 [BSC_VTY_ATTR_RESTART_ABIS_RSL_LINK] = 'r',
1190 [BSC_VTY_ATTR_NEW_LCHAN] = 'l',
1191 },
1192};
Neels Hofmeyrb5a107d2020-11-12 23:00:08 +01001193
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001194int main(int argc, char **argv)
1195{
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001196 char *test_file = NULL;
1197 int rc;
1198
1199 if (argc < 2) {
1200 fprintf(stderr, "Pass a handover test script as argument\n");
1201 exit(1);
1202 }
1203 test_file = argv[1];
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001204
Neels Hofmeyre3416182018-03-05 05:31:14 +01001205 ctx = talloc_named_const(NULL, 0, "handover_test");
1206 msgb_talloc_ctx_init(ctx, 0);
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001207 vty_info.tall_ctx = ctx;
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001208
Neels Hofmeyre3416182018-03-05 05:31:14 +01001209 osmo_init_logging2(ctx, &log_info);
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001210
1211 log_set_print_category(osmo_stderr_target, 1);
1212 log_set_print_category_hex(osmo_stderr_target, 0);
1213 log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_BASENAME);
Neels Hofmeyr31f525e2018-05-14 18:14:15 +02001214 osmo_fsm_log_addr(false);
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001215
Neels Hofmeyr958f2592018-05-27 01:26:31 +02001216 bsc_network_alloc();
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001217 if (!bsc_gsmnet)
1218 exit(1);
1219
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001220 vty_init(&vty_info);
1221 bsc_vty_init(bsc_gsmnet);
1222 ho_test_vty_init();
1223
Neels Hofmeyr31f525e2018-05-14 18:14:15 +02001224 ts_fsm_init();
1225 lchan_fsm_init();
Neels Hofmeyr31f525e2018-05-14 18:14:15 +02001226 bsc_subscr_conn_fsm_init();
1227 handover_fsm_init();
1228
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001229 ho_set_algorithm(bsc_gsmnet->ho, 2);
1230 ho_set_ho_active(bsc_gsmnet->ho, true);
1231 ho_set_hodec2_as_active(bsc_gsmnet->ho, true);
1232 ho_set_hodec2_min_rxlev(bsc_gsmnet->ho, -100);
1233 ho_set_hodec2_rxlev_avg_win(bsc_gsmnet->ho, 1);
1234 ho_set_hodec2_rxlev_neigh_avg_win(bsc_gsmnet->ho, 1);
1235 ho_set_hodec2_rxqual_avg_win(bsc_gsmnet->ho, 10);
1236 ho_set_hodec2_pwr_hysteresis(bsc_gsmnet->ho, 3);
1237 ho_set_hodec2_pwr_interval(bsc_gsmnet->ho, 1);
1238 ho_set_hodec2_afs_bias_rxlev(bsc_gsmnet->ho, 0);
1239 ho_set_hodec2_min_rxqual(bsc_gsmnet->ho, 5);
1240 ho_set_hodec2_afs_bias_rxqual(bsc_gsmnet->ho, 0);
1241 ho_set_hodec2_max_distance(bsc_gsmnet->ho, 9999);
1242 ho_set_hodec2_ho_max(bsc_gsmnet->ho, 9999);
1243 ho_set_hodec2_penalty_max_dist(bsc_gsmnet->ho, 300);
1244 ho_set_hodec2_penalty_failed_ho(bsc_gsmnet->ho, 60);
1245 ho_set_hodec2_penalty_failed_as(bsc_gsmnet->ho, 60);
1246
Vadim Yanitskiy4f3a6412020-05-31 01:56:20 +07001247 /* We don't really need any specific model here */
1248 bts_model_unknown_init();
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001249
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001250 /* Disable the congestion check timer, we will trigger manually. */
1251 bsc_gsmnet->hodec2.congestion_check_interval_s = 0;
1252
1253 handover_decision_1_init();
1254 hodec2_init(bsc_gsmnet);
1255
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001256 rc = vty_read_config_file(test_file, NULL);
1257 if (rc < 0) {
1258 fprintf(stderr, "Failed to parse the test file: '%s'\n", test_file);
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001259 }
1260
Neels Hofmeyre3416182018-03-05 05:31:14 +01001261 talloc_free(ctx);
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001262 fprintf(stderr,"-------------------\n");
1263 if (!rc)
1264 fprintf(stderr, "pass\n");
1265 else
1266 fprintf(stderr, "FAIL\n");
1267 return rc;
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001268}
1269
1270void rtp_socket_free() {}
1271void rtp_send_frame() {}
1272void rtp_socket_upstream() {}
1273void rtp_socket_create() {}
1274void rtp_socket_connect() {}
1275void rtp_socket_proxy() {}
1276void trau_mux_unmap() {}
1277void trau_mux_map_lchan() {}
1278void trau_recv_lchan() {}
1279void trau_send_frame() {}
Harald Welte3561bd42018-01-28 03:04:16 +01001280int osmo_bsc_sigtran_send(struct gsm_subscriber_connection *conn, struct msgb *msg) { return 0; }
1281int osmo_bsc_sigtran_open_conn(struct gsm_subscriber_connection *conn, struct msgb *msg) { return 0; }
Vadim Yanitskiy6a26e2c2020-08-26 18:49:08 +07001282void bsc_sapi_n_reject(struct gsm_subscriber_connection *conn, uint8_t dlci, enum gsm0808_cause cause) {}
Neels Hofmeyrc19581f2018-05-27 03:05:18 +02001283void bsc_cipher_mode_compl(struct gsm_subscriber_connection *conn, struct msgb *msg, uint8_t chosen_encr) {}
Neels Hofmeyr2001dd62020-09-11 23:35:28 +00001284int bsc_compl_l3(struct gsm_lchan *lchan, struct msgb *msg, uint16_t chosen_channel)
Neels Hofmeyrc19581f2018-05-27 03:05:18 +02001285{ return 0; }
Neels Hofmeyr86ce1052020-09-18 02:49:32 +02001286int bsc_paging_start(struct bsc_paging_params *params)
1287{ return 0; }
Neels Hofmeyrc19581f2018-05-27 03:05:18 +02001288void bsc_dtap(struct gsm_subscriber_connection *conn, uint8_t link_id, struct msgb *msg) {}
1289void bsc_assign_compl(struct gsm_subscriber_connection *conn, uint8_t rr_cause) {}
Neels Hofmeyrc19581f2018-05-27 03:05:18 +02001290void bsc_cm_update(struct gsm_subscriber_connection *conn,
1291 const uint8_t *cm2, uint8_t cm2_len,
1292 const uint8_t *cm3, uint8_t cm3_len) {}
Neels Hofmeyr31f525e2018-05-14 18:14:15 +02001293struct gsm0808_handover_required;
1294int bsc_tx_bssmap_ho_required(struct gsm_lchan *lchan, const struct gsm0808_cell_id_list2 *target_cells)
1295{ return 0; }
1296int bsc_tx_bssmap_ho_request_ack(struct gsm_subscriber_connection *conn, struct msgb *rr_ho_command)
1297{ return 0; }
1298int bsc_tx_bssmap_ho_detect(struct gsm_subscriber_connection *conn) { return 0; }
1299enum handover_result bsc_tx_bssmap_ho_complete(struct gsm_subscriber_connection *conn,
1300 struct gsm_lchan *lchan) { return HO_RESULT_OK; }
1301void bsc_tx_bssmap_ho_failure(struct gsm_subscriber_connection *conn) {}
Neels Hofmeyrc27ae2d2020-10-04 21:32:52 +02001302void osmo_bsc_sigtran_tx_reset(void) {}
Neels Hofmeyre95b92b2020-10-09 17:18:29 +02001303void osmo_bsc_sigtran_tx_reset_ack(void) {}
Neels Hofmeyrc27ae2d2020-10-04 21:32:52 +02001304void osmo_bsc_sigtran_reset(void) {}
1305void bssmap_reset_alloc(void) {}
1306void bssmap_reset_is_conn_ready(void) {}