blob: 33e5ff0a9ae4dbbf9219c5122ee446bd3979d2ae [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 Hofmeyr909e9722017-12-07 03:54:01 +0100621 rh = (struct abis_rsl_rll_hdr *) msgb_put(msg, sizeof(*rh));
622 rh->c.msg_discr = ABIS_RSL_MDISC_RLL;
623 rh->c.msg_type = RSL_MT_DATA_IND;
624 rh->ie_chan = RSL_IE_CHAN_NR;
625 rh->chan_nr = chan_nr;
626 rh->ie_link_id = RSL_IE_LINK_IDENT;
627 rh->link_id = 0x00;
628
629 buf = msgb_put(msg, 3);
630 buf[0] = RSL_IE_L3_INFO;
631 buf[1] = (sizeof(*gh) + sizeof(*hc)) >> 8;
632 buf[2] = (sizeof(*gh) + sizeof(*hc)) & 0xff;
633
634 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
635 hc = (struct gsm48_ho_cpl *) msgb_put(msg, sizeof(*hc));
636
637 gh->proto_discr = GSM48_PDISC_RR;
638 gh->msg_type =
639 success ? GSM48_MT_RR_HANDO_COMPL : GSM48_MT_RR_HANDO_FAIL;
640
641 msg->dst = lchan->ts->trx->bts->c0->rsl_link;
642 msg->l2h = (unsigned char *)rh;
643 msg->l3h = (unsigned char *)gh;
644
645 abis_rsl_rcvmsg(msg);
646}
647
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100648static void lchan_release_ack(struct gsm_lchan *lchan)
649{
650 if (lchan->fi && lchan->fi->state == LCHAN_ST_WAIT_BEFORE_RF_RELEASE) {
651 /* don't wait before release */
652 osmo_fsm_inst_state_chg(lchan->fi, LCHAN_ST_WAIT_RF_RELEASE_ACK, 0, 0);
653 /* ack the release */
654 osmo_fsm_inst_dispatch(lchan->fi, LCHAN_EV_RSL_RF_CHAN_REL_ACK, 0);
655 }
656}
657
Neels Hofmeyr1d7473c2018-03-05 21:53:18 +0100658/* override, requires '-Wl,--wrap=abis_rsl_sendmsg'.
659 * Catch RSL messages sent towards the BTS. */
660int __real_abis_rsl_sendmsg(struct msgb *msg);
661int __wrap_abis_rsl_sendmsg(struct msgb *msg)
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100662{
663 struct abis_rsl_dchan_hdr *dh = (struct abis_rsl_dchan_hdr *) msg->data;
664 struct e1inp_sign_link *sign_link = msg->dst;
665 int rc;
666 struct gsm_lchan *lchan = rsl_lchan_lookup(sign_link->trx, dh->chan_nr, &rc);
Neels Hofmeyrfb6d9dc2020-11-13 01:13:20 +0100667 struct gsm_lchan *other_lchan;
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100668
669 if (rc) {
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100670 fprintf(stderr, "rsl_lchan_lookup() failed\n");
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100671 exit(1);
672 }
673
674 switch (dh->c.msg_type) {
675 case RSL_MT_CHAN_ACTIV:
676 rc = parse_chan_act(lchan, dh->data);
677 if (rc == 0)
678 got_chan_req = 1;
679 break;
680 case RSL_MT_RF_CHAN_REL:
681 rc = parse_chan_rel(lchan, dh->data);
682 if (rc == 0)
683 send_chan_act_ack(chan_req_lchan, 0);
Neels Hofmeyrfb6d9dc2020-11-13 01:13:20 +0100684
685 /* send dyn TS back to PDCH if unused */
686 switch (chan_req_lchan->ts->pchan_on_init) {
687 case GSM_PCHAN_TCH_F_TCH_H_PDCH:
688 case GSM_PCHAN_TCH_F_PDCH:
689 switch (chan_req_lchan->ts->pchan_is) {
690 case GSM_PCHAN_TCH_H:
691 other_lchan = &chan_req_lchan->ts->lchan[
692 (chan_req_lchan == &chan_req_lchan->ts->lchan[0])?
693 1 : 0];
694 if (lchan_state_is(other_lchan, LCHAN_ST_ESTABLISHED))
695 break;
696 /* else fall thru */
697 case GSM_PCHAN_TCH_F:
698 chan_req_lchan->ts->pchan_is = GSM_PCHAN_PDCH;
699 break;
700 default:
701 break;
702 }
703 break;
704 default:
705 break;
706 }
707
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100708 break;
709 case RSL_MT_DATA_REQ:
710 rc = parse_ho_command(lchan, msg->l3h, msgb_l3len(msg));
711 if (rc == 0)
712 got_ho_req = 1;
713 break;
714 case RSL_MT_IPAC_CRCX:
715 break;
Neels Hofmeyr5b1a7d12018-11-06 22:24:07 +0100716 case RSL_MT_DEACTIVATE_SACCH:
717 break;
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100718 default:
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100719 fprintf(stderr, "unknown rsl message=0x%x\n", dh->c.msg_type);
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100720 }
721 return 0;
722}
723
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100724struct gsm_bts *bts_by_num_str(const char *num_str)
725{
726 struct gsm_bts *bts = gsm_bts_num(bsc_gsmnet, atoi(num_str));
727 OSMO_ASSERT(bts);
728 return bts;
729}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100730
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100731struct gsm_bts_trx *trx_by_num_str(struct gsm_bts *bts, const char *num_str)
732{
733 struct gsm_bts_trx *trx = gsm_bts_trx_num(bts, atoi(num_str));
734 OSMO_ASSERT(trx);
735 return trx;
736}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100737
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100738#define LCHAN_ARGS "lchan <0-255> <0-255> <0-7> <0-7>"
739#define LCHAN_ARGS_DOC "identify an lchan\nBTS nr\nTRX nr\nTimeslot nr\nSubslot nr\n"
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100740
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100741static struct gsm_lchan *parse_lchan_args(const char **argv)
742{
743 struct gsm_bts *bts = bts_by_num_str(argv[0]);
744 struct gsm_bts_trx *trx = trx_by_num_str(bts, argv[1]);
745 struct gsm_bts_trx_ts *ts = &trx->ts[atoi(argv[2])];
746 return &ts->lchan[atoi(argv[3])];
747}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100748
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100749#define TS_USE " (TCH/F|TCH/H-|TCH/-H|TCH/HH|PDCH" \
750 "|tch/f|tch/h-|tch/-h|tch/hh|pdch" \
751 "|-|*)"
752#define TS_USE_DOC "'TCH/F': one FR call\n" \
753 "'TCH/H-': HR TS with first subslot used as TCH/H, other subslot unused\n" \
754 "'TCH/HH': HR TS with both subslots used as TCH/H\n" \
755 "'TCH/-H': HR TS with only second subslot used as TCH/H\n" \
756 "'PDCH': TS used for PDCH (e.g. unused dynamic TS)\n" \
757 "'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 "'-': TS unused\n" \
763 "'*': TS allowed to be in any state\n"
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100764
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100765DEFUN(create_n_bts, create_n_bts_cmd,
766 "create-n-bts <1-255>",
767 "Create a number of BTS with four TCH/F and four TCH/H timeslots\n"
768 "Number of BTS to create\n")
769{
770 int i;
771 int n = atoi(argv[0]);
772 for (i = 0; i < n; i++)
773 _create_bts(1, NULL, 0);
774 return CMD_SUCCESS;
775}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100776
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100777DEFUN(create_bts, create_bts_cmd,
778 "create-bts trx-count <1-255> timeslots .TS_CFG",
779 "Create a new BTS with specific timeslot configuration\n"
780 "Create N TRX in the new BTS\n"
781 "TRX count\n"
782 "Timeslot config\n"
783 "Timeslot types for 8 * trx-count, each being one of CCCH+SDCCH4|SDCCH8|TCH/F|TCH/H|TCH/F_TCH/H_PDCH|...;"
784 " shorthands: cs+4 = CCCH+SDCCH4; dyn = TCH/F_TCH/H_PDCH\n")
785{
786 int num_trx = atoi(argv[0]);
787 _create_bts(num_trx, argv + 1, argc - 1);
788 return CMD_SUCCESS;
789}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100790
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100791DEFUN(create_ms, create_ms_cmd,
792 "create-ms bts <0-999> (TCH/F|TCH/H) (AMR|HR|EFR)",
793 "Create an MS using the next free matching lchan on a given BTS\n"
794 "BTS index to subscribe on\n"
795 "lchan type to select\n"
796 "codec\n")
797{
798 const char *bts_nr_str = argv[0];
799 const char *tch_type = argv[1];
800 const char *codec = argv[2];
801 struct gsm_lchan *lchan;
802 fprintf(stderr, "- Creating mobile at BTS %s on "
803 "%s with %s codec\n", bts_nr_str, tch_type, codec);
804 lchan = create_lchan(bts_by_num_str(bts_nr_str),
805 !strcmp(tch_type, "TCH/F"), codec);
806 if (!lchan) {
807 fprintf(stderr, "Failed to create lchan!\n");
808 return CMD_WARNING;
809 }
810 fprintf(stderr, " * New MS is at %s\n", gsm_lchan_name(lchan));
811 return CMD_SUCCESS;
812}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100813
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100814DEFUN(meas_rep, meas_rep_cmd,
815 "meas-rep " LCHAN_ARGS " rxlev <0-255> rxqual <0-7> ta <0-255>"
816 " [neighbors] [<0-255>] [<0-255>] [<0-255>] [<0-255>] [<0-255>] [<0-255>]",
817 "Send measurement report\n"
818 LCHAN_ARGS_DOC
819 "rxlev\nrxlev\n"
820 "rxqual\nrxqual\n"
821 "timing advance\ntiming advance\n"
822 "neighbors list of rxlev reported by each neighbor cell\n"
823 "neighbor 0 rxlev\n"
824 "neighbor 1 rxlev\n"
825 "neighbor 2 rxlev\n"
826 "neighbor 3 rxlev\n"
827 "neighbor 4 rxlev\n"
828 "neighbor 5 rxlev\n"
829 )
830{
831 struct gsm_lchan *lc;
832 uint8_t rxlev;
833 uint8_t rxqual;
834 uint8_t ta;
835 int i;
836 struct neighbor_meas nm[6] = {};
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100837
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100838 lc = parse_lchan_args(argv);
839 argv += 4;
840 argc -= 4;
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100841
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100842 rxlev = atoi(argv[0]);
843 rxqual = atoi(argv[1]);
844 ta = atoi(argv[2]);
845 argv += 3;
846 argc -= 3;
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100847
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100848 if (!lchan_state_is(lc, LCHAN_ST_ESTABLISHED)) {
849 fprintf(stderr, "Error: sending measurement report for %s which is in state %s\n",
850 gsm_lchan_name(lc), lchan_state_name(lc));
851 exit(1);
852 }
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100853
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100854 /* skip the optional [neighbors] keyword */
855 if (argc) {
856 argv++;
857 argc--;
858 }
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100859
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100860 fprintf(stderr, "- Sending measurement report from %s: rxlev=%u rxqual=%u ta=%u (%d neighbors)\n",
861 gsm_lchan_name(lc), rxlev, rxqual, ta, argc);
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100862
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100863 for (i = 0; i < 6; i++) {
864 int neighbor_bts_nr = i;
865 /* since our bts is not in the list of neighbor cells, we need to shift */
866 if (neighbor_bts_nr >= lc->ts->trx->bts->nr)
867 neighbor_bts_nr++;
868 nm[i] = (struct neighbor_meas){
869 .rxlev = argc > i ? atoi(argv[i]) : 0,
870 .bsic = 0x3f,
871 .bcch_f = i,
872 };
873 if (i < argc)
874 fprintf(stderr, " * Neighbor cell #%d, actual BTS %d: rxlev=%d\n", i, neighbor_bts_nr,
875 nm[i].rxlev);
876 }
877 got_chan_req = 0;
878 gen_meas_rep(lc, rxlev, rxqual, ta, argc, nm);
879 return CMD_SUCCESS;
880}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100881
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100882DEFUN(congestion_check, congestion_check_cmd,
883 "congestion-check",
884 "Trigger a congestion check\n")
885{
886 fprintf(stderr, "- Triggering congestion check\n");
887 got_chan_req = 0;
888 hodec2_congestion_check(bsc_gsmnet);
889 return CMD_SUCCESS;
890}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100891
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100892DEFUN(expect_no_chan, expect_no_chan_cmd,
893 "expect-no-chan",
894 "Expect that no channel request was sent from BSC to any cell\n")
895{
896 fprintf(stderr, "- Expecting no channel request\n");
897 if (got_chan_req) {
898 fprintf(stderr, " * Got channel request at %s\n", gsm_lchan_name(chan_req_lchan));
899 fprintf(stderr, "Test failed, because channel was requested\n");
900 exit(1);
901 }
902 fprintf(stderr, " * Got no channel request\n");
903 return CMD_SUCCESS;
904}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100905
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100906static void _expect_chan_activ(struct gsm_lchan *lchan)
907{
908 fprintf(stderr, "- Expecting channel request at %s\n",
909 gsm_lchan_name(lchan));
910 if (!got_chan_req) {
911 fprintf(stderr, "Test failed, because no channel was requested\n");
912 exit(1);
913 }
914 fprintf(stderr, " * Got channel request at %s\n", gsm_lchan_name(chan_req_lchan));
915 if (lchan != chan_req_lchan) {
916 fprintf(stderr, "Test failed, because channel was requested on a different lchan than expected\n"
917 "expected: %s got: %s\n",
918 gsm_lchan_name(lchan), gsm_lchan_name(chan_req_lchan));
919 exit(1);
920 }
921}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100922
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100923static void _ack_chan_activ(struct gsm_lchan *lchan)
924{
925 fprintf(stderr, "- Acknowledging channel request on %s\n", gsm_lchan_name(lchan));
926 got_ho_req = 0;
927 send_chan_act_ack(lchan, 1);
928}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100929
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100930static void _expect_ho_req(struct gsm_lchan *lchan)
931{
932 fprintf(stderr, "- Expecting handover/assignment request at %s\n",
933 gsm_lchan_name(lchan));
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100934
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100935 if (!got_ho_req) {
936 fprintf(stderr, "Test failed, because no handover was requested\n");
937 exit(1);
938 }
939 fprintf(stderr, " * Got handover/assignment request at %s\n", gsm_lchan_name(ho_req_lchan));
940 if (ho_req_lchan != lchan) {
941 fprintf(stderr, "Test failed, because handover/assignment was not commanded on the expected lchan\n");
942 exit(1);
943 }
944}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100945
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100946DEFUN(expect_chan, expect_chan_cmd,
947 "expect-chan " LCHAN_ARGS,
948 "Expect a channel request from BSC to a cell for a specific lchan\n"
949 LCHAN_ARGS_DOC)
950{
951 _expect_chan_activ(parse_lchan_args(argv));
952 return CMD_SUCCESS;
953}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100954
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100955DEFUN(ack_chan, ack_chan_cmd,
956 "ack-chan",
957 "ACK a previous Channel Request\n")
958{
959 OSMO_ASSERT(got_chan_req);
960 _ack_chan_activ(chan_req_lchan);
961 return CMD_SUCCESS;
962}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100963
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100964DEFUN(expect_ho_req, expect_ho_req_cmd,
965 "expect-ho-req " LCHAN_ARGS,
966 "Expect a handover of a given lchan\n"
967 LCHAN_ARGS_DOC)
968{
969 _expect_ho_req(parse_lchan_args(argv));
970 return CMD_SUCCESS;
971}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100972
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100973DEFUN(ho_complete, ho_complete_cmd,
974 "ho-complete",
975 "Send Handover Complete for the most recent HO target lchan\n")
976{
977 if (!got_chan_req) {
978 fprintf(stderr, "Cannot ack handover/assignment, because no chan request\n");
979 exit(1);
980 }
981 if (!got_ho_req) {
982 fprintf(stderr, "Cannot ack handover/assignment, because no ho request\n");
983 exit(1);
984 }
985 send_ho_complete(chan_req_lchan, true);
986 lchan_release_ack(ho_req_lchan);
987 return CMD_SUCCESS;
988}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100989
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100990DEFUN(expect_ho, expect_ho_cmd,
991 "expect-ho from " LCHAN_ARGS " to " LCHAN_ARGS,
992 "Expect a handover of a specific lchan to a specific target lchan;"
993 " shorthand for expect-chan, ack-chan, expect-ho, ho-complete.\n"
994 "lchan to handover from\n" LCHAN_ARGS_DOC
995 "lchan that to handover to\n" LCHAN_ARGS_DOC)
996{
997 struct gsm_lchan *from = parse_lchan_args(argv);
998 struct gsm_lchan *to = parse_lchan_args(argv+4);
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100999
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001000 _expect_chan_activ(to);
1001 _ack_chan_activ(to);
1002 _expect_ho_req(from);
1003 send_ho_complete(to, true);
1004 lchan_release_ack(from);
1005 return CMD_SUCCESS;
1006}
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001007
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001008DEFUN(ho_failed, ho_failed_cmd,
1009 "ho-failed",
1010 "Fail the most recent handover request\n")
1011{
1012 if (!got_chan_req) {
1013 fprintf(stderr, "Cannot fail handover, because no chan request\n");
1014 exit(1);
1015 }
1016 got_chan_req = 0;
1017 got_ho_req = 0;
1018 send_ho_complete(ho_req_lchan, false);
1019 lchan_release_ack(chan_req_lchan);
1020 return CMD_SUCCESS;
1021}
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001022
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001023DEFUN(expect_ts_use, expect_ts_use_cmd,
1024 "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,
1025 "Expect timeslots of a BTS' TRX to be in a specific state\n"
1026 "Indicate a BTS and TRX\n" "BTS nr\n" "TRX nr\n"
1027 "List of 8 expected TS states\n"
1028 TS_USE_DOC TS_USE_DOC TS_USE_DOC TS_USE_DOC TS_USE_DOC TS_USE_DOC TS_USE_DOC TS_USE_DOC)
1029{
1030 struct gsm_bts *bts = bts_by_num_str(argv[0]);
1031 struct gsm_bts_trx *trx = trx_by_num_str(bts, argv[1]);
1032 argv += 2;
1033 argc -= 2;
1034 if (!_expect_ts_use(bts, trx, argv))
1035 exit(1);
1036 return CMD_SUCCESS;
1037}
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001038
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001039DEFUN(codec_f, codec_f_cmd,
1040 "codec tch/f (AMR|EFR|FR)",
1041 "Define which codec should be used for new TCH/F lchans (for set-ts-use)\n"
1042 "Configure the TCH/F codec to use\nAMR\nEFR\nFR\n")
1043{
1044 osmo_talloc_replace_string(ctx, &codec_tch_f, argv[0]);
1045 return CMD_SUCCESS;
1046}
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001047
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001048DEFUN(codec_h, codec_h_cmd,
1049 "codec tch/h (AMR|HR)",
1050 "Define which codec should be used for new TCH/H lchans (for set-ts-use)\n"
1051 "Configure the TCH/H codec to use\nAMR\nHR\n")
1052{
1053 osmo_talloc_replace_string(ctx, &codec_tch_h, argv[0]);
1054 return CMD_SUCCESS;
1055}
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001056
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001057DEFUN(set_ts_use, set_ts_use_cmd,
1058 "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,
1059 "Put timeslots of a BTS' TRX into a specific state\n"
1060 "Indicate a BTS and TRX\n" "BTS nr\n" "TRX nr\n"
1061 "List of 8 TS states to apply\n"
1062 TS_USE_DOC TS_USE_DOC TS_USE_DOC TS_USE_DOC TS_USE_DOC TS_USE_DOC TS_USE_DOC TS_USE_DOC)
1063{
1064 struct gsm_bts *bts = bts_by_num_str(argv[0]);
1065 struct gsm_bts_trx *trx = trx_by_num_str(bts, argv[1]);
1066 argv += 2;
1067 argc -= 2;
1068 if (!_set_ts_use(bts, trx, argv))
1069 exit(1);
1070 if (!_expect_ts_use(bts, trx, argv))
1071 exit(1);
1072 return CMD_SUCCESS;
1073}
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001074
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001075static void ho_test_vty_init()
1076{
1077 install_element(CONFIG_NODE, &create_n_bts_cmd);
1078 install_element(CONFIG_NODE, &create_bts_cmd);
1079 install_element(CONFIG_NODE, &create_ms_cmd);
1080 install_element(CONFIG_NODE, &meas_rep_cmd);
1081 install_element(CONFIG_NODE, &congestion_check_cmd);
1082 install_element(CONFIG_NODE, &expect_no_chan_cmd);
1083 install_element(CONFIG_NODE, &expect_chan_cmd);
1084 install_element(CONFIG_NODE, &ack_chan_cmd);
1085 install_element(CONFIG_NODE, &expect_ho_req_cmd);
1086 install_element(CONFIG_NODE, &ho_complete_cmd);
1087 install_element(CONFIG_NODE, &expect_ho_cmd);
1088 install_element(CONFIG_NODE, &ho_failed_cmd);
1089 install_element(CONFIG_NODE, &expect_ts_use_cmd);
1090 install_element(CONFIG_NODE, &codec_f_cmd);
1091 install_element(CONFIG_NODE, &codec_h_cmd);
1092 install_element(CONFIG_NODE, &set_ts_use_cmd);
1093}
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001094
1095static const struct log_info_cat log_categories[] = {
1096 [DHO] = {
1097 .name = "DHO",
1098 .description = "Hand-Over Process",
1099 .color = "\033[1;38m",
1100 .enabled = 1, .loglevel = LOGL_DEBUG,
1101 },
1102 [DHODEC] = {
1103 .name = "DHODEC",
1104 .description = "Hand-Over Decision",
1105 .color = "\033[1;38m",
1106 .enabled = 1, .loglevel = LOGL_DEBUG,
1107 },
1108 [DMEAS] = {
1109 .name = "DMEAS",
1110 .description = "Radio Measurement Processing",
1111 .enabled = 1, .loglevel = LOGL_DEBUG,
1112 },
1113 [DREF] = {
1114 .name = "DREF",
1115 .description = "Reference Counting",
1116 .enabled = 1, .loglevel = LOGL_DEBUG,
1117 },
1118 [DRSL] = {
1119 .name = "DRSL",
Keithd925c7c2018-04-16 13:40:07 +02001120 .description = "A-bis Radio Signalling Link (RSL)",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001121 .color = "\033[1;35m",
1122 .enabled = 1, .loglevel = LOGL_DEBUG,
1123 },
Neels Hofmeyr31f525e2018-05-14 18:14:15 +02001124 [DRR] = {
1125 .name = "DRR",
1126 .description = "RR",
1127 .color = "\033[1;35m",
1128 .enabled = 1, .loglevel = LOGL_DEBUG,
1129 },
1130 [DRLL] = {
1131 .name = "DRLL",
1132 .description = "RLL",
1133 .color = "\033[1;35m",
1134 .enabled = 1, .loglevel = LOGL_DEBUG,
1135 },
Harald Welte3561bd42018-01-28 03:04:16 +01001136 [DMSC] = {
1137 .name = "DMSC",
1138 .description = "Mobile Switching Center",
1139 .enabled = 1, .loglevel = LOGL_DEBUG,
1140 },
Neels Hofmeyr3c5612f2018-07-11 19:53:39 +02001141 [DCHAN] = {
1142 .name = "DCHAN",
1143 .description = "lchan FSM",
1144 .color = "\033[1;32m",
1145 .enabled = 1, .loglevel = LOGL_DEBUG,
1146 },
1147 [DTS] = {
1148 .name = "DTS",
1149 .description = "timeslot FSM",
1150 .color = "\033[1;31m",
1151 .enabled = 1, .loglevel = LOGL_DEBUG,
1152 },
1153 [DAS] = {
1154 .name = "DAS",
1155 .description = "assignment FSM",
1156 .color = "\033[1;33m",
1157 .enabled = 1, .loglevel = LOGL_DEBUG,
1158 },
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001159};
1160
1161const struct log_info log_info = {
1162 .cat = log_categories,
1163 .num_cat = ARRAY_SIZE(log_categories),
1164};
1165
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001166static struct vty_app_info vty_info = {
1167 .name = "ho_test",
1168 .copyright =
1169 "Copyright (C) 2020 sysmocom - s.f.m.c. GmbH\r\n"
1170 "License AGPLv3+: GNU AGPL version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n"
1171 "This is free software: you are free to change and redistribute it.\r\n"
1172 "There is NO WARRANTY, to the extent permitted by law.\r\n",
1173 .version = PACKAGE_VERSION,
1174 .usr_attr_desc = {
1175 [BSC_VTY_ATTR_RESTART_ABIS_OML_LINK] = \
1176 "This command applies on A-bis OML link (re)establishment",
1177 [BSC_VTY_ATTR_RESTART_ABIS_RSL_LINK] = \
1178 "This command applies on A-bis RSL link (re)establishment",
1179 [BSC_VTY_ATTR_NEW_LCHAN] = \
1180 "This command applies for newly created lchans",
1181 },
1182 .usr_attr_letters = {
1183 [BSC_VTY_ATTR_RESTART_ABIS_OML_LINK] = 'o',
1184 [BSC_VTY_ATTR_RESTART_ABIS_RSL_LINK] = 'r',
1185 [BSC_VTY_ATTR_NEW_LCHAN] = 'l',
1186 },
1187};
Neels Hofmeyrb5a107d2020-11-12 23:00:08 +01001188
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001189int main(int argc, char **argv)
1190{
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001191 char *test_file = NULL;
1192 int rc;
1193
1194 if (argc < 2) {
1195 fprintf(stderr, "Pass a handover test script as argument\n");
1196 exit(1);
1197 }
1198 test_file = argv[1];
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001199
Neels Hofmeyre3416182018-03-05 05:31:14 +01001200 ctx = talloc_named_const(NULL, 0, "handover_test");
1201 msgb_talloc_ctx_init(ctx, 0);
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001202 vty_info.tall_ctx = ctx;
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001203
Neels Hofmeyre3416182018-03-05 05:31:14 +01001204 osmo_init_logging2(ctx, &log_info);
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001205
1206 log_set_print_category(osmo_stderr_target, 1);
1207 log_set_print_category_hex(osmo_stderr_target, 0);
1208 log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_BASENAME);
Neels Hofmeyr31f525e2018-05-14 18:14:15 +02001209 osmo_fsm_log_addr(false);
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001210
Neels Hofmeyr958f2592018-05-27 01:26:31 +02001211 bsc_network_alloc();
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001212 if (!bsc_gsmnet)
1213 exit(1);
1214
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001215 vty_init(&vty_info);
1216 bsc_vty_init(bsc_gsmnet);
1217 ho_test_vty_init();
1218
Neels Hofmeyr31f525e2018-05-14 18:14:15 +02001219 ts_fsm_init();
1220 lchan_fsm_init();
Neels Hofmeyr31f525e2018-05-14 18:14:15 +02001221 bsc_subscr_conn_fsm_init();
1222 handover_fsm_init();
1223
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001224 ho_set_algorithm(bsc_gsmnet->ho, 2);
1225 ho_set_ho_active(bsc_gsmnet->ho, true);
1226 ho_set_hodec2_as_active(bsc_gsmnet->ho, true);
1227 ho_set_hodec2_min_rxlev(bsc_gsmnet->ho, -100);
1228 ho_set_hodec2_rxlev_avg_win(bsc_gsmnet->ho, 1);
1229 ho_set_hodec2_rxlev_neigh_avg_win(bsc_gsmnet->ho, 1);
1230 ho_set_hodec2_rxqual_avg_win(bsc_gsmnet->ho, 10);
1231 ho_set_hodec2_pwr_hysteresis(bsc_gsmnet->ho, 3);
1232 ho_set_hodec2_pwr_interval(bsc_gsmnet->ho, 1);
1233 ho_set_hodec2_afs_bias_rxlev(bsc_gsmnet->ho, 0);
1234 ho_set_hodec2_min_rxqual(bsc_gsmnet->ho, 5);
1235 ho_set_hodec2_afs_bias_rxqual(bsc_gsmnet->ho, 0);
1236 ho_set_hodec2_max_distance(bsc_gsmnet->ho, 9999);
1237 ho_set_hodec2_ho_max(bsc_gsmnet->ho, 9999);
1238 ho_set_hodec2_penalty_max_dist(bsc_gsmnet->ho, 300);
1239 ho_set_hodec2_penalty_failed_ho(bsc_gsmnet->ho, 60);
1240 ho_set_hodec2_penalty_failed_as(bsc_gsmnet->ho, 60);
1241
Vadim Yanitskiy4f3a6412020-05-31 01:56:20 +07001242 /* We don't really need any specific model here */
1243 bts_model_unknown_init();
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001244
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001245 /* Disable the congestion check timer, we will trigger manually. */
1246 bsc_gsmnet->hodec2.congestion_check_interval_s = 0;
1247
1248 handover_decision_1_init();
1249 hodec2_init(bsc_gsmnet);
1250
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001251 rc = vty_read_config_file(test_file, NULL);
1252 if (rc < 0) {
1253 fprintf(stderr, "Failed to parse the test file: '%s'\n", test_file);
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001254 }
1255
Neels Hofmeyre3416182018-03-05 05:31:14 +01001256 talloc_free(ctx);
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001257 fprintf(stderr,"-------------------\n");
1258 if (!rc)
1259 fprintf(stderr, "pass\n");
1260 else
1261 fprintf(stderr, "FAIL\n");
1262 return rc;
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001263}
1264
1265void rtp_socket_free() {}
1266void rtp_send_frame() {}
1267void rtp_socket_upstream() {}
1268void rtp_socket_create() {}
1269void rtp_socket_connect() {}
1270void rtp_socket_proxy() {}
1271void trau_mux_unmap() {}
1272void trau_mux_map_lchan() {}
1273void trau_recv_lchan() {}
1274void trau_send_frame() {}
Harald Welte3561bd42018-01-28 03:04:16 +01001275int osmo_bsc_sigtran_send(struct gsm_subscriber_connection *conn, struct msgb *msg) { return 0; }
1276int osmo_bsc_sigtran_open_conn(struct gsm_subscriber_connection *conn, struct msgb *msg) { return 0; }
Vadim Yanitskiy6a26e2c2020-08-26 18:49:08 +07001277void bsc_sapi_n_reject(struct gsm_subscriber_connection *conn, uint8_t dlci, enum gsm0808_cause cause) {}
Neels Hofmeyrc19581f2018-05-27 03:05:18 +02001278void bsc_cipher_mode_compl(struct gsm_subscriber_connection *conn, struct msgb *msg, uint8_t chosen_encr) {}
Neels Hofmeyr2001dd62020-09-11 23:35:28 +00001279int bsc_compl_l3(struct gsm_lchan *lchan, struct msgb *msg, uint16_t chosen_channel)
Neels Hofmeyrc19581f2018-05-27 03:05:18 +02001280{ return 0; }
Neels Hofmeyr86ce1052020-09-18 02:49:32 +02001281int bsc_paging_start(struct bsc_paging_params *params)
1282{ return 0; }
Neels Hofmeyrc19581f2018-05-27 03:05:18 +02001283void bsc_dtap(struct gsm_subscriber_connection *conn, uint8_t link_id, struct msgb *msg) {}
1284void bsc_assign_compl(struct gsm_subscriber_connection *conn, uint8_t rr_cause) {}
Neels Hofmeyrc19581f2018-05-27 03:05:18 +02001285void bsc_cm_update(struct gsm_subscriber_connection *conn,
1286 const uint8_t *cm2, uint8_t cm2_len,
1287 const uint8_t *cm3, uint8_t cm3_len) {}
Neels Hofmeyr31f525e2018-05-14 18:14:15 +02001288struct gsm0808_handover_required;
1289int bsc_tx_bssmap_ho_required(struct gsm_lchan *lchan, const struct gsm0808_cell_id_list2 *target_cells)
1290{ return 0; }
1291int bsc_tx_bssmap_ho_request_ack(struct gsm_subscriber_connection *conn, struct msgb *rr_ho_command)
1292{ return 0; }
1293int bsc_tx_bssmap_ho_detect(struct gsm_subscriber_connection *conn) { return 0; }
1294enum handover_result bsc_tx_bssmap_ho_complete(struct gsm_subscriber_connection *conn,
1295 struct gsm_lchan *lchan) { return HO_RESULT_OK; }
1296void bsc_tx_bssmap_ho_failure(struct gsm_subscriber_connection *conn) {}
Neels Hofmeyrc27ae2d2020-10-04 21:32:52 +02001297void osmo_bsc_sigtran_tx_reset(void) {}
Neels Hofmeyre95b92b2020-10-09 17:18:29 +02001298void osmo_bsc_sigtran_tx_reset_ack(void) {}
Neels Hofmeyrc27ae2d2020-10-04 21:32:52 +02001299void osmo_bsc_sigtran_reset(void) {}
1300void bssmap_reset_alloc(void) {}
1301void bssmap_reset_is_conn_ready(void) {}