blob: 69b25a10fae76512e8c727e9b6fd648d101a4fe0 [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 Hofmeyre0dfe962020-12-10 16:04:26 +0100608static void send_ho_detect(struct gsm_lchan *lchan)
609{
610 struct msgb *msg = msgb_alloc_headroom(256, 64, "RSL");
611 struct abis_rsl_rll_hdr *rh;
612 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
613
614 fprintf(stderr, "- Send HO DETECT for %s\n", gsm_lchan_name(lchan));
615
616 rh = (struct abis_rsl_rll_hdr *) msgb_put(msg, sizeof(*rh));
617 rh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
618 rh->c.msg_type = RSL_MT_HANDO_DET;
619 rh->ie_chan = RSL_IE_CHAN_NR;
620 rh->chan_nr = chan_nr;
621 rh->ie_link_id = RSL_IE_LINK_IDENT;
622 rh->link_id = 0x00;
623
624 msg->dst = lchan->ts->trx->bts->c0->rsl_link;
625 msg->l2h = (unsigned char *)rh;
626
627 abis_rsl_rcvmsg(msg);
628
629 send_est_ind(lchan);
630 osmo_fsm_inst_dispatch(lchan->fi, LCHAN_EV_RTP_READY, 0);
631
632}
633
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100634static void send_ho_complete(struct gsm_lchan *lchan, bool success)
635{
636 struct msgb *msg = msgb_alloc_headroom(256, 64, "RSL");
637 struct abis_rsl_rll_hdr *rh;
638 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
639 uint8_t *buf;
640 struct gsm48_hdr *gh;
641 struct gsm48_ho_cpl *hc;
642
Neels Hofmeyr64982dd2020-12-10 16:05:35 +0100643 if (success)
644 fprintf(stderr, "- Send HO COMPLETE for %s\n", gsm_lchan_name(lchan));
645 else
646 fprintf(stderr, "- Send HO FAIL to %s\n", gsm_lchan_name(lchan));
647
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100648 rh = (struct abis_rsl_rll_hdr *) msgb_put(msg, sizeof(*rh));
649 rh->c.msg_discr = ABIS_RSL_MDISC_RLL;
650 rh->c.msg_type = RSL_MT_DATA_IND;
651 rh->ie_chan = RSL_IE_CHAN_NR;
652 rh->chan_nr = chan_nr;
653 rh->ie_link_id = RSL_IE_LINK_IDENT;
654 rh->link_id = 0x00;
655
656 buf = msgb_put(msg, 3);
657 buf[0] = RSL_IE_L3_INFO;
658 buf[1] = (sizeof(*gh) + sizeof(*hc)) >> 8;
659 buf[2] = (sizeof(*gh) + sizeof(*hc)) & 0xff;
660
661 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
662 hc = (struct gsm48_ho_cpl *) msgb_put(msg, sizeof(*hc));
663
664 gh->proto_discr = GSM48_PDISC_RR;
665 gh->msg_type =
666 success ? GSM48_MT_RR_HANDO_COMPL : GSM48_MT_RR_HANDO_FAIL;
667
668 msg->dst = lchan->ts->trx->bts->c0->rsl_link;
669 msg->l2h = (unsigned char *)rh;
670 msg->l3h = (unsigned char *)gh;
671
672 abis_rsl_rcvmsg(msg);
673}
674
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100675static void lchan_release_ack(struct gsm_lchan *lchan)
676{
677 if (lchan->fi && lchan->fi->state == LCHAN_ST_WAIT_BEFORE_RF_RELEASE) {
678 /* don't wait before release */
679 osmo_fsm_inst_state_chg(lchan->fi, LCHAN_ST_WAIT_RF_RELEASE_ACK, 0, 0);
680 /* ack the release */
681 osmo_fsm_inst_dispatch(lchan->fi, LCHAN_EV_RSL_RF_CHAN_REL_ACK, 0);
682 }
683}
684
Neels Hofmeyr1d7473c2018-03-05 21:53:18 +0100685/* override, requires '-Wl,--wrap=abis_rsl_sendmsg'.
686 * Catch RSL messages sent towards the BTS. */
687int __real_abis_rsl_sendmsg(struct msgb *msg);
688int __wrap_abis_rsl_sendmsg(struct msgb *msg)
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100689{
690 struct abis_rsl_dchan_hdr *dh = (struct abis_rsl_dchan_hdr *) msg->data;
691 struct e1inp_sign_link *sign_link = msg->dst;
692 int rc;
693 struct gsm_lchan *lchan = rsl_lchan_lookup(sign_link->trx, dh->chan_nr, &rc);
Neels Hofmeyrfb6d9dc2020-11-13 01:13:20 +0100694 struct gsm_lchan *other_lchan;
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100695
696 if (rc) {
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100697 fprintf(stderr, "rsl_lchan_lookup() failed\n");
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100698 exit(1);
699 }
700
701 switch (dh->c.msg_type) {
702 case RSL_MT_CHAN_ACTIV:
703 rc = parse_chan_act(lchan, dh->data);
704 if (rc == 0)
705 got_chan_req = 1;
706 break;
707 case RSL_MT_RF_CHAN_REL:
708 rc = parse_chan_rel(lchan, dh->data);
709 if (rc == 0)
710 send_chan_act_ack(chan_req_lchan, 0);
Neels Hofmeyrfb6d9dc2020-11-13 01:13:20 +0100711
712 /* send dyn TS back to PDCH if unused */
713 switch (chan_req_lchan->ts->pchan_on_init) {
714 case GSM_PCHAN_TCH_F_TCH_H_PDCH:
715 case GSM_PCHAN_TCH_F_PDCH:
716 switch (chan_req_lchan->ts->pchan_is) {
717 case GSM_PCHAN_TCH_H:
718 other_lchan = &chan_req_lchan->ts->lchan[
719 (chan_req_lchan == &chan_req_lchan->ts->lchan[0])?
720 1 : 0];
721 if (lchan_state_is(other_lchan, LCHAN_ST_ESTABLISHED))
722 break;
723 /* else fall thru */
724 case GSM_PCHAN_TCH_F:
725 chan_req_lchan->ts->pchan_is = GSM_PCHAN_PDCH;
726 break;
727 default:
728 break;
729 }
730 break;
731 default:
732 break;
733 }
734
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100735 break;
736 case RSL_MT_DATA_REQ:
737 rc = parse_ho_command(lchan, msg->l3h, msgb_l3len(msg));
738 if (rc == 0)
739 got_ho_req = 1;
740 break;
741 case RSL_MT_IPAC_CRCX:
742 break;
Neels Hofmeyr5b1a7d12018-11-06 22:24:07 +0100743 case RSL_MT_DEACTIVATE_SACCH:
744 break;
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100745 default:
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100746 fprintf(stderr, "unknown rsl message=0x%x\n", dh->c.msg_type);
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100747 }
748 return 0;
749}
750
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100751struct gsm_bts *bts_by_num_str(const char *num_str)
752{
753 struct gsm_bts *bts = gsm_bts_num(bsc_gsmnet, atoi(num_str));
754 OSMO_ASSERT(bts);
755 return bts;
756}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100757
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100758struct gsm_bts_trx *trx_by_num_str(struct gsm_bts *bts, const char *num_str)
759{
760 struct gsm_bts_trx *trx = gsm_bts_trx_num(bts, atoi(num_str));
761 OSMO_ASSERT(trx);
762 return trx;
763}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100764
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100765#define LCHAN_ARGS "lchan <0-255> <0-255> <0-7> <0-7>"
766#define LCHAN_ARGS_DOC "identify an lchan\nBTS nr\nTRX nr\nTimeslot nr\nSubslot nr\n"
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100767
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100768static struct gsm_lchan *parse_lchan_args(const char **argv)
769{
770 struct gsm_bts *bts = bts_by_num_str(argv[0]);
771 struct gsm_bts_trx *trx = trx_by_num_str(bts, argv[1]);
772 struct gsm_bts_trx_ts *ts = &trx->ts[atoi(argv[2])];
773 return &ts->lchan[atoi(argv[3])];
774}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100775
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100776#define TS_USE " (TCH/F|TCH/H-|TCH/-H|TCH/HH|PDCH" \
777 "|tch/f|tch/h-|tch/-h|tch/hh|pdch" \
778 "|-|*)"
779#define TS_USE_DOC "'TCH/F': one FR call\n" \
780 "'TCH/H-': HR TS with first subslot used as TCH/H, other subslot unused\n" \
781 "'TCH/HH': HR TS with both subslots used as TCH/H\n" \
782 "'TCH/-H': HR TS with only second subslot used as TCH/H\n" \
783 "'PDCH': TS used for PDCH (e.g. unused dynamic TS)\n" \
784 "'tch/f': one FR call\n" \
785 "'tch/h-': HR TS with first subslot used as TCH/H, other subslot unused\n" \
786 "'tch/hh': HR TS with both subslots used as TCH/H\n" \
787 "'tch/-h': HR TS with only second subslot used as TCH/H\n" \
788 "'pdch': TS used for PDCH (e.g. unused dynamic TS)\n" \
789 "'-': TS unused\n" \
790 "'*': TS allowed to be in any state\n"
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100791
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100792DEFUN(create_n_bts, create_n_bts_cmd,
793 "create-n-bts <1-255>",
794 "Create a number of BTS with four TCH/F and four TCH/H timeslots\n"
795 "Number of BTS to create\n")
796{
797 int i;
798 int n = atoi(argv[0]);
799 for (i = 0; i < n; i++)
800 _create_bts(1, NULL, 0);
801 return CMD_SUCCESS;
802}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100803
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100804DEFUN(create_bts, create_bts_cmd,
805 "create-bts trx-count <1-255> timeslots .TS_CFG",
806 "Create a new BTS with specific timeslot configuration\n"
807 "Create N TRX in the new BTS\n"
808 "TRX count\n"
809 "Timeslot config\n"
810 "Timeslot types for 8 * trx-count, each being one of CCCH+SDCCH4|SDCCH8|TCH/F|TCH/H|TCH/F_TCH/H_PDCH|...;"
811 " shorthands: cs+4 = CCCH+SDCCH4; dyn = TCH/F_TCH/H_PDCH\n")
812{
813 int num_trx = atoi(argv[0]);
814 _create_bts(num_trx, argv + 1, argc - 1);
815 return CMD_SUCCESS;
816}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100817
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100818DEFUN(create_ms, create_ms_cmd,
819 "create-ms bts <0-999> (TCH/F|TCH/H) (AMR|HR|EFR)",
820 "Create an MS using the next free matching lchan on a given BTS\n"
821 "BTS index to subscribe on\n"
822 "lchan type to select\n"
823 "codec\n")
824{
825 const char *bts_nr_str = argv[0];
826 const char *tch_type = argv[1];
827 const char *codec = argv[2];
828 struct gsm_lchan *lchan;
829 fprintf(stderr, "- Creating mobile at BTS %s on "
830 "%s with %s codec\n", bts_nr_str, tch_type, codec);
831 lchan = create_lchan(bts_by_num_str(bts_nr_str),
832 !strcmp(tch_type, "TCH/F"), codec);
833 if (!lchan) {
834 fprintf(stderr, "Failed to create lchan!\n");
835 return CMD_WARNING;
836 }
837 fprintf(stderr, " * New MS is at %s\n", gsm_lchan_name(lchan));
838 return CMD_SUCCESS;
839}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100840
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100841DEFUN(meas_rep, meas_rep_cmd,
842 "meas-rep " LCHAN_ARGS " rxlev <0-255> rxqual <0-7> ta <0-255>"
843 " [neighbors] [<0-255>] [<0-255>] [<0-255>] [<0-255>] [<0-255>] [<0-255>]",
844 "Send measurement report\n"
845 LCHAN_ARGS_DOC
846 "rxlev\nrxlev\n"
847 "rxqual\nrxqual\n"
848 "timing advance\ntiming advance\n"
849 "neighbors list of rxlev reported by each neighbor cell\n"
850 "neighbor 0 rxlev\n"
851 "neighbor 1 rxlev\n"
852 "neighbor 2 rxlev\n"
853 "neighbor 3 rxlev\n"
854 "neighbor 4 rxlev\n"
855 "neighbor 5 rxlev\n"
856 )
857{
858 struct gsm_lchan *lc;
859 uint8_t rxlev;
860 uint8_t rxqual;
861 uint8_t ta;
862 int i;
863 struct neighbor_meas nm[6] = {};
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100864
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100865 lc = parse_lchan_args(argv);
866 argv += 4;
867 argc -= 4;
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100868
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100869 rxlev = atoi(argv[0]);
870 rxqual = atoi(argv[1]);
871 ta = atoi(argv[2]);
872 argv += 3;
873 argc -= 3;
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100874
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100875 if (!lchan_state_is(lc, LCHAN_ST_ESTABLISHED)) {
876 fprintf(stderr, "Error: sending measurement report for %s which is in state %s\n",
877 gsm_lchan_name(lc), lchan_state_name(lc));
878 exit(1);
879 }
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100880
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100881 /* skip the optional [neighbors] keyword */
882 if (argc) {
883 argv++;
884 argc--;
885 }
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100886
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100887 fprintf(stderr, "- Sending measurement report from %s: rxlev=%u rxqual=%u ta=%u (%d neighbors)\n",
888 gsm_lchan_name(lc), rxlev, rxqual, ta, argc);
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100889
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100890 for (i = 0; i < 6; i++) {
891 int neighbor_bts_nr = i;
892 /* since our bts is not in the list of neighbor cells, we need to shift */
893 if (neighbor_bts_nr >= lc->ts->trx->bts->nr)
894 neighbor_bts_nr++;
895 nm[i] = (struct neighbor_meas){
896 .rxlev = argc > i ? atoi(argv[i]) : 0,
897 .bsic = 0x3f,
898 .bcch_f = i,
899 };
900 if (i < argc)
901 fprintf(stderr, " * Neighbor cell #%d, actual BTS %d: rxlev=%d\n", i, neighbor_bts_nr,
902 nm[i].rxlev);
903 }
904 got_chan_req = 0;
905 gen_meas_rep(lc, rxlev, rxqual, ta, argc, nm);
906 return CMD_SUCCESS;
907}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100908
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100909DEFUN(congestion_check, congestion_check_cmd,
910 "congestion-check",
911 "Trigger a congestion check\n")
912{
913 fprintf(stderr, "- Triggering congestion check\n");
914 got_chan_req = 0;
915 hodec2_congestion_check(bsc_gsmnet);
916 return CMD_SUCCESS;
917}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100918
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100919DEFUN(expect_no_chan, expect_no_chan_cmd,
920 "expect-no-chan",
921 "Expect that no channel request was sent from BSC to any cell\n")
922{
923 fprintf(stderr, "- Expecting no channel request\n");
924 if (got_chan_req) {
925 fprintf(stderr, " * Got channel request at %s\n", gsm_lchan_name(chan_req_lchan));
926 fprintf(stderr, "Test failed, because channel was requested\n");
927 exit(1);
928 }
929 fprintf(stderr, " * Got no channel request\n");
930 return CMD_SUCCESS;
931}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100932
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100933static void _expect_chan_activ(struct gsm_lchan *lchan)
934{
935 fprintf(stderr, "- Expecting channel request at %s\n",
936 gsm_lchan_name(lchan));
937 if (!got_chan_req) {
938 fprintf(stderr, "Test failed, because no channel was requested\n");
939 exit(1);
940 }
941 fprintf(stderr, " * Got channel request at %s\n", gsm_lchan_name(chan_req_lchan));
942 if (lchan != chan_req_lchan) {
943 fprintf(stderr, "Test failed, because channel was requested on a different lchan than expected\n"
944 "expected: %s got: %s\n",
945 gsm_lchan_name(lchan), gsm_lchan_name(chan_req_lchan));
946 exit(1);
947 }
948}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100949
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100950static void _ack_chan_activ(struct gsm_lchan *lchan)
951{
952 fprintf(stderr, "- Acknowledging channel request on %s\n", gsm_lchan_name(lchan));
953 got_ho_req = 0;
954 send_chan_act_ack(lchan, 1);
955}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100956
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100957static void _expect_ho_req(struct gsm_lchan *lchan)
958{
959 fprintf(stderr, "- Expecting handover/assignment request at %s\n",
960 gsm_lchan_name(lchan));
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100961
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100962 if (!got_ho_req) {
963 fprintf(stderr, "Test failed, because no handover was requested\n");
964 exit(1);
965 }
966 fprintf(stderr, " * Got handover/assignment request at %s\n", gsm_lchan_name(ho_req_lchan));
967 if (ho_req_lchan != lchan) {
968 fprintf(stderr, "Test failed, because handover/assignment was not commanded on the expected lchan\n");
969 exit(1);
970 }
971}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100972
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100973DEFUN(expect_chan, expect_chan_cmd,
974 "expect-chan " LCHAN_ARGS,
975 "Expect a channel request from BSC to a cell for a specific lchan\n"
976 LCHAN_ARGS_DOC)
977{
978 _expect_chan_activ(parse_lchan_args(argv));
979 return CMD_SUCCESS;
980}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100981
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100982DEFUN(ack_chan, ack_chan_cmd,
983 "ack-chan",
984 "ACK a previous Channel Request\n")
985{
986 OSMO_ASSERT(got_chan_req);
987 _ack_chan_activ(chan_req_lchan);
988 return CMD_SUCCESS;
989}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100990
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +0100991DEFUN(expect_ho_req, expect_ho_req_cmd,
992 "expect-ho-req " LCHAN_ARGS,
993 "Expect a handover of a given lchan\n"
994 LCHAN_ARGS_DOC)
995{
996 _expect_ho_req(parse_lchan_args(argv));
997 return CMD_SUCCESS;
998}
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100999
Neels Hofmeyre0dfe962020-12-10 16:04:26 +01001000DEFUN(ho_detection, ho_detection_cmd,
1001 "ho-detect",
1002 "Send Handover Detection to the most recent HO target lchan\n")
1003{
1004 if (!got_chan_req) {
1005 fprintf(stderr, "Cannot ack handover/assignment, because no chan request\n");
1006 exit(1);
1007 }
1008 if (!got_ho_req) {
1009 fprintf(stderr, "Cannot ack handover/assignment, because no ho request\n");
1010 exit(1);
1011 }
1012 send_ho_detect(chan_req_lchan);
1013 return CMD_SUCCESS;
1014}
1015
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001016DEFUN(ho_complete, ho_complete_cmd,
1017 "ho-complete",
1018 "Send Handover Complete for the most recent HO target lchan\n")
1019{
1020 if (!got_chan_req) {
1021 fprintf(stderr, "Cannot ack handover/assignment, because no chan request\n");
1022 exit(1);
1023 }
1024 if (!got_ho_req) {
1025 fprintf(stderr, "Cannot ack handover/assignment, because no ho request\n");
1026 exit(1);
1027 }
1028 send_ho_complete(chan_req_lchan, true);
1029 lchan_release_ack(ho_req_lchan);
1030 return CMD_SUCCESS;
1031}
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001032
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001033DEFUN(expect_ho, expect_ho_cmd,
1034 "expect-ho from " LCHAN_ARGS " to " LCHAN_ARGS,
1035 "Expect a handover of a specific lchan to a specific target lchan;"
1036 " shorthand for expect-chan, ack-chan, expect-ho, ho-complete.\n"
1037 "lchan to handover from\n" LCHAN_ARGS_DOC
1038 "lchan that to handover to\n" LCHAN_ARGS_DOC)
1039{
1040 struct gsm_lchan *from = parse_lchan_args(argv);
1041 struct gsm_lchan *to = parse_lchan_args(argv+4);
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001042
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001043 _expect_chan_activ(to);
1044 _ack_chan_activ(to);
1045 _expect_ho_req(from);
Neels Hofmeyre0dfe962020-12-10 16:04:26 +01001046 send_ho_detect(to);
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001047 send_ho_complete(to, true);
1048 lchan_release_ack(from);
1049 return CMD_SUCCESS;
1050}
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001051
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001052DEFUN(ho_failed, ho_failed_cmd,
1053 "ho-failed",
1054 "Fail the most recent handover request\n")
1055{
1056 if (!got_chan_req) {
1057 fprintf(stderr, "Cannot fail handover, because no chan request\n");
1058 exit(1);
1059 }
1060 got_chan_req = 0;
1061 got_ho_req = 0;
1062 send_ho_complete(ho_req_lchan, false);
1063 lchan_release_ack(chan_req_lchan);
1064 return CMD_SUCCESS;
1065}
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001066
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001067DEFUN(expect_ts_use, expect_ts_use_cmd,
1068 "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,
1069 "Expect timeslots of a BTS' TRX to be in a specific state\n"
1070 "Indicate a BTS and TRX\n" "BTS nr\n" "TRX nr\n"
1071 "List of 8 expected TS states\n"
1072 TS_USE_DOC TS_USE_DOC TS_USE_DOC TS_USE_DOC TS_USE_DOC TS_USE_DOC TS_USE_DOC TS_USE_DOC)
1073{
1074 struct gsm_bts *bts = bts_by_num_str(argv[0]);
1075 struct gsm_bts_trx *trx = trx_by_num_str(bts, argv[1]);
1076 argv += 2;
1077 argc -= 2;
1078 if (!_expect_ts_use(bts, trx, argv))
1079 exit(1);
1080 return CMD_SUCCESS;
1081}
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001082
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001083DEFUN(codec_f, codec_f_cmd,
1084 "codec tch/f (AMR|EFR|FR)",
1085 "Define which codec should be used for new TCH/F lchans (for set-ts-use)\n"
1086 "Configure the TCH/F codec to use\nAMR\nEFR\nFR\n")
1087{
1088 osmo_talloc_replace_string(ctx, &codec_tch_f, argv[0]);
1089 return CMD_SUCCESS;
1090}
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001091
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001092DEFUN(codec_h, codec_h_cmd,
1093 "codec tch/h (AMR|HR)",
1094 "Define which codec should be used for new TCH/H lchans (for set-ts-use)\n"
1095 "Configure the TCH/H codec to use\nAMR\nHR\n")
1096{
1097 osmo_talloc_replace_string(ctx, &codec_tch_h, argv[0]);
1098 return CMD_SUCCESS;
1099}
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001100
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001101DEFUN(set_ts_use, set_ts_use_cmd,
1102 "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,
1103 "Put timeslots of a BTS' TRX into a specific state\n"
1104 "Indicate a BTS and TRX\n" "BTS nr\n" "TRX nr\n"
1105 "List of 8 TS states to apply\n"
1106 TS_USE_DOC TS_USE_DOC TS_USE_DOC TS_USE_DOC TS_USE_DOC TS_USE_DOC TS_USE_DOC TS_USE_DOC)
1107{
1108 struct gsm_bts *bts = bts_by_num_str(argv[0]);
1109 struct gsm_bts_trx *trx = trx_by_num_str(bts, argv[1]);
1110 argv += 2;
1111 argc -= 2;
1112 if (!_set_ts_use(bts, trx, argv))
1113 exit(1);
1114 if (!_expect_ts_use(bts, trx, argv))
1115 exit(1);
1116 return CMD_SUCCESS;
1117}
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001118
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001119static void ho_test_vty_init()
1120{
1121 install_element(CONFIG_NODE, &create_n_bts_cmd);
1122 install_element(CONFIG_NODE, &create_bts_cmd);
1123 install_element(CONFIG_NODE, &create_ms_cmd);
1124 install_element(CONFIG_NODE, &meas_rep_cmd);
1125 install_element(CONFIG_NODE, &congestion_check_cmd);
1126 install_element(CONFIG_NODE, &expect_no_chan_cmd);
1127 install_element(CONFIG_NODE, &expect_chan_cmd);
1128 install_element(CONFIG_NODE, &ack_chan_cmd);
1129 install_element(CONFIG_NODE, &expect_ho_req_cmd);
Neels Hofmeyre0dfe962020-12-10 16:04:26 +01001130 install_element(CONFIG_NODE, &ho_detection_cmd);
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001131 install_element(CONFIG_NODE, &ho_complete_cmd);
1132 install_element(CONFIG_NODE, &expect_ho_cmd);
1133 install_element(CONFIG_NODE, &ho_failed_cmd);
1134 install_element(CONFIG_NODE, &expect_ts_use_cmd);
1135 install_element(CONFIG_NODE, &codec_f_cmd);
1136 install_element(CONFIG_NODE, &codec_h_cmd);
1137 install_element(CONFIG_NODE, &set_ts_use_cmd);
1138}
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001139
1140static const struct log_info_cat log_categories[] = {
1141 [DHO] = {
1142 .name = "DHO",
1143 .description = "Hand-Over Process",
1144 .color = "\033[1;38m",
1145 .enabled = 1, .loglevel = LOGL_DEBUG,
1146 },
1147 [DHODEC] = {
1148 .name = "DHODEC",
1149 .description = "Hand-Over Decision",
1150 .color = "\033[1;38m",
1151 .enabled = 1, .loglevel = LOGL_DEBUG,
1152 },
1153 [DMEAS] = {
1154 .name = "DMEAS",
1155 .description = "Radio Measurement Processing",
1156 .enabled = 1, .loglevel = LOGL_DEBUG,
1157 },
1158 [DREF] = {
1159 .name = "DREF",
1160 .description = "Reference Counting",
1161 .enabled = 1, .loglevel = LOGL_DEBUG,
1162 },
1163 [DRSL] = {
1164 .name = "DRSL",
Keithd925c7c2018-04-16 13:40:07 +02001165 .description = "A-bis Radio Signalling Link (RSL)",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001166 .color = "\033[1;35m",
1167 .enabled = 1, .loglevel = LOGL_DEBUG,
1168 },
Neels Hofmeyr31f525e2018-05-14 18:14:15 +02001169 [DRR] = {
1170 .name = "DRR",
1171 .description = "RR",
1172 .color = "\033[1;35m",
1173 .enabled = 1, .loglevel = LOGL_DEBUG,
1174 },
1175 [DRLL] = {
1176 .name = "DRLL",
1177 .description = "RLL",
1178 .color = "\033[1;35m",
1179 .enabled = 1, .loglevel = LOGL_DEBUG,
1180 },
Harald Welte3561bd42018-01-28 03:04:16 +01001181 [DMSC] = {
1182 .name = "DMSC",
1183 .description = "Mobile Switching Center",
1184 .enabled = 1, .loglevel = LOGL_DEBUG,
1185 },
Neels Hofmeyr3c5612f2018-07-11 19:53:39 +02001186 [DCHAN] = {
1187 .name = "DCHAN",
1188 .description = "lchan FSM",
1189 .color = "\033[1;32m",
1190 .enabled = 1, .loglevel = LOGL_DEBUG,
1191 },
1192 [DTS] = {
1193 .name = "DTS",
1194 .description = "timeslot FSM",
1195 .color = "\033[1;31m",
1196 .enabled = 1, .loglevel = LOGL_DEBUG,
1197 },
1198 [DAS] = {
1199 .name = "DAS",
1200 .description = "assignment FSM",
1201 .color = "\033[1;33m",
1202 .enabled = 1, .loglevel = LOGL_DEBUG,
1203 },
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001204};
1205
1206const struct log_info log_info = {
1207 .cat = log_categories,
1208 .num_cat = ARRAY_SIZE(log_categories),
1209};
1210
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001211static struct vty_app_info vty_info = {
1212 .name = "ho_test",
1213 .copyright =
1214 "Copyright (C) 2020 sysmocom - s.f.m.c. GmbH\r\n"
1215 "License AGPLv3+: GNU AGPL version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n"
1216 "This is free software: you are free to change and redistribute it.\r\n"
1217 "There is NO WARRANTY, to the extent permitted by law.\r\n",
1218 .version = PACKAGE_VERSION,
1219 .usr_attr_desc = {
1220 [BSC_VTY_ATTR_RESTART_ABIS_OML_LINK] = \
1221 "This command applies on A-bis OML link (re)establishment",
1222 [BSC_VTY_ATTR_RESTART_ABIS_RSL_LINK] = \
1223 "This command applies on A-bis RSL link (re)establishment",
1224 [BSC_VTY_ATTR_NEW_LCHAN] = \
1225 "This command applies for newly created lchans",
1226 },
1227 .usr_attr_letters = {
1228 [BSC_VTY_ATTR_RESTART_ABIS_OML_LINK] = 'o',
1229 [BSC_VTY_ATTR_RESTART_ABIS_RSL_LINK] = 'r',
1230 [BSC_VTY_ATTR_NEW_LCHAN] = 'l',
1231 },
1232};
Neels Hofmeyrb5a107d2020-11-12 23:00:08 +01001233
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001234int main(int argc, char **argv)
1235{
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001236 char *test_file = NULL;
1237 int rc;
1238
1239 if (argc < 2) {
1240 fprintf(stderr, "Pass a handover test script as argument\n");
1241 exit(1);
1242 }
1243 test_file = argv[1];
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001244
Neels Hofmeyre3416182018-03-05 05:31:14 +01001245 ctx = talloc_named_const(NULL, 0, "handover_test");
1246 msgb_talloc_ctx_init(ctx, 0);
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001247 vty_info.tall_ctx = ctx;
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001248
Neels Hofmeyre3416182018-03-05 05:31:14 +01001249 osmo_init_logging2(ctx, &log_info);
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001250
1251 log_set_print_category(osmo_stderr_target, 1);
1252 log_set_print_category_hex(osmo_stderr_target, 0);
1253 log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_BASENAME);
Neels Hofmeyr31f525e2018-05-14 18:14:15 +02001254 osmo_fsm_log_addr(false);
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001255
Neels Hofmeyr958f2592018-05-27 01:26:31 +02001256 bsc_network_alloc();
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001257 if (!bsc_gsmnet)
1258 exit(1);
1259
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001260 vty_init(&vty_info);
1261 bsc_vty_init(bsc_gsmnet);
1262 ho_test_vty_init();
1263
Neels Hofmeyr31f525e2018-05-14 18:14:15 +02001264 ts_fsm_init();
1265 lchan_fsm_init();
Neels Hofmeyr31f525e2018-05-14 18:14:15 +02001266 bsc_subscr_conn_fsm_init();
1267 handover_fsm_init();
1268
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001269 ho_set_algorithm(bsc_gsmnet->ho, 2);
1270 ho_set_ho_active(bsc_gsmnet->ho, true);
1271 ho_set_hodec2_as_active(bsc_gsmnet->ho, true);
1272 ho_set_hodec2_min_rxlev(bsc_gsmnet->ho, -100);
1273 ho_set_hodec2_rxlev_avg_win(bsc_gsmnet->ho, 1);
1274 ho_set_hodec2_rxlev_neigh_avg_win(bsc_gsmnet->ho, 1);
1275 ho_set_hodec2_rxqual_avg_win(bsc_gsmnet->ho, 10);
1276 ho_set_hodec2_pwr_hysteresis(bsc_gsmnet->ho, 3);
1277 ho_set_hodec2_pwr_interval(bsc_gsmnet->ho, 1);
1278 ho_set_hodec2_afs_bias_rxlev(bsc_gsmnet->ho, 0);
1279 ho_set_hodec2_min_rxqual(bsc_gsmnet->ho, 5);
1280 ho_set_hodec2_afs_bias_rxqual(bsc_gsmnet->ho, 0);
1281 ho_set_hodec2_max_distance(bsc_gsmnet->ho, 9999);
1282 ho_set_hodec2_ho_max(bsc_gsmnet->ho, 9999);
1283 ho_set_hodec2_penalty_max_dist(bsc_gsmnet->ho, 300);
1284 ho_set_hodec2_penalty_failed_ho(bsc_gsmnet->ho, 60);
1285 ho_set_hodec2_penalty_failed_as(bsc_gsmnet->ho, 60);
1286
Vadim Yanitskiy4f3a6412020-05-31 01:56:20 +07001287 /* We don't really need any specific model here */
1288 bts_model_unknown_init();
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001289
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001290 /* Disable the congestion check timer, we will trigger manually. */
1291 bsc_gsmnet->hodec2.congestion_check_interval_s = 0;
1292
1293 handover_decision_1_init();
1294 hodec2_init(bsc_gsmnet);
1295
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001296 rc = vty_read_config_file(test_file, NULL);
1297 if (rc < 0) {
1298 fprintf(stderr, "Failed to parse the test file: '%s'\n", test_file);
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001299 }
1300
Neels Hofmeyre3416182018-03-05 05:31:14 +01001301 talloc_free(ctx);
Neels Hofmeyr1a3eaef2020-11-18 16:25:55 +01001302 fprintf(stderr,"-------------------\n");
1303 if (!rc)
1304 fprintf(stderr, "pass\n");
1305 else
1306 fprintf(stderr, "FAIL\n");
1307 return rc;
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001308}
1309
1310void rtp_socket_free() {}
1311void rtp_send_frame() {}
1312void rtp_socket_upstream() {}
1313void rtp_socket_create() {}
1314void rtp_socket_connect() {}
1315void rtp_socket_proxy() {}
1316void trau_mux_unmap() {}
1317void trau_mux_map_lchan() {}
1318void trau_recv_lchan() {}
1319void trau_send_frame() {}
Harald Welte3561bd42018-01-28 03:04:16 +01001320int osmo_bsc_sigtran_send(struct gsm_subscriber_connection *conn, struct msgb *msg) { return 0; }
1321int osmo_bsc_sigtran_open_conn(struct gsm_subscriber_connection *conn, struct msgb *msg) { return 0; }
Vadim Yanitskiy6a26e2c2020-08-26 18:49:08 +07001322void bsc_sapi_n_reject(struct gsm_subscriber_connection *conn, uint8_t dlci, enum gsm0808_cause cause) {}
Neels Hofmeyrc19581f2018-05-27 03:05:18 +02001323void bsc_cipher_mode_compl(struct gsm_subscriber_connection *conn, struct msgb *msg, uint8_t chosen_encr) {}
Neels Hofmeyr2001dd62020-09-11 23:35:28 +00001324int bsc_compl_l3(struct gsm_lchan *lchan, struct msgb *msg, uint16_t chosen_channel)
Neels Hofmeyrc19581f2018-05-27 03:05:18 +02001325{ return 0; }
Neels Hofmeyr86ce1052020-09-18 02:49:32 +02001326int bsc_paging_start(struct bsc_paging_params *params)
1327{ return 0; }
Neels Hofmeyrc19581f2018-05-27 03:05:18 +02001328void bsc_dtap(struct gsm_subscriber_connection *conn, uint8_t link_id, struct msgb *msg) {}
1329void bsc_assign_compl(struct gsm_subscriber_connection *conn, uint8_t rr_cause) {}
Neels Hofmeyrc19581f2018-05-27 03:05:18 +02001330void bsc_cm_update(struct gsm_subscriber_connection *conn,
1331 const uint8_t *cm2, uint8_t cm2_len,
1332 const uint8_t *cm3, uint8_t cm3_len) {}
Neels Hofmeyr31f525e2018-05-14 18:14:15 +02001333struct gsm0808_handover_required;
1334int bsc_tx_bssmap_ho_required(struct gsm_lchan *lchan, const struct gsm0808_cell_id_list2 *target_cells)
1335{ return 0; }
1336int bsc_tx_bssmap_ho_request_ack(struct gsm_subscriber_connection *conn, struct msgb *rr_ho_command)
1337{ return 0; }
1338int bsc_tx_bssmap_ho_detect(struct gsm_subscriber_connection *conn) { return 0; }
1339enum handover_result bsc_tx_bssmap_ho_complete(struct gsm_subscriber_connection *conn,
1340 struct gsm_lchan *lchan) { return HO_RESULT_OK; }
1341void bsc_tx_bssmap_ho_failure(struct gsm_subscriber_connection *conn) {}
Neels Hofmeyrc27ae2d2020-10-04 21:32:52 +02001342void osmo_bsc_sigtran_tx_reset(void) {}
Neels Hofmeyre95b92b2020-10-09 17:18:29 +02001343void osmo_bsc_sigtran_tx_reset_ack(void) {}
Neels Hofmeyrc27ae2d2020-10-04 21:32:52 +02001344void osmo_bsc_sigtran_reset(void) {}
1345void bssmap_reset_alloc(void) {}
1346void bssmap_reset_is_conn_ready(void) {}