blob: 7f0aa31aa41a1a55d13c300c1b08c55f3042534a [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>
Stefan Sperling5b6aa652018-04-09 13:31:51 +020027#include <inttypes.h>
Harald Welte8470bf22008-12-25 23:28:35 +000028
Neels Hofmeyrc0164792017-09-04 15:15:32 +020029#include <osmocom/bsc/chan_alloc.h>
30#include <osmocom/bsc/abis_nm.h>
31#include <osmocom/bsc/abis_rsl.h>
32#include <osmocom/bsc/debug.h>
Neels Hofmeyrc0164792017-09-04 15:15:32 +020033#include <osmocom/bsc/signal.h>
Neels Hofmeyr31f525e2018-05-14 18:14:15 +020034#include <osmocom/bsc/timeslot_fsm.h>
35#include <osmocom/bsc/lchan_fsm.h>
Neels Hofmeyr62427422018-07-24 16:18:15 +020036#include <osmocom/bsc/gsm_04_08_rr.h>
Holger Freytherc6ea9db2008-12-30 19:18:21 +000037
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010038#include <osmocom/core/talloc.h>
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +080039
Neels Hofmeyr2afffd52016-09-25 17:01:20 +020040void bts_chan_load(struct pchan_load *cl, const struct gsm_bts *bts)
Harald Welteb908cb72009-12-22 13:09:29 +010041{
42 struct gsm_bts_trx *trx;
43
44 llist_for_each_entry(trx, &bts->trx_list, list) {
45 int i;
46
47 /* skip administratively deactivated tranxsceivers */
Harald Welted64c0bc2011-05-30 12:07:53 +020048 if (!nm_is_running(&trx->mo.nm_state) ||
49 !nm_is_running(&trx->bb_transc.mo.nm_state))
Harald Welteb908cb72009-12-22 13:09:29 +010050 continue;
51
52 for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
53 struct gsm_bts_trx_ts *ts = &trx->ts[i];
Neels Hofmeyr31f525e2018-05-14 18:14:15 +020054 struct load_counter *pl = &cl->pchan[ts->pchan_on_init];
55 struct gsm_lchan *lchan;
Harald Welteb908cb72009-12-22 13:09:29 +010056
57 /* skip administratively deactivated timeslots */
Harald Welted64c0bc2011-05-30 12:07:53 +020058 if (!nm_is_running(&ts->mo.nm_state))
Harald Welteb908cb72009-12-22 13:09:29 +010059 continue;
60
Neels Hofmeyr31f525e2018-05-14 18:14:15 +020061 ts_for_each_lchan(lchan, ts) {
Harald Welte744886a2019-05-23 21:58:21 +020062 /* don't even count CBCH slots in total */
63 if (lchan->type == GSM_LCHAN_CBCH)
64 continue;
65
Harald Welteb908cb72009-12-22 13:09:29 +010066 pl->total++;
67
Neels Hofmeyr31f525e2018-05-14 18:14:15 +020068 switch (lchan->fi->state) {
69 case LCHAN_ST_UNUSED:
Harald Welteb908cb72009-12-22 13:09:29 +010070 break;
71 default:
72 pl->used++;
73 break;
74 }
75 }
76 }
77 }
78}
79
80void network_chan_load(struct pchan_load *pl, struct gsm_network *net)
81{
82 struct gsm_bts *bts;
83
84 memset(pl, 0, sizeof(*pl));
85
86 llist_for_each_entry(bts, &net->bts_list, list)
Neels Hofmeyr2afffd52016-09-25 17:01:20 +020087 bts_chan_load(pl, bts);
Harald Welteb908cb72009-12-22 13:09:29 +010088}
Neels Hofmeyr2afffd52016-09-25 17:01:20 +020089
Stefan Sperling6cee8932018-01-30 18:14:22 +010090/* Update T3122 wait indicator based on samples of BTS channel load. */
91void
92bts_update_t3122_chan_load(struct gsm_bts *bts)
93{
94 struct pchan_load pl;
95 uint64_t used = 0;
96 uint32_t total = 0;
97 uint64_t load;
98 uint64_t wait_ind;
99 static const uint8_t min_wait_ind = GSM_T3122_DEFAULT;
100 static const uint8_t max_wait_ind = 128; /* max wait ~2 minutes */
101 int i;
102
Neels Hofmeyrf802f7f2018-02-15 18:46:39 +0100103 /* Ignore BTS that are not in operation, in order to not flood the log with "bogus channel load"
104 * messages */
105 if (!trx_is_usable(bts->c0))
106 return;
107
Stefan Sperling6cee8932018-01-30 18:14:22 +0100108 /* Sum up current load across all channels. */
109 memset(&pl, 0, sizeof(pl));
110 bts_chan_load(&pl, bts);
111 for (i = 0; i < ARRAY_SIZE(pl.pchan); i++) {
112 struct load_counter *lc = &pl.pchan[i];
113
114 /* Ignore samples too large for fixed-point calculations (shouldn't happen). */
115 if (lc->used > UINT16_MAX || lc->total > UINT16_MAX) {
116 LOGP(DRLL, LOGL_NOTICE, "(bts=%d) numbers in channel load sample "
117 "too large (used=%u / total=%u)\n", bts->nr, lc->used, lc->total);
118 continue;
119 }
120
121 used += lc->used;
122 total += lc->total;
123 }
124
125 /* Check for invalid samples (shouldn't happen). */
126 if (total == 0 || used > total) {
Pau Espin Pedrolfa422552018-04-19 14:31:13 +0200127 LOGP(DRLL, LOGL_NOTICE, "(bts=%d) bogus channel load sample (used=%"PRIu64" / total=%"PRIu32")\n",
Stefan Sperling6cee8932018-01-30 18:14:22 +0100128 bts->nr, used, total);
129 bts->T3122 = 0; /* disable override of network-wide default value */
130 bts->chan_load_samples_idx = 0; /* invalidate other samples collected so far */
131 return;
132 }
133
134 /* If we haven't got enough samples yet, store measurement for later use. */
135 if (bts->chan_load_samples_idx < ARRAY_SIZE(bts->chan_load_samples)) {
136 struct load_counter *sample = &bts->chan_load_samples[bts->chan_load_samples_idx++];
137 sample->total = (unsigned int)total;
138 sample->used = (unsigned int)used;
139 return;
140 }
141
142 /* We have enough samples and will overwrite our current samples later. */
143 bts->chan_load_samples_idx = 0;
144
145 /* Add all previous samples to the current sample. */
146 for (i = 0; i < ARRAY_SIZE(bts->chan_load_samples); i++) {
147 struct load_counter *sample = &bts->chan_load_samples[i];
148 total += sample->total;
149 used += sample->used;
150 }
151
152 used <<= 8; /* convert to fixed-point */
153
154 /* Log channel load average. */
155 load = ((used / total) * 100);
Stefan Sperling5b6aa652018-04-09 13:31:51 +0200156 LOGP(DRLL, LOGL_DEBUG, "(bts=%d) channel load average is %"PRIu64".%.2"PRIu64"%%\n",
Stefan Sperling6cee8932018-01-30 18:14:22 +0100157 bts->nr, (load & 0xffffff00) >> 8, (load & 0xff) / 10);
Stefan Sperling6442e432018-02-06 14:44:54 +0100158 bts->chan_load_avg = ((load & 0xffffff00) >> 8);
159 OSMO_ASSERT(bts->chan_load_avg <= 100);
160 osmo_stat_item_set(bts->bts_statg->items[BTS_STAT_CHAN_LOAD_AVERAGE], bts->chan_load_avg);
Stefan Sperling6cee8932018-01-30 18:14:22 +0100161
162 /* Calculate new T3122 wait indicator. */
163 wait_ind = ((used / total) * max_wait_ind);
164 wait_ind >>= 8; /* convert from fixed-point to integer */
165 if (wait_ind < min_wait_ind)
166 wait_ind = min_wait_ind;
167 else if (wait_ind > max_wait_ind)
168 wait_ind = max_wait_ind;
169
Pau Espin Pedrolfa422552018-04-19 14:31:13 +0200170 LOGP(DRLL, LOGL_DEBUG, "(bts=%d) T3122 wait indicator set to %"PRIu64" seconds\n", bts->nr, wait_ind);
Stefan Sperling6cee8932018-01-30 18:14:22 +0100171 bts->T3122 = (uint8_t)wait_ind;
Stefan Sperling81dc9e72018-02-05 17:34:36 +0100172 osmo_stat_item_set(bts->bts_statg->items[BTS_STAT_T3122], wait_ind);
Stefan Sperling6cee8932018-01-30 18:14:22 +0100173}