blob: 284cb216b1738caea53342d39217ff6f37ae04e9 [file] [log] [blame]
Harald Welte8470bf22008-12-25 23:28:35 +00001/* GSM Channel allocation routines
2 *
3 * (C) 2008 by Harald Welte <laforge@gnumonks.org>
Holger Freythere64a7a32009-02-06 21:55:37 +00004 * (C) 2008, 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
Harald Welte8470bf22008-12-25 23:28:35 +00005 *
6 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
Harald Welte9af6ddf2011-01-01 15:25:50 +01009 * it under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
Harald Welte8470bf22008-12-25 23:28:35 +000011 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Harald Welte9af6ddf2011-01-01 15:25:50 +010016 * GNU Affero General Public License for more details.
Harald Welte8470bf22008-12-25 23:28:35 +000017 *
Harald Welte9af6ddf2011-01-01 15:25:50 +010018 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Harald Welte8470bf22008-12-25 23:28:35 +000020 *
21 */
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <errno.h>
27
Neels Hofmeyrc0164792017-09-04 15:15:32 +020028#include <osmocom/bsc/chan_alloc.h>
29#include <osmocom/bsc/abis_nm.h>
30#include <osmocom/bsc/abis_rsl.h>
31#include <osmocom/bsc/debug.h>
Neels Hofmeyrc0164792017-09-04 15:15:32 +020032#include <osmocom/bsc/signal.h>
33#include <osmocom/bsc/gsm_04_08_utils.h>
Holger Freytherc6ea9db2008-12-30 19:18:21 +000034
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010035#include <osmocom/core/talloc.h>
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +080036
Andreas Eversberg7c41cd12013-06-02 10:36:53 +020037bool ts_is_usable(const struct gsm_bts_trx_ts *ts)
Harald Welte4c704542009-12-24 10:10:16 +010038{
Max6e4f1842018-01-07 16:45:42 +010039 if (!trx_is_usable(ts->trx))
40 return false;
Harald Welte4c704542009-12-24 10:10:16 +010041
Neels Hofmeyrc6926d02016-07-14 02:51:13 +020042 /* If a TCH/F_PDCH TS is busy changing, it is already taken or not
Neels Hofmeyr832afa32016-06-14 13:12:00 +020043 * yet available. */
44 if (ts->pchan == GSM_PCHAN_TCH_F_PDCH) {
45 if (ts->flags & TS_F_PDCH_PENDING_MASK)
Maxd0ff6942017-11-29 12:45:34 +010046 return false;
Neels Hofmeyr832afa32016-06-14 13:12:00 +020047 }
48
Neels Hofmeyrfdd9ad72016-07-14 03:01:24 +020049 /* If a dynamic channel is busy changing, it is already taken or not
50 * yet available. */
51 if (ts->pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH) {
52 if (ts->dyn.pchan_is != ts->dyn.pchan_want)
Maxd0ff6942017-11-29 12:45:34 +010053 return false;
Neels Hofmeyrfdd9ad72016-07-14 03:01:24 +020054 }
55
Maxd0ff6942017-11-29 12:45:34 +010056 return true;
Harald Welte4c704542009-12-24 10:10:16 +010057}
58
Maxd0ff6942017-11-29 12:45:34 +010059bool trx_is_usable(const struct gsm_bts_trx *trx)
Harald Welte4c704542009-12-24 10:10:16 +010060{
61 /* FIXME: How does this behave for BS-11 ? */
62 if (is_ipaccess_bts(trx->bts)) {
Harald Welted64c0bc2011-05-30 12:07:53 +020063 if (!nm_is_running(&trx->mo.nm_state) ||
64 !nm_is_running(&trx->bb_transc.mo.nm_state))
Maxd0ff6942017-11-29 12:45:34 +010065 return false;
Harald Welte4c704542009-12-24 10:10:16 +010066 }
67
Maxd0ff6942017-11-29 12:45:34 +010068 return true;
Harald Welte4c704542009-12-24 10:10:16 +010069}
70
Andreas Eversbergdf65c9a2013-05-30 10:29:36 +020071static int trx_count_free_ts(struct gsm_bts_trx *trx, enum gsm_phys_chan_config pchan)
72{
73 struct gsm_bts_trx_ts *ts;
74 int j, ss;
75 int count = 0;
76
77 if (!trx_is_usable(trx))
78 return 0;
79
80 for (j = 0; j < ARRAY_SIZE(trx->ts); j++) {
81 enum gsm_phys_chan_config ts_pchan_is;
82 ts = &trx->ts[j];
83 if (!ts_is_usable(ts))
84 continue;
85
86 ts_pchan_is = ts_pchan(ts);
87
88 if (ts_pchan_is == GSM_PCHAN_PDCH) {
89 /* Dynamic timeslots in PDCH mode will become TCH if needed. */
90 switch (ts->pchan) {
91 case GSM_PCHAN_TCH_F_PDCH:
92 if (pchan == GSM_PCHAN_TCH_F)
93 count++;
94 continue;
95
96 case GSM_PCHAN_TCH_F_TCH_H_PDCH:
97 if (pchan == GSM_PCHAN_TCH_F)
98 count++;
99 else if (pchan == GSM_PCHAN_TCH_H)
100 count += 2;
101 continue;
102
103 default:
104 /* Not dynamic, not applicable. */
105 continue;
106 }
107 }
108
109 if (ts_pchan_is != pchan)
110 continue;
111 /* check if all sub-slots are allocated yet */
112 for (ss = 0; ss < ts_subslots(ts); ss++) {
113 struct gsm_lchan *lc = &ts->lchan[ss];
114 if (lc->type == GSM_LCHAN_NONE &&
115 lc->state == LCHAN_S_NONE)
116 count++;
117 }
118 }
119
120 return count;
121}
122
123/* Count number of free TS of given pchan type */
124int bts_count_free_ts(struct gsm_bts *bts, enum gsm_phys_chan_config pchan)
125{
126 struct gsm_bts_trx *trx;
127 int count = 0;
128
129 llist_for_each_entry(trx, &bts->trx_list, list)
130 count += trx_count_free_ts(trx, pchan);
131
132 return count;
133}
134
Harald Welte8470bf22008-12-25 23:28:35 +0000135static struct gsm_lchan *
Neels Hofmeyrfdd9ad72016-07-14 03:01:24 +0200136_lc_find_trx(struct gsm_bts_trx *trx, enum gsm_phys_chan_config pchan,
137 enum gsm_phys_chan_config dyn_as_pchan)
Harald Welte8470bf22008-12-25 23:28:35 +0000138{
Harald Welte8470bf22008-12-25 23:28:35 +0000139 struct gsm_bts_trx_ts *ts;
Andreas Eversberg0434efa2013-10-11 13:05:16 +0200140 int j, start, stop, dir, ss;
Neels Hofmeyrfdd9ad72016-07-14 03:01:24 +0200141 int check_subslots;
Harald Welte88367262009-08-10 13:25:55 +0200142
Harald Welte4c704542009-12-24 10:10:16 +0100143 if (!trx_is_usable(trx))
144 return NULL;
145
Andreas Eversberg0434efa2013-10-11 13:05:16 +0200146 if (trx->bts->chan_alloc_reverse) {
147 /* check TS 7..0 */
148 start = 7;
149 stop = -1;
150 dir = -1;
151 } else {
152 /* check TS 0..7 */
153 start = 0;
154 stop = 8;
155 dir = 1;
156 }
157
158 for (j = start; j != stop; j += dir) {
Harald Weltefc0d9522009-08-10 13:46:55 +0200159 ts = &trx->ts[j];
Harald Welte4c704542009-12-24 10:10:16 +0100160 if (!ts_is_usable(ts))
161 continue;
Neels Hofmeyra6685252016-06-06 12:53:25 +0200162 if (ts->pchan != pchan)
Harald Weltefc0d9522009-08-10 13:46:55 +0200163 continue;
Neels Hofmeyrfdd9ad72016-07-14 03:01:24 +0200164
165 /*
166 * Allocation for fully dynamic timeslots
167 * (does not apply for ip.access style GSM_PCHAN_TCH_F_PDCH)
168 *
169 * Note the special nature of a dynamic timeslot in PDCH mode:
170 * in PDCH mode, typically, lchan->type is GSM_LCHAN_NONE and
171 * lchan->state is LCHAN_S_NONE -- an otherwise unused slot
172 * becomes PDCH implicitly. In the same sense, this channel
173 * allocator will never be asked to find an available PDCH
174 * slot; only TCH/F or TCH/H will be requested, and PDCH mode
175 * means that it is available for switchover.
176 *
177 * A dynamic timeslot in PDCH mode may be switched to TCH/F or
178 * TCH/H. If a dyn TS is already in TCH/F or TCH/H mode, it
179 * means that it is in use and its mode can't be switched.
180 *
181 * The logic concerning channels for TCH/F is trivial: there is
182 * only one channel, so a dynamic TS in TCH/F mode is already
183 * taken and not available for allocation. For TCH/H, we need
184 * to check whether a dynamic timeslot is already in TCH/H mode
185 * and whether one of the two channels is still available.
186 */
Neels Hofmeyre14f4b92016-12-05 16:48:36 +0100187 switch (pchan) {
188 case GSM_PCHAN_TCH_F_TCH_H_PDCH:
Neels Hofmeyrfdd9ad72016-07-14 03:01:24 +0200189 if (ts->dyn.pchan_is != ts->dyn.pchan_want) {
190 /* The TS's mode is being switched. Not
191 * available anymore/yet. */
192 DEBUGP(DRLL, "%s already in switchover\n",
193 gsm_ts_and_pchan_name(ts));
194 continue;
195 }
196 if (ts->dyn.pchan_is == GSM_PCHAN_PDCH) {
197 /* This slot is available. Still check for
198 * error states to be sure; in all cases the
199 * first lchan will be used. */
200 if (ts->lchan->state != LCHAN_S_NONE
201 && ts->lchan->state != LCHAN_S_ACTIVE)
202 continue;
203 return ts->lchan;
204 }
Neels Hofmeyre14f4b92016-12-05 16:48:36 +0100205 if (ts->dyn.pchan_is != dyn_as_pchan)
206 /* not applicable. */
Neels Hofmeyrfdd9ad72016-07-14 03:01:24 +0200207 continue;
Neels Hofmeyre14f4b92016-12-05 16:48:36 +0100208 /* The requested type matches the dynamic timeslot's
209 * current mode. A channel may still be available
210 * (think TCH/H). */
211 check_subslots = ts_subslots(ts);
212 break;
213
Neels Hofmeyr8825c692016-12-05 16:50:47 +0100214 case GSM_PCHAN_TCH_F_PDCH:
215 /* Available for voice when in PDCH mode */
216 if (ts_pchan(ts) != GSM_PCHAN_PDCH)
217 continue;
218 /* Subslots of a PDCH ts don't need to be checked. */
219 return ts->lchan;
220
Neels Hofmeyre14f4b92016-12-05 16:48:36 +0100221 default:
Neels Hofmeyrfdd9ad72016-07-14 03:01:24 +0200222 /* Not a dynamic channel, there is only one pchan kind: */
Neels Hofmeyr54860252016-07-29 18:13:38 +0200223 check_subslots = ts_subslots(ts);
Neels Hofmeyre14f4b92016-12-05 16:48:36 +0100224 break;
Neels Hofmeyrfdd9ad72016-07-14 03:01:24 +0200225 }
226
227 /* Is a sub-slot still available? */
228 for (ss = 0; ss < check_subslots; ss++) {
Harald Weltefc0d9522009-08-10 13:46:55 +0200229 struct gsm_lchan *lc = &ts->lchan[ss];
Harald Welte (local)3e460312009-12-27 18:12:29 +0100230 if (lc->type == GSM_LCHAN_NONE &&
231 lc->state == LCHAN_S_NONE)
Harald Weltefc0d9522009-08-10 13:46:55 +0200232 return lc;
Harald Welte8470bf22008-12-25 23:28:35 +0000233 }
234 }
Harald Weltec0d83b02010-03-28 15:58:03 +0800235
Harald Weltefc0d9522009-08-10 13:46:55 +0200236 return NULL;
237}
238
239static struct gsm_lchan *
Neels Hofmeyrfdd9ad72016-07-14 03:01:24 +0200240_lc_dyn_find_bts(struct gsm_bts *bts, enum gsm_phys_chan_config pchan,
241 enum gsm_phys_chan_config dyn_as_pchan)
Harald Weltefc0d9522009-08-10 13:46:55 +0200242{
243 struct gsm_bts_trx *trx;
Harald Weltefc0d9522009-08-10 13:46:55 +0200244 struct gsm_lchan *lc;
245
246 if (bts->chan_alloc_reverse) {
247 llist_for_each_entry_reverse(trx, &bts->trx_list, list) {
Neels Hofmeyrfdd9ad72016-07-14 03:01:24 +0200248 lc = _lc_find_trx(trx, pchan, dyn_as_pchan);
Harald Weltefc0d9522009-08-10 13:46:55 +0200249 if (lc)
250 return lc;
251 }
252 } else {
253 llist_for_each_entry(trx, &bts->trx_list, list) {
Neels Hofmeyrfdd9ad72016-07-14 03:01:24 +0200254 lc = _lc_find_trx(trx, pchan, dyn_as_pchan);
Harald Weltefc0d9522009-08-10 13:46:55 +0200255 if (lc)
256 return lc;
257 }
258 }
259
Harald Weltef86852c2015-01-01 12:46:26 +0100260 return NULL;
Harald Welte8470bf22008-12-25 23:28:35 +0000261}
262
Neels Hofmeyrfdd9ad72016-07-14 03:01:24 +0200263static struct gsm_lchan *
264_lc_find_bts(struct gsm_bts *bts, enum gsm_phys_chan_config pchan)
265{
266 return _lc_dyn_find_bts(bts, pchan, GSM_PCHAN_NONE);
267}
268
Neels Hofmeyra6685252016-06-06 12:53:25 +0200269/* Allocate a logical channel.
270 *
Neels Hofmeyrc6926d02016-07-14 02:51:13 +0200271 * Dynamic channel types: we always prefer a dedicated TS, and only pick +
272 * switch a dynamic TS if no pure TS of the requested PCHAN is available.
273 *
274 * TCH_F/PDCH: if we pick a PDCH ACT style dynamic TS as TCH/F channel, PDCH
275 * will be disabled in rsl_chan_activate_lchan(); there is no need to check
276 * whether PDCH mode is currently active, here.
Neels Hofmeyra6685252016-06-06 12:53:25 +0200277 */
Holger Hans Peter Freyther457c2a82010-09-06 08:58:42 +0800278struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type,
279 int allow_bigger)
Harald Welte8470bf22008-12-25 23:28:35 +0000280{
281 struct gsm_lchan *lchan = NULL;
Harald Welte30f1f372014-12-28 15:00:45 +0100282 enum gsm_phys_chan_config first, first_cbch, second, second_cbch;
Harald Welte8470bf22008-12-25 23:28:35 +0000283
284 switch (type) {
285 case GSM_LCHAN_SDCCH:
Harald Welte65676fe2009-08-10 14:44:24 +0200286 if (bts->chan_alloc_reverse) {
287 first = GSM_PCHAN_SDCCH8_SACCH8C;
Harald Welte30f1f372014-12-28 15:00:45 +0100288 first_cbch = GSM_PCHAN_SDCCH8_SACCH8C_CBCH;
Harald Welte65676fe2009-08-10 14:44:24 +0200289 second = GSM_PCHAN_CCCH_SDCCH4;
Harald Welte30f1f372014-12-28 15:00:45 +0100290 second_cbch = GSM_PCHAN_CCCH_SDCCH4_CBCH;
Harald Welte65676fe2009-08-10 14:44:24 +0200291 } else {
292 first = GSM_PCHAN_CCCH_SDCCH4;
Harald Welte30f1f372014-12-28 15:00:45 +0100293 first_cbch = GSM_PCHAN_CCCH_SDCCH4_CBCH;
Harald Welte65676fe2009-08-10 14:44:24 +0200294 second = GSM_PCHAN_SDCCH8_SACCH8C;
Harald Welte30f1f372014-12-28 15:00:45 +0100295 second_cbch = GSM_PCHAN_SDCCH8_SACCH8C_CBCH;
Harald Welte65676fe2009-08-10 14:44:24 +0200296 }
297
298 lchan = _lc_find_bts(bts, first);
Harald Welte8470bf22008-12-25 23:28:35 +0000299 if (lchan == NULL)
Harald Welte30f1f372014-12-28 15:00:45 +0100300 lchan = _lc_find_bts(bts, first_cbch);
301 if (lchan == NULL)
Harald Welte65676fe2009-08-10 14:44:24 +0200302 lchan = _lc_find_bts(bts, second);
Harald Welte30f1f372014-12-28 15:00:45 +0100303 if (lchan == NULL)
304 lchan = _lc_find_bts(bts, second_cbch);
Holger Hans Peter Freyther457c2a82010-09-06 08:58:42 +0800305
306 /* allow to assign bigger channels */
307 if (allow_bigger) {
308 if (lchan == NULL) {
309 lchan = _lc_find_bts(bts, GSM_PCHAN_TCH_H);
Neels Hofmeyrf5713a52016-06-06 12:57:22 +0200310 if (lchan)
311 type = GSM_LCHAN_TCH_H;
Holger Hans Peter Freyther457c2a82010-09-06 08:58:42 +0800312 }
313
314 if (lchan == NULL) {
315 lchan = _lc_find_bts(bts, GSM_PCHAN_TCH_F);
Neels Hofmeyrf5713a52016-06-06 12:57:22 +0200316 if (lchan)
317 type = GSM_LCHAN_TCH_F;
Holger Hans Peter Freyther457c2a82010-09-06 08:58:42 +0800318 }
Neels Hofmeyra6685252016-06-06 12:53:25 +0200319
320 /* try dynamic TCH/F_PDCH */
321 if (lchan == NULL) {
322 lchan = _lc_find_bts(bts, GSM_PCHAN_TCH_F_PDCH);
323 /* TCH/F_PDCH will be used as TCH/F */
324 if (lchan)
325 type = GSM_LCHAN_TCH_F;
326 }
Neels Hofmeyrfdd9ad72016-07-14 03:01:24 +0200327
328 /* try fully dynamic TCH/F_TCH/H_PDCH */
329 if (lchan == NULL) {
330 lchan = _lc_dyn_find_bts(bts, GSM_PCHAN_TCH_F_TCH_H_PDCH,
331 GSM_PCHAN_TCH_H);
332 if (lchan)
333 type = GSM_LCHAN_TCH_H;
334 }
335 /*
336 * No need to check fully dynamic channels for TCH/F:
337 * if no TCH/H was available, neither will be TCH/F.
338 */
Holger Hans Peter Freyther457c2a82010-09-06 08:58:42 +0800339 }
Harald Welte8470bf22008-12-25 23:28:35 +0000340 break;
341 case GSM_LCHAN_TCH_F:
Harald Weltefc0d9522009-08-10 13:46:55 +0200342 lchan = _lc_find_bts(bts, GSM_PCHAN_TCH_F);
Harald Weltea4c63b02014-05-18 22:23:26 +0200343 /* If we don't have TCH/F available, fall-back to TCH/H */
344 if (!lchan) {
345 lchan = _lc_find_bts(bts, GSM_PCHAN_TCH_H);
Neels Hofmeyrf5713a52016-06-06 12:57:22 +0200346 if (lchan)
347 type = GSM_LCHAN_TCH_H;
Harald Weltea4c63b02014-05-18 22:23:26 +0200348 }
Neels Hofmeyra6685252016-06-06 12:53:25 +0200349 /* If we don't have TCH/H either, try dynamic TCH/F_PDCH */
350 if (!lchan) {
351 lchan = _lc_find_bts(bts, GSM_PCHAN_TCH_F_PDCH);
352 /* TCH/F_PDCH used as TCH/F -- here, type is already
353 * set to GSM_LCHAN_TCH_F, but for clarity's sake... */
354 if (lchan)
355 type = GSM_LCHAN_TCH_F;
356 }
Neels Hofmeyr5f0c71b2016-07-23 20:15:28 +0200357
Neels Hofmeyrfdd9ad72016-07-14 03:01:24 +0200358 /* Try fully dynamic TCH/F_TCH/H_PDCH as TCH/F... */
Neels Hofmeyr5f0c71b2016-07-23 20:15:28 +0200359 if (!lchan && bts->network->dyn_ts_allow_tch_f) {
Neels Hofmeyrfdd9ad72016-07-14 03:01:24 +0200360 lchan = _lc_dyn_find_bts(bts,
361 GSM_PCHAN_TCH_F_TCH_H_PDCH,
362 GSM_PCHAN_TCH_F);
363 if (lchan)
364 type = GSM_LCHAN_TCH_F;
365 }
366 /* ...and as TCH/H. */
367 if (!lchan) {
368 lchan = _lc_dyn_find_bts(bts,
369 GSM_PCHAN_TCH_F_TCH_H_PDCH,
370 GSM_PCHAN_TCH_H);
371 if (lchan)
372 type = GSM_LCHAN_TCH_H;
373 }
Harald Welte8470bf22008-12-25 23:28:35 +0000374 break;
375 case GSM_LCHAN_TCH_H:
Alexander Couzensfbd96f52016-08-29 18:40:02 +0200376 lchan = _lc_find_bts(bts, GSM_PCHAN_TCH_H);
Harald Welte210c8502009-12-12 20:58:20 +0100377 /* If we don't have TCH/H available, fall-back to TCH/F */
Harald Welte487e6be2009-12-12 21:16:38 +0100378 if (!lchan) {
Harald Welte210c8502009-12-12 20:58:20 +0100379 lchan = _lc_find_bts(bts, GSM_PCHAN_TCH_F);
Neels Hofmeyrf5713a52016-06-06 12:57:22 +0200380 if (lchan)
381 type = GSM_LCHAN_TCH_F;
Harald Welte487e6be2009-12-12 21:16:38 +0100382 }
Neels Hofmeyrfdd9ad72016-07-14 03:01:24 +0200383 /* No dedicated TCH/x available -- try fully dynamic
384 * TCH/F_TCH/H_PDCH */
385 if (!lchan) {
386 lchan = _lc_dyn_find_bts(bts,
387 GSM_PCHAN_TCH_F_TCH_H_PDCH,
388 GSM_PCHAN_TCH_H);
389 if (lchan)
390 type = GSM_LCHAN_TCH_H;
391 }
392 /*
393 * No need to check TCH/F_TCH/H_PDCH channels for TCH/F:
394 * if no TCH/H was available, neither will be TCH/F.
395 */
Neels Hofmeyra6685252016-06-06 12:53:25 +0200396 /* If we don't have TCH/F either, try dynamic TCH/F_PDCH */
397 if (!lchan) {
398 lchan = _lc_find_bts(bts, GSM_PCHAN_TCH_F_PDCH);
399 if (lchan)
400 type = GSM_LCHAN_TCH_F;
401 }
Harald Welte8470bf22008-12-25 23:28:35 +0000402 break;
403 default:
Harald Welteb1d4c8e2009-12-17 23:10:46 +0100404 LOGP(DRLL, LOGL_ERROR, "Unknown gsm_chan_t %u\n", type);
Harald Welte8470bf22008-12-25 23:28:35 +0000405 }
406
Holger Freytherc6ea9db2008-12-30 19:18:21 +0000407 if (lchan) {
Harald Welte8470bf22008-12-25 23:28:35 +0000408 lchan->type = type;
Holger Freytherc6ea9db2008-12-30 19:18:21 +0000409
Neels Hofmeyrd1c0e372016-07-25 12:33:02 +0200410 LOGP(DRLL, LOGL_INFO, "%s Allocating lchan=%u as %s\n",
411 gsm_ts_and_pchan_name(lchan->ts),
412 lchan->nr, gsm_lchant_name(lchan->type));
413
Andreas Eversberg970b4342013-06-01 16:46:39 +0200414 /* reset measurement report counter and index */
415 lchan->meas_rep_count = 0;
416 lchan->meas_rep_idx = 0;
Neels Hofmeyr35ba85c2018-02-12 16:47:40 +0100417 lchan->meas_rep_last_seen_nr = 255;
Andreas Eversberg970b4342013-06-01 16:46:39 +0200418
Holger Hans Peter Freyther5ba6f482009-10-28 14:23:39 +0100419 /* clear sapis */
Holger Hans Peter Freyther45b02432009-11-18 22:59:51 +0100420 memset(lchan->sapis, 0, ARRAY_SIZE(lchan->sapis));
Holger Hans Peter Freyther5ba6f482009-10-28 14:23:39 +0100421
Holger Hans Peter Freytherea528022009-11-18 22:57:02 +0100422 /* clear multi rate config */
Andreas Eversberg73266522014-01-19 11:47:44 +0100423 memset(&lchan->mr_ms_lv, 0, sizeof(lchan->mr_ms_lv));
424 memset(&lchan->mr_bts_lv, 0, sizeof(lchan->mr_bts_lv));
Holger Hans Peter Freyther454140e2014-12-28 12:08:28 +0100425 lchan->broken_reason = "";
Harald Weltec0d83b02010-03-28 15:58:03 +0800426 } else {
427 struct challoc_signal_data sig;
Neels Hofmeyrd1c0e372016-07-25 12:33:02 +0200428
429 LOGP(DRLL, LOGL_ERROR, "Failed to allocate %s channel\n",
430 gsm_lchant_name(type));
431
Harald Weltec0d83b02010-03-28 15:58:03 +0800432 sig.bts = bts;
433 sig.type = type;
Pablo Neira Ayusobbc5b992011-05-06 12:12:31 +0200434 osmo_signal_dispatch(SS_CHALLOC, S_CHALLOC_ALLOC_FAIL, &sig);
Holger Freytherc6ea9db2008-12-30 19:18:21 +0000435 }
Harald Welte8470bf22008-12-25 23:28:35 +0000436
437 return lchan;
438}
439
440/* Free a logical channel */
441void lchan_free(struct gsm_lchan *lchan)
442{
Harald Weltec0d83b02010-03-28 15:58:03 +0800443 struct challoc_signal_data sig;
Harald Welted12b0fd2009-12-15 21:36:05 +0100444 int i;
445
Harald Weltec0d83b02010-03-28 15:58:03 +0800446 sig.type = lchan->type;
Harald Welte8470bf22008-12-25 23:28:35 +0000447 lchan->type = GSM_LCHAN_NONE;
Holger Hans Peter Freyther2412a072010-06-28 15:47:12 +0800448
449
450 if (lchan->conn) {
Holger Hans Peter Freyther08eebd52010-12-27 13:28:20 +0100451 struct lchan_signal_data sig;
452
Holger Hans Peter Freyther2412a072010-06-28 15:47:12 +0800453 /* We might kill an active channel... */
Holger Hans Peter Freyther08eebd52010-12-27 13:28:20 +0100454 sig.lchan = lchan;
455 sig.mr = NULL;
Pablo Neira Ayusobbc5b992011-05-06 12:12:31 +0200456 osmo_signal_dispatch(SS_LCHAN, S_LCHAN_UNEXPECTED_RELEASE, &sig);
Holger Freyther12aa50d2009-01-01 18:02:05 +0000457 }
Holger Freytherc6ea9db2008-12-30 19:18:21 +0000458
459 /* stop the timer */
Pablo Neira Ayusobf540cb2011-05-06 12:11:06 +0200460 osmo_timer_del(&lchan->T3101);
Holger Freytherc6ea9db2008-12-30 19:18:21 +0000461
Harald Welted12b0fd2009-12-15 21:36:05 +0100462 /* clear cached measuement reports */
463 lchan->meas_rep_idx = 0;
464 for (i = 0; i < ARRAY_SIZE(lchan->meas_rep); i++) {
465 lchan->meas_rep[i].flags = 0;
466 lchan->meas_rep[i].nr = 0;
467 }
Harald Weltef7c28b02009-12-21 13:30:17 +0100468 for (i = 0; i < ARRAY_SIZE(lchan->neigh_meas); i++)
469 lchan->neigh_meas[i].arfcn = 0;
Harald Welted12b0fd2009-12-15 21:36:05 +0100470
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +0800471 if (lchan->rqd_ref) {
472 talloc_free(lchan->rqd_ref);
473 lchan->rqd_ref = NULL;
474 lchan->rqd_ta = 0;
475 }
476
Harald Weltec0d83b02010-03-28 15:58:03 +0800477 sig.lchan = lchan;
478 sig.bts = lchan->ts->trx->bts;
Pablo Neira Ayusobbc5b992011-05-06 12:12:31 +0200479 osmo_signal_dispatch(SS_CHALLOC, S_CHALLOC_FREED, &sig);
Harald Weltec0d83b02010-03-28 15:58:03 +0800480
Holger Hans Peter Freyther2412a072010-06-28 15:47:12 +0800481 if (lchan->conn) {
Holger Hans Peter Freyther40494552010-06-28 17:09:29 +0800482 LOGP(DRLL, LOGL_ERROR, "the subscriber connection should be gone.\n");
Holger Hans Peter Freyther2412a072010-06-28 15:47:12 +0800483 lchan->conn = NULL;
484 }
485
Harald Welte8470bf22008-12-25 23:28:35 +0000486 /* FIXME: ts_free() the timeslot, if we're the last logical
487 * channel using it */
488}
Holger Freytherc6ea9db2008-12-30 19:18:21 +0000489
Holger Hans Peter Freyther135f7972010-04-15 11:21:02 +0200490/*
491 * There was an error with the TRX and we need to forget
492 * any state so that a lchan can be allocated again after
493 * the trx is fully usable.
Holger Hans Peter Freytherf7a1c232010-06-22 12:19:06 +0800494 *
495 * This should be called after lchan_free to force a channel
496 * be available for allocation again. This means that this
497 * method will stop the "delay after error"-timer and set the
498 * state to LCHAN_S_NONE.
Holger Hans Peter Freyther135f7972010-04-15 11:21:02 +0200499 */
500void lchan_reset(struct gsm_lchan *lchan)
501{
Pablo Neira Ayusobf540cb2011-05-06 12:11:06 +0200502 osmo_timer_del(&lchan->T3101);
Holger Hans Peter Freytherb3489392011-12-28 16:21:05 +0100503 osmo_timer_del(&lchan->T3109);
Pablo Neira Ayusobf540cb2011-05-06 12:11:06 +0200504 osmo_timer_del(&lchan->T3111);
505 osmo_timer_del(&lchan->error_timer);
Holger Hans Peter Freyther135f7972010-04-15 11:21:02 +0200506
507 lchan->type = GSM_LCHAN_NONE;
Maxdc10ce92017-09-06 18:20:36 +0200508 rsl_lchan_set_state(lchan, LCHAN_S_NONE);
Holger Hans Peter Freyther135f7972010-04-15 11:21:02 +0200509}
510
Holger Hans Peter Freyther4b85a322010-07-29 17:09:36 +0800511/* Drive the release process of the lchan */
Holger Hans Peter Freyther85825352011-12-27 22:24:17 +0100512static void _lchan_handle_release(struct gsm_lchan *lchan,
Holger Hans Peter Freytherb3489392011-12-28 16:21:05 +0100513 int sacch_deact, int mode)
Holger Hans Peter Freyther4b85a322010-07-29 17:09:36 +0800514{
Holger Hans Peter Freyther85825352011-12-27 22:24:17 +0100515 /* Release all SAPIs on the local end and continue */
516 rsl_release_sapis_from(lchan, 1, RSL_REL_LOCAL_END);
Holger Hans Peter Freyther4b85a322010-07-29 17:09:36 +0800517
Holger Hans Peter Freyther85825352011-12-27 22:24:17 +0100518 /*
519 * Shall we send a RR Release, start T3109 and wait for the
520 * release indication from the BTS or just take it down (e.g.
521 * on assignment requests)
522 */
Holger Hans Peter Freytherb3489392011-12-28 16:21:05 +0100523 if (sacch_deact) {
Holger Hans Peter Freyther4b85a322010-07-29 17:09:36 +0800524 gsm48_send_rr_release(lchan);
Holger Hans Peter Freytherb3489392011-12-28 16:21:05 +0100525
526 /* Deactivate the SACCH on the BTS side */
527 rsl_deact_sacch(lchan);
528 rsl_start_t3109(lchan);
Holger Hans Peter Freyther006e3d82012-12-25 23:45:14 +0100529 } else if (lchan->sapis[0] == LCHAN_SAPI_UNUSED) {
530 rsl_direct_rf_release(lchan);
Holger Hans Peter Freytherb3489392011-12-28 16:21:05 +0100531 } else {
Holger Hans Peter Freyther85825352011-12-27 22:24:17 +0100532 rsl_release_request(lchan, 0, mode);
Holger Hans Peter Freytherb3489392011-12-28 16:21:05 +0100533 }
Holger Hans Peter Freyther4b85a322010-07-29 17:09:36 +0800534}
Holger Hans Peter Freyther135f7972010-04-15 11:21:02 +0200535
Holger Freyther67b4b9a2009-01-01 03:46:11 +0000536/* Consider releasing the channel now */
Holger Hans Peter Freyther5ca825e2012-12-06 12:01:38 +0100537int lchan_release(struct gsm_lchan *lchan, int sacch_deact, enum rsl_rel_mode mode)
Holger Freytherc6ea9db2008-12-30 19:18:21 +0000538{
Holger Hans Peter Freyther4b85a322010-07-29 17:09:36 +0800539 DEBUGP(DRLL, "%s starting release sequence\n", gsm_lchan_name(lchan));
Holger Hans Peter Freyther63d18b52010-04-10 00:14:55 +0200540 rsl_lchan_set_state(lchan, LCHAN_S_REL_REQ);
Holger Hans Peter Freyther4b85a322010-07-29 17:09:36 +0800541
Holger Hans Peter Freytherabf962b2010-11-14 16:04:46 +0100542 lchan->conn = NULL;
Holger Hans Peter Freyther85825352011-12-27 22:24:17 +0100543 _lchan_handle_release(lchan, sacch_deact, mode);
Holger Freyther67b4b9a2009-01-01 03:46:11 +0000544 return 1;
545}
546
Neels Hofmeyr2afffd52016-09-25 17:01:20 +0200547void bts_chan_load(struct pchan_load *cl, const struct gsm_bts *bts)
Harald Welteb908cb72009-12-22 13:09:29 +0100548{
549 struct gsm_bts_trx *trx;
550
551 llist_for_each_entry(trx, &bts->trx_list, list) {
552 int i;
553
554 /* skip administratively deactivated tranxsceivers */
Harald Welted64c0bc2011-05-30 12:07:53 +0200555 if (!nm_is_running(&trx->mo.nm_state) ||
556 !nm_is_running(&trx->bb_transc.mo.nm_state))
Harald Welteb908cb72009-12-22 13:09:29 +0100557 continue;
558
559 for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
560 struct gsm_bts_trx_ts *ts = &trx->ts[i];
561 struct load_counter *pl = &cl->pchan[ts->pchan];
562 int j;
Neels Hofmeyr36733802016-07-29 18:10:59 +0200563 int subslots;
Harald Welteb908cb72009-12-22 13:09:29 +0100564
565 /* skip administratively deactivated timeslots */
Harald Welted64c0bc2011-05-30 12:07:53 +0200566 if (!nm_is_running(&ts->mo.nm_state))
Harald Welteb908cb72009-12-22 13:09:29 +0100567 continue;
568
Neels Hofmeyr36733802016-07-29 18:10:59 +0200569 subslots = ts_subslots(ts);
570 for (j = 0; j < subslots; j++) {
Harald Welteb908cb72009-12-22 13:09:29 +0100571 struct gsm_lchan *lchan = &ts->lchan[j];
572
573 pl->total++;
574
575 switch (lchan->state) {
576 case LCHAN_S_NONE:
577 break;
578 default:
579 pl->used++;
580 break;
581 }
582 }
583 }
584 }
585}
586
587void network_chan_load(struct pchan_load *pl, struct gsm_network *net)
588{
589 struct gsm_bts *bts;
590
591 memset(pl, 0, sizeof(*pl));
592
593 llist_for_each_entry(bts, &net->bts_list, list)
Neels Hofmeyr2afffd52016-09-25 17:01:20 +0200594 bts_chan_load(pl, bts);
Harald Welteb908cb72009-12-22 13:09:29 +0100595}
Neels Hofmeyr2afffd52016-09-25 17:01:20 +0200596
Stefan Sperling6cee8932018-01-30 18:14:22 +0100597/* Update T3122 wait indicator based on samples of BTS channel load. */
598void
599bts_update_t3122_chan_load(struct gsm_bts *bts)
600{
601 struct pchan_load pl;
602 uint64_t used = 0;
603 uint32_t total = 0;
604 uint64_t load;
605 uint64_t wait_ind;
606 static const uint8_t min_wait_ind = GSM_T3122_DEFAULT;
607 static const uint8_t max_wait_ind = 128; /* max wait ~2 minutes */
608 int i;
609
Neels Hofmeyrf802f7f2018-02-15 18:46:39 +0100610 /* Ignore BTS that are not in operation, in order to not flood the log with "bogus channel load"
611 * messages */
612 if (!trx_is_usable(bts->c0))
613 return;
614
Stefan Sperling6cee8932018-01-30 18:14:22 +0100615 /* Sum up current load across all channels. */
616 memset(&pl, 0, sizeof(pl));
617 bts_chan_load(&pl, bts);
618 for (i = 0; i < ARRAY_SIZE(pl.pchan); i++) {
619 struct load_counter *lc = &pl.pchan[i];
620
621 /* Ignore samples too large for fixed-point calculations (shouldn't happen). */
622 if (lc->used > UINT16_MAX || lc->total > UINT16_MAX) {
623 LOGP(DRLL, LOGL_NOTICE, "(bts=%d) numbers in channel load sample "
624 "too large (used=%u / total=%u)\n", bts->nr, lc->used, lc->total);
625 continue;
626 }
627
628 used += lc->used;
629 total += lc->total;
630 }
631
632 /* Check for invalid samples (shouldn't happen). */
633 if (total == 0 || used > total) {
634 LOGP(DRLL, LOGL_NOTICE, "(bts=%d) bogus channel load sample (used=%lu / total=%u)\n",
635 bts->nr, used, total);
636 bts->T3122 = 0; /* disable override of network-wide default value */
637 bts->chan_load_samples_idx = 0; /* invalidate other samples collected so far */
638 return;
639 }
640
641 /* If we haven't got enough samples yet, store measurement for later use. */
642 if (bts->chan_load_samples_idx < ARRAY_SIZE(bts->chan_load_samples)) {
643 struct load_counter *sample = &bts->chan_load_samples[bts->chan_load_samples_idx++];
644 sample->total = (unsigned int)total;
645 sample->used = (unsigned int)used;
646 return;
647 }
648
649 /* We have enough samples and will overwrite our current samples later. */
650 bts->chan_load_samples_idx = 0;
651
652 /* Add all previous samples to the current sample. */
653 for (i = 0; i < ARRAY_SIZE(bts->chan_load_samples); i++) {
654 struct load_counter *sample = &bts->chan_load_samples[i];
655 total += sample->total;
656 used += sample->used;
657 }
658
659 used <<= 8; /* convert to fixed-point */
660
661 /* Log channel load average. */
662 load = ((used / total) * 100);
663 LOGP(DRLL, LOGL_DEBUG, "(bts=%d) channel load average is %lu.%.2lu%%\n",
664 bts->nr, (load & 0xffffff00) >> 8, (load & 0xff) / 10);
Stefan Sperling6442e432018-02-06 14:44:54 +0100665 bts->chan_load_avg = ((load & 0xffffff00) >> 8);
666 OSMO_ASSERT(bts->chan_load_avg <= 100);
667 osmo_stat_item_set(bts->bts_statg->items[BTS_STAT_CHAN_LOAD_AVERAGE], bts->chan_load_avg);
Stefan Sperling6cee8932018-01-30 18:14:22 +0100668
669 /* Calculate new T3122 wait indicator. */
670 wait_ind = ((used / total) * max_wait_ind);
671 wait_ind >>= 8; /* convert from fixed-point to integer */
672 if (wait_ind < min_wait_ind)
673 wait_ind = min_wait_ind;
674 else if (wait_ind > max_wait_ind)
675 wait_ind = max_wait_ind;
676
677 LOGP(DRLL, LOGL_DEBUG, "(bts=%d) T3122 wait indicator set to %lu seconds\n", bts->nr, wait_ind);
678 bts->T3122 = (uint8_t)wait_ind;
Stefan Sperling81dc9e72018-02-05 17:34:36 +0100679 osmo_stat_item_set(bts->bts_statg->items[BTS_STAT_T3122], wait_ind);
Stefan Sperling6cee8932018-01-30 18:14:22 +0100680}