blob: 6ddb088809474451efe3e44d65db376fc3a77467 [file] [log] [blame]
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +02001/* GSM Radio Signalling Link messages on the A-bis interface
Harald Welte52b1f982008-12-23 20:25:15 +00002 * 3GPP TS 08.58 version 8.6.0 Release 1999 / ETSI TS 100 596 V8.6.0 */
3
Harald Welte3c9c5f92010-03-04 10:33:10 +01004/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
Holger Hans Peter Freyther85825352011-12-27 22:24:17 +01005 * (C) 2012 by Holger Hans Peter Freyther
Harald Welte8470bf22008-12-25 23:28:35 +00006 *
Harald Welte52b1f982008-12-23 20:25:15 +00007 * All Rights Reserved
8 *
9 * This program is free software; you can redistribute it and/or modify
Harald Welte9af6ddf2011-01-01 15:25:50 +010010 * it under the terms of the GNU Affero General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
Harald Welte52b1f982008-12-23 20:25:15 +000012 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Harald Welte9af6ddf2011-01-01 15:25:50 +010017 * GNU Affero General Public License for more details.
Harald Welte52b1f982008-12-23 20:25:15 +000018 *
Harald Welte9af6ddf2011-01-01 15:25:50 +010019 * You should have received a copy of the GNU Affero General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Harald Welte52b1f982008-12-23 20:25:15 +000021 *
22 */
23
24#include <stdio.h>
Harald Welte8470bf22008-12-25 23:28:35 +000025#include <stdlib.h>
Harald Welte52b1f982008-12-23 20:25:15 +000026#include <errno.h>
Harald Welte75099262009-02-16 21:12:08 +000027#include <netinet/in.h>
Harald Welte167df882009-02-17 14:35:45 +000028#include <arpa/inet.h>
Harald Welte52b1f982008-12-23 20:25:15 +000029
Harald Welte8470bf22008-12-25 23:28:35 +000030#include <openbsc/gsm_data.h>
31#include <openbsc/gsm_04_08.h>
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010032#include <osmocom/gsm/gsm_utils.h>
Harald Welte8470bf22008-12-25 23:28:35 +000033#include <openbsc/abis_rsl.h>
34#include <openbsc/chan_alloc.h>
Harald Welteedcc5272009-08-09 13:47:35 +020035#include <openbsc/bsc_rll.h>
Harald Welte8470bf22008-12-25 23:28:35 +000036#include <openbsc/debug.h>
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010037#include <osmocom/gsm/tlv.h>
Maxc08ee712016-05-11 12:45:13 +020038#include <osmocom/gsm/protocol/gsm_04_08.h>
39#include <osmocom/gsm/protocol/gsm_08_58.h>
Holger Freyther392209c2009-02-10 00:06:19 +000040#include <openbsc/paging.h>
Harald Welte167df882009-02-17 14:35:45 +000041#include <openbsc/signal.h>
Harald Welte3c7dc6e2009-11-29 19:07:28 +010042#include <openbsc/meas_rep.h>
Harald Welte17f5bf62009-12-20 15:42:44 +010043#include <openbsc/rtp_proxy.h>
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +020044#include <osmocom/abis/e1_input.h>
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010045#include <osmocom/gsm/rsl.h>
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010046#include <osmocom/core/talloc.h>
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +080047
Harald Welte8470bf22008-12-25 23:28:35 +000048#define RSL_ALLOC_SIZE 1024
49#define RSL_ALLOC_HEADROOM 128
Harald Welte52b1f982008-12-23 20:25:15 +000050
Holger Hans Peter Freytherb3489392011-12-28 16:21:05 +010051enum sacch_deact {
52 SACCH_NONE,
53 SACCH_DEACTIVATE,
54};
55
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +080056static int rsl_send_imm_assignment(struct gsm_lchan *lchan);
Holger Hans Peter Freytherf0405062014-04-06 12:21:05 +020057static void error_timeout_cb(void *data);
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +080058
Holger Hans Peter Freyther08eebd52010-12-27 13:28:20 +010059static void send_lchan_signal(int sig_no, struct gsm_lchan *lchan,
60 struct gsm_meas_rep *resp)
61{
62 struct lchan_signal_data sig;
63 sig.lchan = lchan;
64 sig.mr = resp;
Pablo Neira Ayusobbc5b992011-05-06 12:12:31 +020065 osmo_signal_dispatch(SS_LCHAN, sig_no, &sig);
Holger Hans Peter Freyther08eebd52010-12-27 13:28:20 +010066}
67
Holger Hans Peter Freyther93599a22012-12-06 19:09:58 +010068static void do_lchan_free(struct gsm_lchan *lchan)
69{
Holger Hans Peter Freytherf0405062014-04-06 12:21:05 +020070 /* We start the error timer to make the channel available again */
71 if (lchan->state == LCHAN_S_REL_ERR) {
72 lchan->error_timer.data = lchan;
73 lchan->error_timer.cb = error_timeout_cb;
74 osmo_timer_schedule(&lchan->error_timer,
75 lchan->ts->trx->bts->network->T3111 + 2, 0);
76 } else {
Holger Hans Peter Freyther93599a22012-12-06 19:09:58 +010077 rsl_lchan_set_state(lchan, LCHAN_S_NONE);
Holger Hans Peter Freytherf0405062014-04-06 12:21:05 +020078 }
Holger Hans Peter Freyther93599a22012-12-06 19:09:58 +010079 lchan_free(lchan);
80}
81
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +020082static uint8_t mdisc_by_msgtype(uint8_t msg_type)
Harald Welte52b1f982008-12-23 20:25:15 +000083{
84 /* mask off the transparent bit ? */
85 msg_type &= 0xfe;
86
Harald Welte8470bf22008-12-25 23:28:35 +000087 if ((msg_type & 0xf0) == 0x00)
Harald Welte52b1f982008-12-23 20:25:15 +000088 return ABIS_RSL_MDISC_RLL;
Harald Welte8470bf22008-12-25 23:28:35 +000089 if ((msg_type & 0xf0) == 0x10) {
Harald Welte52b1f982008-12-23 20:25:15 +000090 if (msg_type >= 0x19 && msg_type <= 0x22)
91 return ABIS_RSL_MDISC_TRX;
92 else
93 return ABIS_RSL_MDISC_COM_CHAN;
94 }
Harald Welte2d5b6382008-12-27 19:46:06 +000095 if ((msg_type & 0xe0) == 0x20)
Harald Welte52b1f982008-12-23 20:25:15 +000096 return ABIS_RSL_MDISC_DED_CHAN;
97
98 return ABIS_RSL_MDISC_LOC;
99}
100
101static inline void init_dchan_hdr(struct abis_rsl_dchan_hdr *dh,
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200102 uint8_t msg_type)
Harald Welte52b1f982008-12-23 20:25:15 +0000103{
104 dh->c.msg_discr = mdisc_by_msgtype(msg_type);
105 dh->c.msg_type = msg_type;
106 dh->ie_chan = RSL_IE_CHAN_NR;
107}
108
Neels Hofmeyr74585722016-07-23 17:38:22 +0200109/* call rsl_lchan_lookup and set the log context */
110static struct gsm_lchan *lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr)
Harald Welte8470bf22008-12-25 23:28:35 +0000111{
Neels Hofmeyr74585722016-07-23 17:38:22 +0200112 int rc;
113 struct gsm_lchan *lchan = rsl_lchan_lookup(trx, chan_nr, &rc);
Harald Welte8470bf22008-12-25 23:28:35 +0000114
Neels Hofmeyr74585722016-07-23 17:38:22 +0200115 if (!lchan) {
Harald Welteb1d4c8e2009-12-17 23:10:46 +0100116 LOGP(DRSL, LOGL_ERROR, "unknown chan_nr=0x%02x\n", chan_nr);
Harald Welte8470bf22008-12-25 23:28:35 +0000117 return NULL;
118 }
119
Neels Hofmeyr74585722016-07-23 17:38:22 +0200120 if (rc < 0)
121 LOGP(DRSL, LOGL_ERROR, "%s mismatching chan_nr=0x%02x\n",
122 gsm_ts_and_pchan_name(lchan->ts), chan_nr);
123
Harald Weltedc5062b2010-03-26 21:28:59 +0800124 log_set_context(BSC_CTX_LCHAN, lchan);
Holger Hans Peter Freyther2412a072010-06-28 15:47:12 +0800125 if (lchan->conn)
126 log_set_context(BSC_CTX_SUBSCR, lchan->conn->subscr);
Harald Welte8470bf22008-12-25 23:28:35 +0000127
128 return lchan;
129}
130
Harald Welte52b1f982008-12-23 20:25:15 +0000131/* As per TS 03.03 Section 2.2, the IMSI has 'not more than 15 digits' */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200132uint64_t str_to_imsi(const char *imsi_str)
Harald Welte52b1f982008-12-23 20:25:15 +0000133{
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200134 uint64_t ret;
Harald Welte52b1f982008-12-23 20:25:15 +0000135
136 ret = strtoull(imsi_str, NULL, 10);
137
138 return ret;
139}
140
Harald Welte8470bf22008-12-25 23:28:35 +0000141static struct msgb *rsl_msgb_alloc(void)
142{
Harald Welte966636f2009-06-26 19:39:35 +0200143 return msgb_alloc_headroom(RSL_ALLOC_SIZE, RSL_ALLOC_HEADROOM,
144 "RSL");
Harald Welte8470bf22008-12-25 23:28:35 +0000145}
146
Harald Welte362322e2009-02-15 14:36:38 +0000147#define MACBLOCK_SIZE 23
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200148static void pad_macblock(uint8_t *out, const uint8_t *in, int len)
Harald Welte362322e2009-02-15 14:36:38 +0000149{
150 memcpy(out, in, len);
151
152 if (len < MACBLOCK_SIZE)
153 memset(out+len, 0x2b, MACBLOCK_SIZE-len);
154}
155
Harald Welte08d91a52009-08-30 15:37:11 +0900156/* Chapter 9.3.7: Encryption Information */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200157static int build_encr_info(uint8_t *out, struct gsm_lchan *lchan)
Harald Welte08d91a52009-08-30 15:37:11 +0900158{
159 *out++ = lchan->encr.alg_id & 0xff;
160 if (lchan->encr.key_len)
161 memcpy(out, lchan->encr.key, lchan->encr.key_len);
162 return lchan->encr.key_len + 1;
163}
164
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200165static void print_rsl_cause(int lvl, const uint8_t *cause_v, uint8_t cause_len)
Harald Welte8830e072009-07-28 17:58:09 +0200166{
Harald Welte7f93cea2009-02-23 00:02:59 +0000167 int i;
168
Harald Welte5b8ed432009-12-24 12:20:20 +0100169 LOGPC(DRSL, lvl, "CAUSE=0x%02x(%s) ",
Harald Welte8830e072009-07-28 17:58:09 +0200170 cause_v[0], rsl_err_name(cause_v[0]));
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +0200171 for (i = 1; i < cause_len-1; i++)
Harald Welte5b8ed432009-12-24 12:20:20 +0100172 LOGPC(DRSL, lvl, "%02x ", cause_v[i]);
Harald Welte7f93cea2009-02-23 00:02:59 +0000173}
174
Harald Weltee8bd9e82011-08-10 23:26:33 +0200175static void lchan_act_tmr_cb(void *data)
176{
177 struct gsm_lchan *lchan = data;
178
Holger Hans Peter Freyther21776242013-05-01 18:44:04 +0200179 LOGP(DRSL, LOGL_ERROR,
180 "%s Timeout during activation. Marked as broken.\n",
Harald Weltee8bd9e82011-08-10 23:26:33 +0200181 gsm_lchan_name(lchan));
182
Holger Hans Peter Freyther454140e2014-12-28 12:08:28 +0100183 rsl_lchan_mark_broken(lchan, "activation timeout");
Daniel Willmann513da172011-08-11 04:44:12 +0200184 lchan_free(lchan);
Harald Weltee8bd9e82011-08-10 23:26:33 +0200185}
186
187static void lchan_deact_tmr_cb(void *data)
188{
189 struct gsm_lchan *lchan = data;
190
Holger Hans Peter Freyther21776242013-05-01 18:44:04 +0200191 LOGP(DRSL, LOGL_ERROR,
192 "%s Timeout during deactivation! Marked as broken.\n",
Harald Weltee8bd9e82011-08-10 23:26:33 +0200193 gsm_lchan_name(lchan));
194
Holger Hans Peter Freyther454140e2014-12-28 12:08:28 +0100195 rsl_lchan_mark_broken(lchan, "de-activation timeout");
Holger Hans Peter Freyther21776242013-05-01 18:44:04 +0200196 lchan_free(lchan);
Harald Weltee8bd9e82011-08-10 23:26:33 +0200197}
198
199
Harald Welte52b1f982008-12-23 20:25:15 +0000200/* Send a BCCH_INFO message as per Chapter 8.5.1 */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200201int rsl_bcch_info(struct gsm_bts_trx *trx, uint8_t type,
202 const uint8_t *data, int len)
Harald Welte52b1f982008-12-23 20:25:15 +0000203{
204 struct abis_rsl_dchan_hdr *dh;
Harald Welte8470bf22008-12-25 23:28:35 +0000205 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000206
207 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof*dh);
208 init_dchan_hdr(dh, RSL_MT_BCCH_INFO);
209 dh->chan_nr = RSL_CHAN_BCCH;
210
211 msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
212 msgb_tlv_put(msg, RSL_IE_FULL_BCCH_INFO, len, data);
213
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200214 msg->dst = trx->rsl_link;
Harald Welte8470bf22008-12-25 23:28:35 +0000215
216 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000217}
218
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200219int rsl_sacch_filling(struct gsm_bts_trx *trx, uint8_t type,
220 const uint8_t *data, int len)
Harald Welte52b1f982008-12-23 20:25:15 +0000221{
222 struct abis_rsl_common_hdr *ch;
Harald Welte8470bf22008-12-25 23:28:35 +0000223 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000224
225 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
226 ch->msg_discr = ABIS_RSL_MDISC_TRX;
227 ch->msg_type = RSL_MT_SACCH_FILL;
228
229 msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
Harald Welte702d8702008-12-26 20:25:35 +0000230 msgb_tl16v_put(msg, RSL_IE_L3_INFO, len, data);
Harald Welte52b1f982008-12-23 20:25:15 +0000231
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200232 msg->dst = trx->rsl_link;
Harald Welte8470bf22008-12-25 23:28:35 +0000233
234 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000235}
236
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200237int rsl_sacch_info_modify(struct gsm_lchan *lchan, uint8_t type,
238 const uint8_t *data, int len)
Harald Welte7a69cf02011-01-13 23:16:03 +0100239{
240 struct abis_rsl_dchan_hdr *dh;
241 struct msgb *msg = rsl_msgb_alloc();
Harald Weltef6093a42011-06-25 10:02:33 +0200242 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte7a69cf02011-01-13 23:16:03 +0100243
244 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
245 init_dchan_hdr(dh, RSL_MT_SACCH_INFO_MODIFY);
246 dh->chan_nr = chan_nr;
247
248 msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
249 msgb_tl16v_put(msg, RSL_IE_L3_INFO, len, data);
250
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200251 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte7a69cf02011-01-13 23:16:03 +0100252
253 return abis_rsl_sendmsg(msg);
254}
255
Harald Weltefcd24452009-06-20 18:15:19 +0200256int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db)
257{
258 struct abis_rsl_dchan_hdr *dh;
Harald Welteeab33352009-06-27 03:09:08 +0200259 struct msgb *msg;
Harald Weltef6093a42011-06-25 10:02:33 +0200260 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Weltefcd24452009-06-20 18:15:19 +0200261
262 db = abs(db);
263 if (db > 30)
264 return -EINVAL;
265
Harald Welteeab33352009-06-27 03:09:08 +0200266 msg = rsl_msgb_alloc();
267
Harald Weltefcd24452009-06-20 18:15:19 +0200268 lchan->bs_power = db/2;
269 if (fpc)
270 lchan->bs_power |= 0x10;
271
272 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
273 init_dchan_hdr(dh, RSL_MT_BS_POWER_CONTROL);
274 dh->chan_nr = chan_nr;
275
276 msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power);
277
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200278 msg->dst = lchan->ts->trx->rsl_link;
Harald Weltefcd24452009-06-20 18:15:19 +0200279
280 return abis_rsl_sendmsg(msg);
281}
282
Harald Weltefcd24452009-06-20 18:15:19 +0200283int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm)
284{
285 struct abis_rsl_dchan_hdr *dh;
Harald Welteeab33352009-06-27 03:09:08 +0200286 struct msgb *msg;
Harald Weltef6093a42011-06-25 10:02:33 +0200287 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Weltefcd24452009-06-20 18:15:19 +0200288 int ctl_lvl;
289
Harald Welte66b6a8d2009-08-09 14:45:18 +0200290 ctl_lvl = ms_pwr_ctl_lvl(lchan->ts->trx->bts->band, dbm);
Harald Weltefcd24452009-06-20 18:15:19 +0200291 if (ctl_lvl < 0)
292 return ctl_lvl;
293
Harald Welteeab33352009-06-27 03:09:08 +0200294 msg = rsl_msgb_alloc();
295
Harald Weltefcd24452009-06-20 18:15:19 +0200296 lchan->ms_power = ctl_lvl;
297
298 if (fpc)
299 lchan->ms_power |= 0x20;
300
301 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
302 init_dchan_hdr(dh, RSL_MT_MS_POWER_CONTROL);
303 dh->chan_nr = chan_nr;
304
305 msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power);
306
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200307 msg->dst = lchan->ts->trx->rsl_link;
Harald Weltefcd24452009-06-20 18:15:19 +0200308
309 return abis_rsl_sendmsg(msg);
310}
311
Harald Welte9943c5b2009-07-29 15:41:29 +0200312static int channel_mode_from_lchan(struct rsl_ie_chan_mode *cm,
313 struct gsm_lchan *lchan)
314{
Holger Hans Peter Freythere1145cf2013-03-09 17:50:10 +0100315 memset(cm, 0, sizeof(*cm));
Harald Welte9943c5b2009-07-29 15:41:29 +0200316
317 /* FIXME: what to do with data calls ? */
Maxc08ee712016-05-11 12:45:13 +0200318 cm->dtx_dtu = 0;
319 if (lchan->ts->trx->bts->dtxu != GSM48_DTX_SHALL_NOT_BE_USED)
320 cm->dtx_dtu |= RSL_CMOD_DTXu;
321 if (lchan->ts->trx->bts->dtxd)
322 cm->dtx_dtu |= RSL_CMOD_DTXd;
Harald Welte9943c5b2009-07-29 15:41:29 +0200323
324 /* set TCH Speech/Data */
325 cm->spd_ind = lchan->rsl_cmode;
326
Harald Welte1a79d362009-11-27 08:55:16 +0100327 if (lchan->rsl_cmode == RSL_CMOD_SPD_SIGN &&
328 lchan->tch_mode != GSM48_CMODE_SIGN)
Harald Welteb1d4c8e2009-12-17 23:10:46 +0100329 LOGP(DRSL, LOGL_ERROR, "unsupported: rsl_mode == signalling, "
Harald Welte1a79d362009-11-27 08:55:16 +0100330 "but tch_mode != signalling\n");
331
Harald Welte9943c5b2009-07-29 15:41:29 +0200332 switch (lchan->type) {
333 case GSM_LCHAN_SDCCH:
334 cm->chan_rt = RSL_CMOD_CRT_SDCCH;
335 break;
336 case GSM_LCHAN_TCH_F:
337 cm->chan_rt = RSL_CMOD_CRT_TCH_Bm;
338 break;
339 case GSM_LCHAN_TCH_H:
340 cm->chan_rt = RSL_CMOD_CRT_TCH_Lm;
341 break;
342 case GSM_LCHAN_NONE:
343 case GSM_LCHAN_UNKNOWN:
344 default:
Neels Hofmeyrbbbcfe52016-07-18 23:47:24 +0200345 LOGP(DRSL, LOGL_ERROR,
346 "unsupported activation lchan->type %u %s\n",
347 lchan->type, gsm_lchant_name(lchan->type));
Harald Welte9943c5b2009-07-29 15:41:29 +0200348 return -EINVAL;
349 }
350
351 switch (lchan->tch_mode) {
352 case GSM48_CMODE_SIGN:
353 cm->chan_rate = 0;
354 break;
355 case GSM48_CMODE_SPEECH_V1:
356 cm->chan_rate = RSL_CMOD_SP_GSM1;
357 break;
358 case GSM48_CMODE_SPEECH_EFR:
359 cm->chan_rate = RSL_CMOD_SP_GSM2;
360 break;
361 case GSM48_CMODE_SPEECH_AMR:
362 cm->chan_rate = RSL_CMOD_SP_GSM3;
363 break;
364 case GSM48_CMODE_DATA_14k5:
Harald Welte9943c5b2009-07-29 15:41:29 +0200365 case GSM48_CMODE_DATA_12k0:
Harald Welte9943c5b2009-07-29 15:41:29 +0200366 case GSM48_CMODE_DATA_6k0:
Harald Weltee4227982012-08-24 15:33:56 +0200367 switch (lchan->csd_mode) {
368 case LCHAN_CSD_M_NT:
369 /* non-transparent CSD with RLP */
370 switch (lchan->tch_mode) {
371 case GSM48_CMODE_DATA_14k5:
372 cm->chan_rate = RSL_CMOD_SP_NT_14k5;
373 break;
374 case GSM48_CMODE_DATA_12k0:
375 cm->chan_rate = RSL_CMOD_SP_NT_12k0;
376 break;
377 case GSM48_CMODE_DATA_6k0:
378 cm->chan_rate = RSL_CMOD_SP_NT_6k0;
379 break;
380 default:
Neels Hofmeyrbbbcfe52016-07-18 23:47:24 +0200381 LOGP(DRSL, LOGL_ERROR,
382 "unsupported lchan->tch_mode %u\n",
383 lchan->tch_mode);
Harald Weltee4227982012-08-24 15:33:56 +0200384 return -EINVAL;
385 }
386 break;
387 /* transparent data services below */
388 case LCHAN_CSD_M_T_1200_75:
389 cm->chan_rate = RSL_CMOD_CSD_T_1200_75;
390 break;
391 case LCHAN_CSD_M_T_600:
392 cm->chan_rate = RSL_CMOD_CSD_T_600;
393 break;
394 case LCHAN_CSD_M_T_1200:
395 cm->chan_rate = RSL_CMOD_CSD_T_1200;
396 break;
397 case LCHAN_CSD_M_T_2400:
398 cm->chan_rate = RSL_CMOD_CSD_T_2400;
399 break;
400 case LCHAN_CSD_M_T_9600:
401 cm->chan_rate = RSL_CMOD_CSD_T_9600;
402 break;
403 case LCHAN_CSD_M_T_14400:
404 cm->chan_rate = RSL_CMOD_CSD_T_14400;
405 break;
406 case LCHAN_CSD_M_T_29000:
407 cm->chan_rate = RSL_CMOD_CSD_T_29000;
408 break;
409 case LCHAN_CSD_M_T_32000:
410 cm->chan_rate = RSL_CMOD_CSD_T_32000;
411 break;
412 default:
Neels Hofmeyrbbbcfe52016-07-18 23:47:24 +0200413 LOGP(DRSL, LOGL_ERROR,
414 "unsupported lchan->csd_mode %u\n",
415 lchan->csd_mode);
Harald Weltee4227982012-08-24 15:33:56 +0200416 return -EINVAL;
417 }
Harald Welte9943c5b2009-07-29 15:41:29 +0200418 default:
Neels Hofmeyrbbbcfe52016-07-18 23:47:24 +0200419 LOGP(DRSL, LOGL_ERROR,
420 "unsupported lchan->tch_mode %u\n",
421 lchan->tch_mode);
Harald Welte9943c5b2009-07-29 15:41:29 +0200422 return -EINVAL;
423 }
424
425 return 0;
426}
427
Holger Hans Peter Freyther11cb7a92015-08-20 19:32:46 +0200428static void mr_config_for_bts(struct gsm_lchan *lchan, struct msgb *msg)
429{
430 if (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR)
431 msgb_tlv_put(msg, RSL_IE_MR_CONFIG, lchan->mr_bts_lv[0],
432 lchan->mr_bts_lv + 1);
433}
434
Harald Welte52b1f982008-12-23 20:25:15 +0000435/* Chapter 8.4.1 */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200436int rsl_chan_activate_lchan(struct gsm_lchan *lchan, uint8_t act_type,
Andreas Eversberg723a7512013-10-11 12:55:35 +0200437 uint8_t ho_ref)
Harald Welte4b634542008-12-27 01:55:51 +0000438{
439 struct abis_rsl_dchan_hdr *dh;
Harald Welteeab33352009-06-27 03:09:08 +0200440 struct msgb *msg;
Harald Welte9943c5b2009-07-29 15:41:29 +0200441 int rc;
Harald Welte93d50e62010-06-29 17:53:45 +0200442 uint8_t *len;
Andreas Eversberg723a7512013-10-11 12:55:35 +0200443 uint8_t ta;
Harald Welte4b634542008-12-27 01:55:51 +0000444
Harald Weltef6093a42011-06-25 10:02:33 +0200445 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte4b634542008-12-27 01:55:51 +0000446 struct rsl_ie_chan_mode cm;
laforge694a5cf2010-06-20 21:38:19 +0200447 struct gsm48_chan_desc cd;
Harald Welte4b634542008-12-27 01:55:51 +0000448
Harald Welte9943c5b2009-07-29 15:41:29 +0200449 rc = channel_mode_from_lchan(&cm, lchan);
450 if (rc < 0)
451 return rc;
Harald Welte4b634542008-12-27 01:55:51 +0000452
Neels Hofmeyrc6926d02016-07-14 02:51:13 +0200453 /* If a TCH_F/PDCH TS is in PDCH mode, deactivate PDCH first. */
Andreas Eversberg9df268e2013-10-11 13:32:30 +0200454 if (lchan->ts->pchan == GSM_PCHAN_TCH_F_PDCH
Neels Hofmeyr2ebacce2016-06-14 14:08:35 +0200455 && (lchan->ts->flags & TS_F_PDCH_ACTIVE)) {
Andreas Eversberg9df268e2013-10-11 13:32:30 +0200456 /* store activation type and handover reference */
457 lchan->dyn_pdch.act_type = act_type;
458 lchan->dyn_pdch.ho_ref = ho_ref;
459 return rsl_ipacc_pdch_activate(lchan->ts, 0);
460 }
461
Neels Hofmeyr832afa32016-06-14 13:12:00 +0200462 rsl_lchan_set_state(lchan, LCHAN_S_ACT_REQ);
463
Andreas Eversberg723a7512013-10-11 12:55:35 +0200464 ta = lchan->rqd_ta;
465
466 /* BS11 requires TA shifted by 2 bits */
467 if (lchan->ts->trx->bts->type == GSM_BTS_TYPE_BS11)
468 ta <<= 2;
469
Holger Hans Peter Freythere38bd6c2010-06-30 11:56:43 +0800470 memset(&cd, 0, sizeof(cd));
laforge694a5cf2010-06-20 21:38:19 +0200471 gsm48_lchan2chan_desc(&cd, lchan);
Harald Welte4b634542008-12-27 01:55:51 +0000472
Harald Welteeab33352009-06-27 03:09:08 +0200473 msg = rsl_msgb_alloc();
Harald Welte4b634542008-12-27 01:55:51 +0000474 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
475 init_dchan_hdr(dh, RSL_MT_CHAN_ACTIV);
476 dh->chan_nr = chan_nr;
477
478 msgb_tv_put(msg, RSL_IE_ACT_TYPE, act_type);
Harald Welte4b634542008-12-27 01:55:51 +0000479 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200480 (uint8_t *) &cm);
Holger Hans Peter Freythere38bd6c2010-06-30 11:56:43 +0800481
482 /*
483 * The Channel Identification is needed for Phase1 phones
484 * and it contains the GSM48 Channel Description and the
485 * Mobile Allocation. The GSM 08.58 asks for the Mobile
486 * Allocation to have a length of zero. We are using the
487 * msgb_l3len to calculate the length of both messages.
488 */
laforge694a5cf2010-06-20 21:38:19 +0200489 msgb_v_put(msg, RSL_IE_CHAN_IDENT);
Harald Welte93d50e62010-06-29 17:53:45 +0200490 len = msgb_put(msg, 1);
Dieter Spaareabb6e32011-07-27 23:40:33 +0200491 msgb_tv_fixed_put(msg, GSM48_IE_CHANDESC_2, sizeof(cd), (const uint8_t *) &cd);
Holger Hans Peter Freyther0379c6d2010-06-30 12:06:20 +0800492
493 if (lchan->ts->hopping.enabled)
494 msgb_tlv_put(msg, GSM48_IE_MA_AFTER, lchan->ts->hopping.ma_len,
495 lchan->ts->hopping.ma_data);
496 else
497 msgb_tlv_put(msg, GSM48_IE_MA_AFTER, 0, NULL);
Holger Hans Peter Freythere38bd6c2010-06-30 11:56:43 +0800498
499 /* update the calculated size */
500 msg->l3h = len + 1;
501 *len = msgb_l3len(msg);
502
Harald Welte08d91a52009-08-30 15:37:11 +0900503 if (lchan->encr.alg_id > RSL_ENC_ALG_A5(0)) {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200504 uint8_t encr_info[MAX_A5_KEY_LEN+2];
Harald Welte08d91a52009-08-30 15:37:11 +0900505 rc = build_encr_info(encr_info, lchan);
506 if (rc > 0)
507 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, rc, encr_info);
508 }
509
Harald Welte8d77b952009-12-17 00:31:10 +0100510 switch (act_type) {
511 case RSL_ACT_INTER_ASYNC:
512 case RSL_ACT_INTER_SYNC:
513 msgb_tv_put(msg, RSL_IE_HANDO_REF, ho_ref);
514 break;
515 default:
516 break;
517 }
518
Harald Welted4c9bf32009-02-15 16:56:18 +0000519 msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power);
520 msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power);
Harald Welte4b634542008-12-27 01:55:51 +0000521 msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta);
Holger Hans Peter Freyther11cb7a92015-08-20 19:32:46 +0200522 mr_config_for_bts(lchan, msg);
Holger Hans Peter Freyther93b6c652010-01-28 04:45:05 +0100523
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200524 msg->dst = lchan->ts->trx->rsl_link;
Harald Weltee79769b2009-02-07 00:48:17 +0000525
Harald Welte4b634542008-12-27 01:55:51 +0000526 return abis_rsl_sendmsg(msg);
527}
528
Harald Welte470abb72009-07-29 11:38:15 +0200529/* Chapter 8.4.9: Modify channel mode on BTS side */
Harald Welteda783762009-02-18 03:29:53 +0000530int rsl_chan_mode_modify_req(struct gsm_lchan *lchan)
531{
532 struct abis_rsl_dchan_hdr *dh;
Harald Welteeab33352009-06-27 03:09:08 +0200533 struct msgb *msg;
Harald Welte9943c5b2009-07-29 15:41:29 +0200534 int rc;
Harald Welteda783762009-02-18 03:29:53 +0000535
Harald Weltef6093a42011-06-25 10:02:33 +0200536 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welteda783762009-02-18 03:29:53 +0000537 struct rsl_ie_chan_mode cm;
538
Harald Welte9943c5b2009-07-29 15:41:29 +0200539 rc = channel_mode_from_lchan(&cm, lchan);
540 if (rc < 0)
541 return rc;
Harald Welteda783762009-02-18 03:29:53 +0000542
Harald Welteeab33352009-06-27 03:09:08 +0200543 msg = rsl_msgb_alloc();
Harald Welteda783762009-02-18 03:29:53 +0000544 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
545 init_dchan_hdr(dh, RSL_MT_MODE_MODIFY_REQ);
546 dh->chan_nr = chan_nr;
547
548 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200549 (uint8_t *) &cm);
Harald Welte08d91a52009-08-30 15:37:11 +0900550
551 if (lchan->encr.alg_id > RSL_ENC_ALG_A5(0)) {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200552 uint8_t encr_info[MAX_A5_KEY_LEN+2];
Harald Welte08d91a52009-08-30 15:37:11 +0900553 rc = build_encr_info(encr_info, lchan);
554 if (rc > 0)
555 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, rc, encr_info);
556 }
557
Holger Hans Peter Freyther11cb7a92015-08-20 19:32:46 +0200558 mr_config_for_bts(lchan, msg);
Holger Hans Peter Freytherea528022009-11-18 22:57:02 +0100559
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200560 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte08d91a52009-08-30 15:37:11 +0900561
562 return abis_rsl_sendmsg(msg);
563}
564
565/* Chapter 8.4.6: Send the encryption command with given L3 info */
566int rsl_encryption_cmd(struct msgb *msg)
567{
568 struct abis_rsl_dchan_hdr *dh;
569 struct gsm_lchan *lchan = msg->lchan;
Harald Weltef6093a42011-06-25 10:02:33 +0200570 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200571 uint8_t encr_info[MAX_A5_KEY_LEN+2];
572 uint8_t l3_len = msg->len;
Harald Welte08d91a52009-08-30 15:37:11 +0900573 int rc;
574
575 /* First push the L3 IE tag and length */
576 msgb_tv16_push(msg, RSL_IE_L3_INFO, l3_len);
577
578 /* then the link identifier (SAPI0, main sign link) */
579 msgb_tv_push(msg, RSL_IE_LINK_IDENT, 0);
580
581 /* then encryption information */
582 rc = build_encr_info(encr_info, lchan);
583 if (rc <= 0)
584 return rc;
585 msgb_tlv_push(msg, RSL_IE_ENCR_INFO, rc, encr_info);
586
587 /* and finally the DCHAN header */
588 dh = (struct abis_rsl_dchan_hdr *) msgb_push(msg, sizeof(*dh));
589 init_dchan_hdr(dh, RSL_MT_ENCR_CMD);
590 dh->chan_nr = chan_nr;
Harald Welteda783762009-02-18 03:29:53 +0000591
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200592 msg->dst = lchan->ts->trx->rsl_link;
Harald Welteda783762009-02-18 03:29:53 +0000593
594 return abis_rsl_sendmsg(msg);
595}
596
Harald Welte115d1032009-08-10 11:43:22 +0200597/* Chapter 8.4.5 / 4.6: Deactivate the SACCH after 04.08 RR CHAN RELEASE */
Harald Welteae0f2362009-07-19 18:36:49 +0200598int rsl_deact_sacch(struct gsm_lchan *lchan)
599{
600 struct abis_rsl_dchan_hdr *dh;
601 struct msgb *msg = rsl_msgb_alloc();
602
603 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
604 init_dchan_hdr(dh, RSL_MT_DEACTIVATE_SACCH);
Harald Weltef6093a42011-06-25 10:02:33 +0200605 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welteae0f2362009-07-19 18:36:49 +0200606
607 msg->lchan = lchan;
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200608 msg->dst = lchan->ts->trx->rsl_link;
Harald Welteae0f2362009-07-19 18:36:49 +0200609
Harald Welte (local)19ef62a2009-12-27 18:16:36 +0100610 DEBUGP(DRSL, "%s DEACTivate SACCH CMD\n", gsm_lchan_name(lchan));
Harald Welteae0f2362009-07-19 18:36:49 +0200611
612 return abis_rsl_sendmsg(msg);
613}
614
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +0800615static void error_timeout_cb(void *data)
616{
617 struct gsm_lchan *lchan = data;
618 if (lchan->state != LCHAN_S_REL_ERR) {
619 LOGP(DRSL, LOGL_ERROR, "%s error timeout but not in error state: %d\n",
620 gsm_lchan_name(lchan), lchan->state);
621 return;
622 }
623
624 /* go back to the none state */
Harald Weltea9e420e2012-11-13 04:26:22 +0100625 LOGP(DRSL, LOGL_INFO, "%s is back in operation.\n", gsm_lchan_name(lchan));
Holger Hans Peter Freyther44752d92010-06-08 11:53:33 +0800626 rsl_lchan_set_state(lchan, LCHAN_S_NONE);
Neels Hofmeyr82c8f752016-06-21 20:55:14 +0200627
Neels Hofmeyr9ddd8e62016-07-06 14:39:04 +0200628 /* Put PDCH channel back into PDCH mode, if GPRS is enabled */
629 if (lchan->ts->pchan == GSM_PCHAN_TCH_F_PDCH
630 && lchan->ts->trx->bts->gprs.mode != BTS_GPRS_NONE)
Neels Hofmeyr82c8f752016-06-21 20:55:14 +0200631 rsl_ipacc_pdch_activate(lchan->ts, 1);
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +0800632}
633
Harald Weltefd355a32011-03-04 13:41:31 +0100634static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan);
635
Harald Welte115d1032009-08-10 11:43:22 +0200636/* Chapter 8.4.14 / 4.7: Tell BTS to release the radio channel */
Holger Hans Peter Freytherb3489392011-12-28 16:21:05 +0100637static int rsl_rf_chan_release(struct gsm_lchan *lchan, int error,
638 enum sacch_deact deact_sacch)
Harald Welte52b1f982008-12-23 20:25:15 +0000639{
640 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +0800641 struct msgb *msg;
Harald Weltefd355a32011-03-04 13:41:31 +0100642 int rc;
Harald Welte52b1f982008-12-23 20:25:15 +0000643
Holger Hans Peter Freytherb3489392011-12-28 16:21:05 +0100644 /* Stop timers that should lead to a channel release */
645 osmo_timer_del(&lchan->T3109);
646
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +0800647 if (lchan->state == LCHAN_S_REL_ERR) {
648 LOGP(DRSL, LOGL_NOTICE, "%s is in error state not sending release.\n",
649 gsm_lchan_name(lchan));
650 return -1;
651 }
652
653 msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000654 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
655 init_dchan_hdr(dh, RSL_MT_RF_CHAN_REL);
Harald Weltef6093a42011-06-25 10:02:33 +0200656 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte52b1f982008-12-23 20:25:15 +0000657
Harald Welte8470bf22008-12-25 23:28:35 +0000658 msg->lchan = lchan;
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200659 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte8470bf22008-12-25 23:28:35 +0000660
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +0800661 DEBUGP(DRSL, "%s RF Channel Release CMD due error %d\n", gsm_lchan_name(lchan), error);
662
663 if (error) {
Holger Hans Peter Freyther9d50a272011-12-28 12:11:40 +0100664 /*
665 * FIXME: GSM 04.08 gives us two options for the abnormal
666 * chanel release. This can be either like in the non-existent
667 * sub-lcuase 3.5.1 or for the main signalling link deactivate
668 * the SACCH, start timer T3109 and consider the channel as
669 * released.
670 *
671 * This code is doing the later for all raido links and not
672 * only the main link. Right now all SAPIs are released on the
673 * local end, the SACCH will be de-activated and right now the
674 * T3111 will be started. First T3109 should be started and then
675 * the T3111.
676 *
677 * TODO: Move this out of the function.
678 */
679
680 /*
681 * sacch de-activate and "local end release"
682 */
Holger Hans Peter Freytherb3489392011-12-28 16:21:05 +0100683 if (deact_sacch == SACCH_DEACTIVATE)
684 rsl_deact_sacch(lchan);
Holger Hans Peter Freyther9d50a272011-12-28 12:11:40 +0100685 rsl_release_sapis_from(lchan, 0, RSL_REL_LOCAL_END);
686
687 /*
688 * TODO: start T3109 now.
689 */
Holger Hans Peter Freyther44752d92010-06-08 11:53:33 +0800690 rsl_lchan_set_state(lchan, LCHAN_S_REL_ERR);
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +0800691 }
Harald Welte2d5b6382008-12-27 19:46:06 +0000692
Harald Weltee8bd9e82011-08-10 23:26:33 +0200693 /* Start another timer or assume the BTS sends a ACK/NACK? */
694 lchan->act_timer.cb = lchan_deact_tmr_cb;
695 lchan->act_timer.data = lchan;
696 osmo_timer_schedule(&lchan->act_timer, 4, 0);
697
Harald Weltefd355a32011-03-04 13:41:31 +0100698 rc = abis_rsl_sendmsg(msg);
699
Harald Welte115d1032009-08-10 11:43:22 +0200700 /* BTS will respond by RF CHAN REL ACK */
Harald Weltefd355a32011-03-04 13:41:31 +0100701 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +0000702}
703
Holger Hans Peter Freyther0e4e73a2014-04-19 17:38:33 +0200704/*
705 * Special handling for channel releases in the error case.
706 */
707static int rsl_rf_chan_release_err(struct gsm_lchan *lchan)
708{
709 if (lchan->state != LCHAN_S_ACTIVE)
710 return 0;
711 return rsl_rf_chan_release(lchan, 1, SACCH_DEACTIVATE);
712}
713
Harald Welte64bb7542011-01-14 14:16:16 +0100714static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan)
715{
Neels Hofmeyr40074682016-07-23 20:01:49 +0200716 struct gsm_bts_trx_ts *ts = lchan->ts;
Harald Welte64bb7542011-01-14 14:16:16 +0100717
718 DEBUGP(DRSL, "%s RF CHANNEL RELEASE ACK\n", gsm_lchan_name(lchan));
719
Holger Hans Peter Freyther93599a22012-12-06 19:09:58 +0100720 /* Stop all pending timers */
Harald Weltee8bd9e82011-08-10 23:26:33 +0200721 osmo_timer_del(&lchan->act_timer);
Holger Hans Peter Freyther93599a22012-12-06 19:09:58 +0100722 osmo_timer_del(&lchan->T3111);
Harald Weltee8bd9e82011-08-10 23:26:33 +0200723
Holger Hans Peter Freyther6f6cbf72015-04-04 19:35:22 +0200724 /*
725 * The BTS didn't respond within the timeout to our channel
726 * release request and we have marked the channel as broken.
727 * Now we do receive an ACK and let's be conservative. If it
728 * is a sysmoBTS we know that only one RF Channel Release ACK
729 * will be sent. So let's "repair" the channel.
730 */
Holger Hans Peter Freyther21776242013-05-01 18:44:04 +0200731 if (lchan->state == LCHAN_S_BROKEN) {
Neels Hofmeyr40074682016-07-23 20:01:49 +0200732 int do_free = is_sysmobts_v2(ts->trx->bts);
Holger Hans Peter Freyther6f6cbf72015-04-04 19:35:22 +0200733 LOGP(DRSL, LOGL_NOTICE,
734 "%s CHAN REL ACK for broken channel. %s.\n",
735 gsm_lchan_name(lchan),
736 do_free ? "Releasing it" : "Keeping it broken");
737 if (do_free)
738 do_lchan_free(lchan);
Holger Hans Peter Freyther21776242013-05-01 18:44:04 +0200739 return 0;
740 }
741
Harald Welte64bb7542011-01-14 14:16:16 +0100742 if (lchan->state != LCHAN_S_REL_REQ && lchan->state != LCHAN_S_REL_ERR)
743 LOGP(DRSL, LOGL_NOTICE, "%s CHAN REL ACK but state %s\n",
744 gsm_lchan_name(lchan),
745 gsm_lchans_name(lchan->state));
Andreas Eversberg9df268e2013-10-11 13:32:30 +0200746
Neels Hofmeyr832afa32016-06-14 13:12:00 +0200747 do_lchan_free(lchan);
748
Neels Hofmeyr3f221222016-06-23 22:44:20 +0200749 /*
750 * Put a dynamic TCH/F_PDCH channel back to PDCH mode iff it was
751 * released successfully. If in error, the PDCH ACT will follow after
752 * T3111 in error_timeout_cb().
753 *
754 * Any state other than LCHAN_S_REL_ERR became LCHAN_S_NONE after above
755 * do_lchan_free(). Assert this, because that's what ensures a PDCH ACT
Neels Hofmeyrc6926d02016-07-14 02:51:13 +0200756 * on a TCH/F_PDCH TS in all cases.
Neels Hofmeyr9ddd8e62016-07-06 14:39:04 +0200757 *
758 * If GPRS is disabled, always skip the PDCH ACT.
Neels Hofmeyr3f221222016-06-23 22:44:20 +0200759 */
760 OSMO_ASSERT(lchan->state == LCHAN_S_NONE
761 || lchan->state == LCHAN_S_REL_ERR);
Neels Hofmeyr40074682016-07-23 20:01:49 +0200762 if (ts->trx->bts->gprs.mode == BTS_GPRS_NONE)
Neels Hofmeyr9ddd8e62016-07-06 14:39:04 +0200763 return 0;
Neels Hofmeyr40074682016-07-23 20:01:49 +0200764 if (ts->pchan == GSM_PCHAN_TCH_F_PDCH
Neels Hofmeyr82c8f752016-06-21 20:55:14 +0200765 && lchan->state == LCHAN_S_NONE)
Neels Hofmeyr40074682016-07-23 20:01:49 +0200766 return rsl_ipacc_pdch_activate(ts, 1);
Harald Welte64bb7542011-01-14 14:16:16 +0100767 return 0;
768}
769
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200770int rsl_paging_cmd(struct gsm_bts *bts, uint8_t paging_group, uint8_t len,
771 uint8_t *ms_ident, uint8_t chan_needed)
Harald Welte52b1f982008-12-23 20:25:15 +0000772{
773 struct abis_rsl_dchan_hdr *dh;
Harald Welte8470bf22008-12-25 23:28:35 +0000774 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000775
776 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
777 init_dchan_hdr(dh, RSL_MT_PAGING_CMD);
778 dh->chan_nr = RSL_CHAN_PCH_AGCH;
779
780 msgb_tv_put(msg, RSL_IE_PAGING_GROUP, paging_group);
Harald Welte255539c2008-12-28 02:26:27 +0000781 msgb_tlv_put(msg, RSL_IE_MS_IDENTITY, len-2, ms_ident+2);
Harald Welte52b1f982008-12-23 20:25:15 +0000782 msgb_tv_put(msg, RSL_IE_CHAN_NEEDED, chan_needed);
783
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200784 msg->dst = bts->c0->rsl_link;
Harald Welte8470bf22008-12-25 23:28:35 +0000785
786 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000787}
788
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200789int imsi_str2bcd(uint8_t *bcd_out, const char *str_in)
Harald Welte52b1f982008-12-23 20:25:15 +0000790{
791 int i, len = strlen(str_in);
792
793 for (i = 0; i < len; i++) {
794 int num = str_in[i] - 0x30;
795 if (num < 0 || num > 9)
796 return -1;
797 if (i % 2 == 0)
798 bcd_out[i/2] = num;
799 else
800 bcd_out[i/2] |= (num << 4);
801 }
802
803 return 0;
804}
805
Harald Welte702d8702008-12-26 20:25:35 +0000806/* Chapter 8.5.6 */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200807int rsl_imm_assign_cmd(struct gsm_bts *bts, uint8_t len, uint8_t *val)
Harald Welte52b1f982008-12-23 20:25:15 +0000808{
Harald Welte8470bf22008-12-25 23:28:35 +0000809 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000810 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200811 uint8_t buf[MACBLOCK_SIZE];
Harald Welte52b1f982008-12-23 20:25:15 +0000812
813 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
814 init_dchan_hdr(dh, RSL_MT_IMMEDIATE_ASSIGN_CMD);
815 dh->chan_nr = RSL_CHAN_PCH_AGCH;
816
Harald Welte362322e2009-02-15 14:36:38 +0000817 switch (bts->type) {
818 case GSM_BTS_TYPE_BS11:
819 msgb_tlv_put(msg, RSL_IE_IMM_ASS_INFO, len, val);
820 break;
821 default:
822 /* If phase 2, construct a FULL_IMM_ASS_INFO */
823 pad_macblock(buf, val, len);
824 msgb_tlv_put(msg, RSL_IE_FULL_IMM_ASS_INFO, MACBLOCK_SIZE, buf);
825 break;
826 }
Harald Welte52b1f982008-12-23 20:25:15 +0000827
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200828 msg->dst = bts->c0->rsl_link;
Harald Welte8470bf22008-12-25 23:28:35 +0000829
830 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000831}
832
Harald Welte67fa91b2009-08-10 09:51:40 +0200833/* Send Siemens specific MS RF Power Capability Indication */
Harald Welte31c48932009-08-10 10:07:33 +0200834int rsl_siemens_mrpci(struct gsm_lchan *lchan, struct rsl_mrpci *mrpci)
Harald Welte67fa91b2009-08-10 09:51:40 +0200835{
836 struct msgb *msg = rsl_msgb_alloc();
837 struct abis_rsl_dchan_hdr *dh;
838
839 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
840 init_dchan_hdr(dh, RSL_MT_SIEMENS_MRPCI);
Harald Welte3c456d02009-08-10 11:26:14 +0200841 dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
Harald Weltef6093a42011-06-25 10:02:33 +0200842 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200843 msgb_tv_put(msg, RSL_IE_SIEMENS_MRPCI, *(uint8_t *)mrpci);
Harald Welte67fa91b2009-08-10 09:51:40 +0200844
Harald Welte5b8ed432009-12-24 12:20:20 +0100845 DEBUGP(DRSL, "%s TX Siemens MRPCI 0x%02x\n",
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200846 gsm_lchan_name(lchan), *(uint8_t *)mrpci);
Harald Welte3c456d02009-08-10 11:26:14 +0200847
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200848 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte3c456d02009-08-10 11:26:14 +0200849
Harald Welte67fa91b2009-08-10 09:51:40 +0200850 return abis_rsl_sendmsg(msg);
851}
852
853
Harald Welte8470bf22008-12-25 23:28:35 +0000854/* Send "DATA REQUEST" message with given L3 Info payload */
Harald Welte52b1f982008-12-23 20:25:15 +0000855/* Chapter 8.3.1 */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200856int rsl_data_request(struct msgb *msg, uint8_t link_id)
Harald Welte52b1f982008-12-23 20:25:15 +0000857{
Harald Welte8470bf22008-12-25 23:28:35 +0000858 if (msg->lchan == NULL) {
Harald Welteb1d4c8e2009-12-17 23:10:46 +0100859 LOGP(DRSL, LOGL_ERROR, "cannot send DATA REQUEST to unknown lchan\n");
Harald Welte8470bf22008-12-25 23:28:35 +0000860 return -EINVAL;
861 }
Harald Welte52b1f982008-12-23 20:25:15 +0000862
Harald Weltef6093a42011-06-25 10:02:33 +0200863 rsl_rll_push_l3(msg, RSL_MT_DATA_REQ, gsm_lchan2chan_nr(msg->lchan),
Harald Welte3c9c5f92010-03-04 10:33:10 +0100864 link_id, 1);
Harald Welte52b1f982008-12-23 20:25:15 +0000865
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200866 msg->dst = msg->lchan->ts->trx->rsl_link;
Harald Welte8470bf22008-12-25 23:28:35 +0000867
868 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000869}
870
Harald Welteedcc5272009-08-09 13:47:35 +0200871/* Send "ESTABLISH REQUEST" message with given L3 Info payload */
872/* Chapter 8.3.1 */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200873int rsl_establish_request(struct gsm_lchan *lchan, uint8_t link_id)
Harald Welteedcc5272009-08-09 13:47:35 +0200874{
Harald Welte3c9c5f92010-03-04 10:33:10 +0100875 struct msgb *msg;
Harald Welteedcc5272009-08-09 13:47:35 +0200876
Harald Weltef6093a42011-06-25 10:02:33 +0200877 msg = rsl_rll_simple(RSL_MT_EST_REQ, gsm_lchan2chan_nr(lchan),
Harald Welte3c9c5f92010-03-04 10:33:10 +0100878 link_id, 0);
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200879 msg->dst = lchan->ts->trx->rsl_link;
Harald Welteedcc5272009-08-09 13:47:35 +0200880
Harald Weltefda74ee2012-04-26 19:42:19 +0200881 DEBUGP(DRLL, "%s RSL RLL ESTABLISH REQ (link_id=0x%02x)\n",
882 gsm_lchan_name(lchan), link_id);
883
Harald Welteedcc5272009-08-09 13:47:35 +0200884 return abis_rsl_sendmsg(msg);
885}
886
Andreas Eversberg7d8fa342013-12-05 13:25:06 +0100887static void rsl_handle_release(struct gsm_lchan *lchan);
888
889/* Special work handler to handle missing RSL_MT_REL_CONF message from
890 * Nokia InSite BTS */
891static void lchan_rel_work_cb(void *data)
892{
893 struct gsm_lchan *lchan = data;
894 int sapi;
895
896 for (sapi = 0; sapi < ARRAY_SIZE(lchan->sapis); ++sapi) {
897 if (lchan->sapis[sapi] == LCHAN_SAPI_REL)
898 lchan->sapis[sapi] = LCHAN_SAPI_UNUSED;
899 }
900 rsl_handle_release(lchan);
901}
902
Harald Welted2dc1de2009-08-08 13:15:07 +0200903/* Chapter 8.3.7 Request the release of multiframe mode of RLL connection.
904 This is what higher layers should call. The BTS then responds with
905 RELEASE CONFIRM, which we in turn use to trigger RSL CHANNEL RELEASE,
906 which in turn is acknowledged by RSL CHANNEL RELEASE ACK, which calls
907 lchan_free() */
Holger Hans Peter Freyther5ca825e2012-12-06 12:01:38 +0100908int rsl_release_request(struct gsm_lchan *lchan, uint8_t link_id,
909 enum rsl_rel_mode release_mode)
Harald Welted2dc1de2009-08-08 13:15:07 +0200910{
Harald Welted2dc1de2009-08-08 13:15:07 +0200911
Harald Welte3c9c5f92010-03-04 10:33:10 +0100912 struct msgb *msg;
913
Harald Weltef6093a42011-06-25 10:02:33 +0200914 msg = rsl_rll_simple(RSL_MT_REL_REQ, gsm_lchan2chan_nr(lchan),
Harald Welte3c9c5f92010-03-04 10:33:10 +0100915 link_id, 0);
Holger Hans Peter Freyther4f5848d2010-06-08 11:57:45 +0800916 /* 0 is normal release, 1 is local end */
Holger Hans Peter Freyther5ca825e2012-12-06 12:01:38 +0100917 msgb_tv_put(msg, RSL_IE_RELEASE_MODE, release_mode);
Harald Welted2dc1de2009-08-08 13:15:07 +0200918
Harald Welte8e93b792009-12-29 10:44:17 +0100919 /* FIXME: start some timer in case we don't receive a REL ACK ? */
920
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200921 msg->dst = lchan->ts->trx->rsl_link;
Harald Welted2dc1de2009-08-08 13:15:07 +0200922
Harald Weltefda74ee2012-04-26 19:42:19 +0200923 DEBUGP(DRLL, "%s RSL RLL RELEASE REQ (link_id=0x%02x, reason=%u)\n",
Holger Hans Peter Freyther5ca825e2012-12-06 12:01:38 +0100924 gsm_lchan_name(lchan), link_id, release_mode);
Harald Weltefda74ee2012-04-26 19:42:19 +0200925
Andreas Eversberg7d8fa342013-12-05 13:25:06 +0100926 abis_rsl_sendmsg(msg);
927
928 /* Do not wait for Nokia BTS to send the confirm. */
929 if (is_nokia_bts(lchan->ts->trx->bts)
930 && lchan->ts->trx->bts->nokia.no_loc_rel_cnf
931 && release_mode == RSL_REL_LOCAL_END) {
932 DEBUGP(DRLL, "Scheduling release, becasuse Nokia InSite BTS does not send a RELease CONFirm.\n");
933 lchan->sapis[link_id & 0x7] = LCHAN_SAPI_REL;
934 lchan->rel_work.cb = lchan_rel_work_cb;
935 lchan->rel_work.data = lchan;
936 osmo_timer_schedule(&lchan->rel_work, 0, 0);
937 }
938
939 return 0;
Harald Welted2dc1de2009-08-08 13:15:07 +0200940}
941
Holger Hans Peter Freyther454140e2014-12-28 12:08:28 +0100942int rsl_lchan_mark_broken(struct gsm_lchan *lchan, const char *reason)
943{
944 lchan->state = LCHAN_S_BROKEN;
945 lchan->broken_reason = reason;
946 return 0;
947}
948
Holger Hans Peter Freyther74419492010-04-10 00:12:31 +0200949int rsl_lchan_set_state(struct gsm_lchan *lchan, int state)
950{
Neels Hofmeyrb0cc6422016-06-21 21:34:46 +0200951 DEBUGP(DRSL, "%s state %s -> %s\n",
952 gsm_lchan_name(lchan), gsm_lchans_name(lchan->state),
953 gsm_lchans_name(state));
Holger Hans Peter Freyther74419492010-04-10 00:12:31 +0200954 lchan->state = state;
955 return 0;
956}
957
Harald Welte702d8702008-12-26 20:25:35 +0000958/* Chapter 8.4.2: Channel Activate Acknowledge */
959static int rsl_rx_chan_act_ack(struct msgb *msg)
960{
961 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
Neels Hofmeyrf29dd5f2016-07-14 16:16:33 +0200962 struct gsm_lchan *lchan = msg->lchan;
Harald Welte702d8702008-12-26 20:25:35 +0000963
964 /* BTS has confirmed channel activation, we now need
965 * to assign the activated channel to the MS */
Harald Welte4b634542008-12-27 01:55:51 +0000966 if (rslh->ie_chan != RSL_IE_CHAN_NR)
967 return -EINVAL;
Harald Welted011e8b2009-11-29 22:45:52 +0100968
Neels Hofmeyrf29dd5f2016-07-14 16:16:33 +0200969 osmo_timer_del(&lchan->act_timer);
Harald Weltee8bd9e82011-08-10 23:26:33 +0200970
Neels Hofmeyrf29dd5f2016-07-14 16:16:33 +0200971 if (lchan->state == LCHAN_S_BROKEN) {
Holger Hans Peter Freyther21776242013-05-01 18:44:04 +0200972 LOGP(DRSL, LOGL_NOTICE, "%s CHAN ACT ACK for broken channel.\n",
Neels Hofmeyrf29dd5f2016-07-14 16:16:33 +0200973 gsm_lchan_name(lchan));
Holger Hans Peter Freyther21776242013-05-01 18:44:04 +0200974 return 0;
975 }
976
Neels Hofmeyrf29dd5f2016-07-14 16:16:33 +0200977 if (lchan->state != LCHAN_S_ACT_REQ)
Harald Welte1887f9d2009-12-29 10:52:38 +0100978 LOGP(DRSL, LOGL_NOTICE, "%s CHAN ACT ACK, but state %s\n",
Neels Hofmeyrf29dd5f2016-07-14 16:16:33 +0200979 gsm_lchan_name(lchan),
980 gsm_lchans_name(lchan->state));
981 rsl_lchan_set_state(lchan, LCHAN_S_ACTIVE);
Harald Welteb8bfc562009-12-21 13:27:11 +0100982
Neels Hofmeyrf29dd5f2016-07-14 16:16:33 +0200983 if (lchan->rqd_ref) {
984 rsl_send_imm_assignment(lchan);
985 talloc_free(lchan->rqd_ref);
986 lchan->rqd_ref = NULL;
987 lchan->rqd_ta = 0;
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +0800988 }
989
Neels Hofmeyrf29dd5f2016-07-14 16:16:33 +0200990 send_lchan_signal(S_LCHAN_ACTIVATE_ACK, lchan, NULL);
Harald Welted011e8b2009-11-29 22:45:52 +0100991
Harald Welte4b634542008-12-27 01:55:51 +0000992 return 0;
993}
Harald Welte702d8702008-12-26 20:25:35 +0000994
Harald Welte4b634542008-12-27 01:55:51 +0000995/* Chapter 8.4.3: Channel Activate NACK */
996static int rsl_rx_chan_act_nack(struct msgb *msg)
997{
Harald Welte6dab0552009-05-01 17:21:37 +0000998 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
999 struct tlv_parsed tp;
Harald Welte4b634542008-12-27 01:55:51 +00001000
Harald Weltee8bd9e82011-08-10 23:26:33 +02001001 osmo_timer_del(&msg->lchan->act_timer);
1002
Holger Hans Peter Freyther21776242013-05-01 18:44:04 +02001003 if (msg->lchan->state == LCHAN_S_BROKEN) {
1004 LOGP(DRSL, LOGL_ERROR,
1005 "%s CHANNEL ACTIVATE NACK for broken channel.\n",
1006 gsm_lchan_name(msg->lchan));
1007 return -1;
1008 }
1009
Daniel Willmann6fc6a122011-08-11 04:54:23 +02001010 LOGP(DRSL, LOGL_ERROR, "%s CHANNEL ACTIVATE NACK ",
Harald Welte (local)19ef62a2009-12-27 18:16:36 +01001011 gsm_lchan_name(msg->lchan));
Harald Welte (local)91b603d2009-12-27 11:48:11 +01001012
Harald Welte6dab0552009-05-01 17:21:37 +00001013 /* BTS has rejected channel activation ?!? */
1014 if (dh->ie_chan != RSL_IE_CHAN_NR)
Harald Welte4b634542008-12-27 01:55:51 +00001015 return -EINVAL;
Harald Welte6dab0552009-05-01 17:21:37 +00001016
1017 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
Harald Welte (local)3e460312009-12-27 18:12:29 +01001018 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE)) {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001019 const uint8_t *cause = TLVP_VAL(&tp, RSL_IE_CAUSE);
Harald Welte (local)3e460312009-12-27 18:12:29 +01001020 print_rsl_cause(LOGL_ERROR, cause,
Harald Welte8830e072009-07-28 17:58:09 +02001021 TLVP_LEN(&tp, RSL_IE_CAUSE));
Holger Hans Peter Freyther638da512012-12-06 19:25:06 +01001022 msg->lchan->error_cause = *cause;
Holger Hans Peter Freyther454140e2014-12-28 12:08:28 +01001023 if (*cause != RSL_ERR_RCH_ALR_ACTV_ALLOC) {
1024 rsl_lchan_mark_broken(msg->lchan, "NACK on activation");
1025 } else
Holger Hans Peter Freytherb3489392011-12-28 16:21:05 +01001026 rsl_rf_chan_release(msg->lchan, 1, SACCH_DEACTIVATE);
Daniel Willmann7ddc3182011-08-11 04:47:11 +02001027
Holger Hans Peter Freyther454140e2014-12-28 12:08:28 +01001028 } else {
1029 rsl_lchan_mark_broken(msg->lchan, "NACK on activation no IE");
1030 }
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +02001031
Harald Welte (local)91b603d2009-12-27 11:48:11 +01001032 LOGPC(DRSL, LOGL_ERROR, "\n");
1033
Holger Hans Peter Freyther08eebd52010-12-27 13:28:20 +01001034 send_lchan_signal(S_LCHAN_ACTIVATE_NACK, msg->lchan, NULL);
Harald Welte4b634542008-12-27 01:55:51 +00001035 return 0;
Harald Welte702d8702008-12-26 20:25:35 +00001036}
1037
Harald Welte7f93cea2009-02-23 00:02:59 +00001038/* Chapter 8.4.4: Connection Failure Indication */
1039static int rsl_rx_conn_fail(struct msgb *msg)
1040{
1041 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1042 struct tlv_parsed tp;
1043
Holger Hans Peter Freyther1e93b792014-04-19 16:45:36 +02001044 LOGP(DRSL, LOGL_NOTICE, "%s CONNECTION FAIL: RELEASING state %s ",
1045 gsm_lchan_name(msg->lchan),
1046 gsm_lchans_name(msg->lchan->state));
1047
Harald Welte7f93cea2009-02-23 00:02:59 +00001048 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
1049
Harald Welte8830e072009-07-28 17:58:09 +02001050 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
Harald Welte5b8ed432009-12-24 12:20:20 +01001051 print_rsl_cause(LOGL_NOTICE, TLVP_VAL(&tp, RSL_IE_CAUSE),
Harald Welte8830e072009-07-28 17:58:09 +02001052 TLVP_LEN(&tp, RSL_IE_CAUSE));
1053
Harald Welte (local)fc057502009-12-26 22:33:09 +01001054 LOGPC(DRSL, LOGL_NOTICE, "\n");
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +02001055 osmo_counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rf_fail);
Holger Hans Peter Freyther0e4e73a2014-04-19 17:38:33 +02001056 return rsl_rf_chan_release_err(msg->lchan);
Harald Welte7f93cea2009-02-23 00:02:59 +00001057}
1058
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001059static void print_meas_rep_uni(struct gsm_meas_rep_unidir *mru,
1060 const char *prefix)
1061{
Harald Welte6739dfb2009-12-16 16:52:07 +01001062 DEBUGPC(DMEAS, "RXL-FULL-%s=%3ddBm RXL-SUB-%s=%3ddBm ",
1063 prefix, rxlev2dbm(mru->full.rx_lev),
1064 prefix, rxlev2dbm(mru->sub.rx_lev));
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001065 DEBUGPC(DMEAS, "RXQ-FULL-%s=%d RXQ-SUB-%s=%d ",
1066 prefix, mru->full.rx_qual, prefix, mru->sub.rx_qual);
1067}
1068
Harald Welte0c1bd612012-07-02 17:12:08 +02001069static void print_meas_rep(struct gsm_lchan *lchan, struct gsm_meas_rep *mr)
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001070{
Harald Welte6739dfb2009-12-16 16:52:07 +01001071 int i;
Harald Welte0c1bd612012-07-02 17:12:08 +02001072 char *name = "";
Harald Welte6739dfb2009-12-16 16:52:07 +01001073
Harald Welte7184bd02015-12-28 14:04:36 +01001074 if (lchan && lchan->conn)
Harald Welte0c1bd612012-07-02 17:12:08 +02001075 name = subscr_name(lchan->conn->subscr);
1076
1077 DEBUGP(DMEAS, "[%s] MEASUREMENT RESULT NR=%d ", name, mr->nr);
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001078
1079 if (mr->flags & MEAS_REP_F_DL_DTX)
1080 DEBUGPC(DMEAS, "DTXd ");
1081
1082 print_meas_rep_uni(&mr->ul, "ul");
1083 DEBUGPC(DMEAS, "BS_POWER=%d ", mr->bs_power);
1084 if (mr->flags & MEAS_REP_F_MS_TO)
1085 DEBUGPC(DMEAS, "MS_TO=%d ", mr->ms_timing_offset);
1086
1087 if (mr->flags & MEAS_REP_F_MS_L1) {
Harald Welte6739dfb2009-12-16 16:52:07 +01001088 DEBUGPC(DMEAS, "L1_MS_PWR=%3ddBm ", mr->ms_l1.pwr);
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001089 DEBUGPC(DMEAS, "L1_FPC=%u ",
1090 mr->flags & MEAS_REP_F_FPC ? 1 : 0);
1091 DEBUGPC(DMEAS, "L1_TA=%u ", mr->ms_l1.ta);
1092 }
1093
1094 if (mr->flags & MEAS_REP_F_UL_DTX)
1095 DEBUGPC(DMEAS, "DTXu ");
1096 if (mr->flags & MEAS_REP_F_BA1)
1097 DEBUGPC(DMEAS, "BA1 ");
1098 if (!(mr->flags & MEAS_REP_F_DL_VALID))
1099 DEBUGPC(DMEAS, "NOT VALID ");
1100 else
1101 print_meas_rep_uni(&mr->dl, "dl");
1102
1103 DEBUGPC(DMEAS, "NUM_NEIGH=%u\n", mr->num_cell);
Harald Welte479015b2009-12-19 18:33:05 +01001104 if (mr->num_cell == 7)
1105 return;
Harald Welte6739dfb2009-12-16 16:52:07 +01001106 for (i = 0; i < mr->num_cell; i++) {
1107 struct gsm_meas_rep_cell *mrc = &mr->cell[i];
Harald Welte303e5e02009-12-25 23:02:22 +01001108 DEBUGP(DMEAS, "IDX=%u ARFCN=%u BSIC=%u => %d dBm\n",
1109 mrc->neigh_idx, mrc->arfcn, mrc->bsic, rxlev2dbm(mrc->rxlev));
Harald Welte6739dfb2009-12-16 16:52:07 +01001110 }
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001111}
1112
Harald Welte440fed02009-05-01 18:43:47 +00001113static int rsl_rx_meas_res(struct msgb *msg)
1114{
1115 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1116 struct tlv_parsed tp;
Harald Welted12b0fd2009-12-15 21:36:05 +01001117 struct gsm_meas_rep *mr = lchan_next_meas_rep(msg->lchan);
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001118 uint8_t len;
1119 const uint8_t *val;
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001120 int rc;
Harald Welte440fed02009-05-01 18:43:47 +00001121
Harald Welteb8bfc562009-12-21 13:27:11 +01001122 /* check if this channel is actually active */
1123 /* FIXME: maybe this check should be way more generic/centralized */
Harald Welte8e93b792009-12-29 10:44:17 +01001124 if (msg->lchan->state != LCHAN_S_ACTIVE) {
Holger Hans Peter Freytherc44db4a2010-07-29 14:50:57 +08001125 LOGP(DRSL, LOGL_DEBUG, "%s: MEAS RES for inactive channel\n",
Harald Welte8e93b792009-12-29 10:44:17 +01001126 gsm_lchan_name(msg->lchan));
Harald Welteb8bfc562009-12-21 13:27:11 +01001127 return 0;
Harald Welte8e93b792009-12-29 10:44:17 +01001128 }
Harald Welteb8bfc562009-12-21 13:27:11 +01001129
Harald Welted12b0fd2009-12-15 21:36:05 +01001130 memset(mr, 0, sizeof(*mr));
Harald Welte33e65972009-12-16 23:29:34 +01001131 mr->lchan = msg->lchan;
Harald Weltedbb1d882009-11-30 19:16:47 +01001132
Harald Welte440fed02009-05-01 18:43:47 +00001133 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
1134
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001135 if (!TLVP_PRESENT(&tp, RSL_IE_MEAS_RES_NR) ||
1136 !TLVP_PRESENT(&tp, RSL_IE_UPLINK_MEAS) ||
1137 !TLVP_PRESENT(&tp, RSL_IE_BS_POWER))
1138 return -EIO;
1139
1140 /* Mandatory Parts */
Harald Welted12b0fd2009-12-15 21:36:05 +01001141 mr->nr = *TLVP_VAL(&tp, RSL_IE_MEAS_RES_NR);
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001142
1143 len = TLVP_LEN(&tp, RSL_IE_UPLINK_MEAS);
1144 val = TLVP_VAL(&tp, RSL_IE_UPLINK_MEAS);
1145 if (len >= 3) {
1146 if (val[0] & 0x40)
Harald Welted12b0fd2009-12-15 21:36:05 +01001147 mr->flags |= MEAS_REP_F_DL_DTX;
1148 mr->ul.full.rx_lev = val[0] & 0x3f;
1149 mr->ul.sub.rx_lev = val[1] & 0x3f;
1150 mr->ul.full.rx_qual = val[2]>>3 & 0x7;
1151 mr->ul.sub.rx_qual = val[2] & 0x7;
Harald Welte440fed02009-05-01 18:43:47 +00001152 }
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001153
Harald Welted12b0fd2009-12-15 21:36:05 +01001154 mr->bs_power = *TLVP_VAL(&tp, RSL_IE_BS_POWER);
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001155
1156 /* Optional Parts */
Harald Welte440fed02009-05-01 18:43:47 +00001157 if (TLVP_PRESENT(&tp, RSL_IE_MS_TIMING_OFFSET))
Harald Welted12b0fd2009-12-15 21:36:05 +01001158 mr->ms_timing_offset =
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001159 *TLVP_VAL(&tp, RSL_IE_MS_TIMING_OFFSET);
1160
Harald Weltefe9af262009-06-20 18:44:35 +02001161 if (TLVP_PRESENT(&tp, RSL_IE_L1_INFO)) {
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001162 struct e1inp_sign_link *sign_link = msg->dst;
1163
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001164 val = TLVP_VAL(&tp, RSL_IE_L1_INFO);
Harald Welted12b0fd2009-12-15 21:36:05 +01001165 mr->flags |= MEAS_REP_F_MS_L1;
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001166 mr->ms_l1.pwr = ms_pwr_dbm(sign_link->trx->bts->band, val[0] >> 3);
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001167 if (val[0] & 0x04)
Harald Welted12b0fd2009-12-15 21:36:05 +01001168 mr->flags |= MEAS_REP_F_FPC;
1169 mr->ms_l1.ta = val[1];
Andreas Eversberg3365cd12011-12-24 11:49:05 +01001170 /* BS11 and Nokia reports TA shifted by 2 bits */
1171 if (msg->lchan->ts->trx->bts->type == GSM_BTS_TYPE_BS11
1172 || msg->lchan->ts->trx->bts->type == GSM_BTS_TYPE_NOKIA_SITE)
Andreas Eversberg2957de92011-12-16 17:45:37 +01001173 mr->ms_l1.ta >>= 2;
Harald Weltefe9af262009-06-20 18:44:35 +02001174 }
Harald Weltef7c43522009-06-09 20:24:21 +00001175 if (TLVP_PRESENT(&tp, RSL_IE_L3_INFO)) {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001176 msg->l3h = (uint8_t *) TLVP_VAL(&tp, RSL_IE_L3_INFO);
Harald Welted12b0fd2009-12-15 21:36:05 +01001177 rc = gsm48_parse_meas_rep(mr, msg);
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001178 if (rc < 0)
1179 return rc;
1180 }
1181
Harald Welte0c1bd612012-07-02 17:12:08 +02001182 print_meas_rep(msg->lchan, mr);
Harald Welte60d68f12009-06-05 20:07:43 +00001183
Holger Hans Peter Freyther08eebd52010-12-27 13:28:20 +01001184 send_lchan_signal(S_LCHAN_MEAS_REP, msg->lchan, mr);
Harald Weltedbb1d882009-11-30 19:16:47 +01001185
Harald Welte75d34a82009-05-23 06:11:13 +00001186 return 0;
Harald Welte440fed02009-05-01 18:43:47 +00001187}
1188
Harald Welted011e8b2009-11-29 22:45:52 +01001189/* Chapter 8.4.7 */
1190static int rsl_rx_hando_det(struct msgb *msg)
1191{
1192 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1193 struct tlv_parsed tp;
1194
Harald Welte (local)19ef62a2009-12-27 18:16:36 +01001195 DEBUGP(DRSL, "%s HANDOVER DETECT ", gsm_lchan_name(msg->lchan));
Harald Welted011e8b2009-11-29 22:45:52 +01001196
1197 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
1198
1199 if (TLVP_PRESENT(&tp, RSL_IE_ACCESS_DELAY))
1200 DEBUGPC(DRSL, "access delay = %u\n",
1201 *TLVP_VAL(&tp, RSL_IE_ACCESS_DELAY));
1202 else
1203 DEBUGPC(DRSL, "\n");
1204
Holger Hans Peter Freyther08eebd52010-12-27 13:28:20 +01001205 send_lchan_signal(S_LCHAN_HANDOVER_DETECT, msg->lchan, NULL);
Harald Welted011e8b2009-11-29 22:45:52 +01001206
1207 return 0;
1208}
1209
Neels Hofmeyr285df2e2016-06-13 12:28:21 +02001210static bool lchan_may_change_pdch(struct gsm_lchan *lchan, bool pdch_act)
1211{
1212 struct gsm_bts_trx_ts *ts;
Neels Hofmeyr285df2e2016-06-13 12:28:21 +02001213
1214 OSMO_ASSERT(lchan);
1215
1216 ts = lchan->ts;
1217 OSMO_ASSERT(ts);
1218 OSMO_ASSERT(ts->trx);
1219 OSMO_ASSERT(ts->trx->bts);
1220
1221 if (lchan->ts->pchan != GSM_PCHAN_TCH_F_PDCH) {
Neels Hofmeyrdd49bee2016-06-21 20:53:27 +02001222 LOGP(DRSL, LOGL_ERROR, "%s pchan=%s Rx PDCH %s ACK"
1223 " for channel that is no TCH/F_PDCH\n",
1224 gsm_lchan_name(lchan),
Neels Hofmeyr285df2e2016-06-13 12:28:21 +02001225 gsm_pchan_name(ts->pchan),
1226 pdch_act? "ACT" : "DEACT");
1227 return false;
1228 }
1229
Neels Hofmeyr832afa32016-06-14 13:12:00 +02001230 if (lchan->state != LCHAN_S_NONE) {
Neels Hofmeyrdd49bee2016-06-21 20:53:27 +02001231 LOGP(DRSL, LOGL_ERROR, "%s pchan=%s Rx PDCH %s ACK"
1232 " in unexpected state: %s\n",
1233 gsm_lchan_name(lchan),
Neels Hofmeyr285df2e2016-06-13 12:28:21 +02001234 gsm_pchan_name(ts->pchan),
1235 pdch_act? "ACT" : "DEACT",
1236 gsm_lchans_name(lchan->state));
1237 return false;
1238 }
1239 return true;
1240}
1241
Andreas Eversberg9df268e2013-10-11 13:32:30 +02001242static int rsl_rx_pdch_act_ack(struct msgb *msg)
1243{
Neels Hofmeyr285df2e2016-06-13 12:28:21 +02001244 if (!lchan_may_change_pdch(msg->lchan, true))
1245 return -EINVAL;
1246
Neels Hofmeyr2ebacce2016-06-14 14:08:35 +02001247 msg->lchan->ts->flags |= TS_F_PDCH_ACTIVE;
Neels Hofmeyr32019882016-06-15 15:32:29 +02001248 msg->lchan->ts->flags &= ~TS_F_PDCH_ACT_PENDING;
Andreas Eversberg9df268e2013-10-11 13:32:30 +02001249
Andreas Eversberg9df268e2013-10-11 13:32:30 +02001250 return 0;
1251}
1252
1253static int rsl_rx_pdch_deact_ack(struct msgb *msg)
1254{
Neels Hofmeyr285df2e2016-06-13 12:28:21 +02001255 if (!lchan_may_change_pdch(msg->lchan, false))
1256 return -EINVAL;
1257
Neels Hofmeyr2ebacce2016-06-14 14:08:35 +02001258 msg->lchan->ts->flags &= ~TS_F_PDCH_ACTIVE;
Neels Hofmeyr32019882016-06-15 15:32:29 +02001259 msg->lchan->ts->flags &= ~TS_F_PDCH_DEACT_PENDING;
Andreas Eversberg9df268e2013-10-11 13:32:30 +02001260
1261 rsl_chan_activate_lchan(msg->lchan, msg->lchan->dyn_pdch.act_type,
1262 msg->lchan->dyn_pdch.ho_ref);
1263
1264 return 0;
1265}
1266
Harald Welte52b1f982008-12-23 20:25:15 +00001267static int abis_rsl_rx_dchan(struct msgb *msg)
1268{
Harald Welte8470bf22008-12-25 23:28:35 +00001269 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
1270 int rc = 0;
Harald Weltef325eb42009-02-19 17:07:39 +00001271 char *ts_name;
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001272 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte52b1f982008-12-23 20:25:15 +00001273
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001274 msg->lchan = lchan_lookup(sign_link->trx, rslh->chan_nr);
Harald Welte (local)19ef62a2009-12-27 18:16:36 +01001275 ts_name = gsm_lchan_name(msg->lchan);
Harald Weltef325eb42009-02-19 17:07:39 +00001276
Harald Welte8470bf22008-12-25 23:28:35 +00001277 switch (rslh->c.msg_type) {
Harald Welte52b1f982008-12-23 20:25:15 +00001278 case RSL_MT_CHAN_ACTIV_ACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001279 DEBUGP(DRSL, "%s CHANNEL ACTIVATE ACK\n", ts_name);
Harald Welte4b634542008-12-27 01:55:51 +00001280 rc = rsl_rx_chan_act_ack(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001281 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001282 case RSL_MT_CHAN_ACTIV_NACK:
Harald Welte4b634542008-12-27 01:55:51 +00001283 rc = rsl_rx_chan_act_nack(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001284 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001285 case RSL_MT_CONN_FAIL:
Harald Welte7f93cea2009-02-23 00:02:59 +00001286 rc = rsl_rx_conn_fail(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001287 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001288 case RSL_MT_MEAS_RES:
Harald Welte440fed02009-05-01 18:43:47 +00001289 rc = rsl_rx_meas_res(msg);
Harald Welte2d5b6382008-12-27 19:46:06 +00001290 break;
Harald Welted011e8b2009-11-29 22:45:52 +01001291 case RSL_MT_HANDO_DET:
1292 rc = rsl_rx_hando_det(msg);
1293 break;
Harald Welte2d5b6382008-12-27 19:46:06 +00001294 case RSL_MT_RF_CHAN_REL_ACK:
Harald Welte64bb7542011-01-14 14:16:16 +01001295 rc = rsl_rx_rf_chan_rel_ack(msg->lchan);
Harald Welte8470bf22008-12-25 23:28:35 +00001296 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001297 case RSL_MT_MODE_MODIFY_ACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001298 DEBUGP(DRSL, "%s CHANNEL MODE MODIFY ACK\n", ts_name);
Harald Welteda783762009-02-18 03:29:53 +00001299 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001300 case RSL_MT_MODE_MODIFY_NACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001301 LOGP(DRSL, LOGL_ERROR, "%s CHANNEL MODE MODIFY NACK\n", ts_name);
Harald Welteda783762009-02-18 03:29:53 +00001302 break;
Harald Welte9c880c92009-10-24 10:29:22 +02001303 case RSL_MT_IPAC_PDCH_ACT_ACK:
Neels Hofmeyr9f5d2312016-05-31 17:51:41 +02001304 DEBUGP(DRSL, "%s IPAC PDCH ACT ACK\n", ts_name);
Andreas Eversberg9df268e2013-10-11 13:32:30 +02001305 rc = rsl_rx_pdch_act_ack(msg);
Harald Welte9c880c92009-10-24 10:29:22 +02001306 break;
1307 case RSL_MT_IPAC_PDCH_ACT_NACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001308 LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH ACT NACK\n", ts_name);
Harald Welte9c880c92009-10-24 10:29:22 +02001309 break;
1310 case RSL_MT_IPAC_PDCH_DEACT_ACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001311 DEBUGP(DRSL, "%s IPAC PDCH DEACT ACK\n", ts_name);
Andreas Eversberg9df268e2013-10-11 13:32:30 +02001312 rc = rsl_rx_pdch_deact_ack(msg);
Harald Welte9c880c92009-10-24 10:29:22 +02001313 break;
1314 case RSL_MT_IPAC_PDCH_DEACT_NACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001315 LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH DEACT NACK\n", ts_name);
Harald Welte9c880c92009-10-24 10:29:22 +02001316 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001317 case RSL_MT_PHY_CONTEXT_CONF:
1318 case RSL_MT_PREPROC_MEAS_RES:
Harald Welte52b1f982008-12-23 20:25:15 +00001319 case RSL_MT_TALKER_DET:
1320 case RSL_MT_LISTENER_DET:
1321 case RSL_MT_REMOTE_CODEC_CONF_REP:
1322 case RSL_MT_MR_CODEC_MOD_ACK:
1323 case RSL_MT_MR_CODEC_MOD_NACK:
1324 case RSL_MT_MR_CODEC_MOD_PER:
Harald Welte5b8ed432009-12-24 12:20:20 +01001325 LOGP(DRSL, LOGL_NOTICE, "%s Unimplemented Abis RSL DChan "
1326 "msg 0x%02x\n", ts_name, rslh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001327 break;
1328 default:
Harald Welte5b8ed432009-12-24 12:20:20 +01001329 LOGP(DRSL, LOGL_NOTICE, "%s unknown Abis RSL DChan msg 0x%02x\n",
1330 ts_name, rslh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001331 return -EINVAL;
1332 }
Harald Weltef325eb42009-02-19 17:07:39 +00001333
Harald Welte8470bf22008-12-25 23:28:35 +00001334 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001335}
1336
Harald Welte702d8702008-12-26 20:25:35 +00001337static int rsl_rx_error_rep(struct msgb *msg)
1338{
1339 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
Harald Welte8830e072009-07-28 17:58:09 +02001340 struct tlv_parsed tp;
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001341 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte702d8702008-12-26 20:25:35 +00001342
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001343 LOGP(DRSL, LOGL_ERROR, "%s ERROR REPORT ", gsm_trx_name(sign_link->trx));
Harald Welte8830e072009-07-28 17:58:09 +02001344
1345 rsl_tlv_parse(&tp, rslh->data, msgb_l2len(msg)-sizeof(*rslh));
1346
1347 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
Harald Welte5b8ed432009-12-24 12:20:20 +01001348 print_rsl_cause(LOGL_ERROR, TLVP_VAL(&tp, RSL_IE_CAUSE),
Harald Welte8830e072009-07-28 17:58:09 +02001349 TLVP_LEN(&tp, RSL_IE_CAUSE));
1350
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001351 LOGPC(DRSL, LOGL_ERROR, "\n");
Harald Welte702d8702008-12-26 20:25:35 +00001352
1353 return 0;
1354}
1355
Harald Welte52b1f982008-12-23 20:25:15 +00001356static int abis_rsl_rx_trx(struct msgb *msg)
1357{
Harald Welte702d8702008-12-26 20:25:35 +00001358 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001359 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte8470bf22008-12-25 23:28:35 +00001360 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001361
1362 switch (rslh->msg_type) {
Harald Welte702d8702008-12-26 20:25:35 +00001363 case RSL_MT_ERROR_REPORT:
1364 rc = rsl_rx_error_rep(msg);
1365 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001366 case RSL_MT_RF_RES_IND:
1367 /* interference on idle channels of TRX */
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001368 //DEBUGP(DRSL, "%s RF Resource Indication\n", gsm_trx_name(sign_link->trx));
Harald Welte8f5e2392009-02-03 12:57:37 +00001369 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001370 case RSL_MT_OVERLOAD:
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +02001371 /* indicate CCCH / ACCH / processor overload */
Harald Welte (local)d48f4eb2009-12-28 23:14:22 +01001372 LOGP(DRSL, LOGL_ERROR, "%s CCCH/ACCH/CPU Overload\n",
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001373 gsm_trx_name(sign_link->trx));
Harald Welte52b1f982008-12-23 20:25:15 +00001374 break;
Dieter Spaar16646022011-07-28 00:01:50 +02001375 case 0x42: /* Nokia specific: SI End ACK */
1376 LOGP(DRSL, LOGL_INFO, "Nokia SI End ACK\n");
1377 break;
1378 case 0x43: /* Nokia specific: SI End NACK */
1379 LOGP(DRSL, LOGL_INFO, "Nokia SI End NACK\n");
1380 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001381 default:
Harald Welte (local)d48f4eb2009-12-28 23:14:22 +01001382 LOGP(DRSL, LOGL_NOTICE, "%s Unknown Abis RSL TRX message "
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001383 "type 0x%02x\n", gsm_trx_name(sign_link->trx), rslh->msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001384 return -EINVAL;
1385 }
Harald Welte8470bf22008-12-25 23:28:35 +00001386 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001387}
1388
Harald Welteb7e81162009-08-10 00:26:10 +02001389/* If T3101 expires, we never received a response to IMMEDIATE ASSIGN */
1390static void t3101_expired(void *data)
1391{
1392 struct gsm_lchan *lchan = data;
1393
Holger Hans Peter Freytherb3489392011-12-28 16:21:05 +01001394 rsl_rf_chan_release(lchan, 1, SACCH_DEACTIVATE);
Harald Welteb7e81162009-08-10 00:26:10 +02001395}
1396
Holger Hans Peter Freytherf30c0dc2010-05-31 21:33:15 +08001397/* If T3111 expires, we will send the RF Channel Request */
1398static void t3111_expired(void *data)
1399{
1400 struct gsm_lchan *lchan = data;
1401
Holger Hans Peter Freytherb3489392011-12-28 16:21:05 +01001402 rsl_rf_chan_release(lchan, 0, SACCH_NONE);
1403}
1404
1405/* If T3109 expires the MS has not send a UA/UM do the error release */
1406static void t3109_expired(void *data)
1407{
1408 struct gsm_lchan *lchan = data;
1409
1410 LOGP(DRSL, LOGL_ERROR,
1411 "%s SACCH deactivation timeout.\n", gsm_lchan_name(lchan));
1412 rsl_rf_chan_release(lchan, 1, SACCH_NONE);
Holger Hans Peter Freytherf30c0dc2010-05-31 21:33:15 +08001413}
1414
Harald Welte2862dca2010-12-23 14:39:29 +01001415/* Format an IMM ASS REJ according to 04.08 Chapter 9.1.20 */
1416static int rsl_send_imm_ass_rej(struct gsm_bts *bts,
1417 unsigned int num_req_refs,
1418 struct gsm48_req_ref *rqd_refs,
1419 uint8_t wait_ind)
1420{
1421 uint8_t buf[GSM_MACBLOCK_LEN];
1422 struct gsm48_imm_ass_rej *iar = (struct gsm48_imm_ass_rej *)buf;
1423
1424 /* create IMMEDIATE ASSIGN REJECT 04.08 message */
1425 memset(iar, 0, sizeof(*iar));
1426 iar->proto_discr = GSM48_PDISC_RR;
Andreas Eversberg75e13a42013-02-07 11:51:16 +01001427 iar->msg_type = GSM48_MT_RR_IMM_ASS_REJ;
Harald Welte2862dca2010-12-23 14:39:29 +01001428 iar->page_mode = GSM48_PM_SAME;
1429
1430 memcpy(&iar->req_ref1, &rqd_refs[0], sizeof(iar->req_ref1));
1431 iar->wait_ind1 = wait_ind;
1432
1433 if (num_req_refs >= 2)
1434 memcpy(&iar->req_ref2, &rqd_refs[1], sizeof(iar->req_ref2));
1435 else
1436 memcpy(&iar->req_ref2, &rqd_refs[0], sizeof(iar->req_ref2));
1437 iar->wait_ind2 = wait_ind;
1438
1439 if (num_req_refs >= 3)
1440 memcpy(&iar->req_ref3, &rqd_refs[2], sizeof(iar->req_ref3));
1441 else
1442 memcpy(&iar->req_ref3, &rqd_refs[0], sizeof(iar->req_ref3));
1443 iar->wait_ind3 = wait_ind;
1444
1445 if (num_req_refs >= 4)
1446 memcpy(&iar->req_ref4, &rqd_refs[3], sizeof(iar->req_ref4));
1447 else
1448 memcpy(&iar->req_ref4, &rqd_refs[0], sizeof(iar->req_ref4));
1449 iar->wait_ind4 = wait_ind;
1450
Andreas Eversberg75e13a42013-02-07 11:51:16 +01001451 /* we need to subtract 1 byte from sizeof(*iar) since ia includes the l2_plen field */
1452 iar->l2_plen = GSM48_LEN2PLEN((sizeof(*iar)-1));
1453
1454 return rsl_imm_assign_cmd(bts, sizeof(*iar), (uint8_t *) iar);
Harald Welte2862dca2010-12-23 14:39:29 +01001455}
1456
Harald Welte8470bf22008-12-25 23:28:35 +00001457/* MS has requested a channel on the RACH */
Harald Welte52b1f982008-12-23 20:25:15 +00001458static int rsl_rx_chan_rqd(struct msgb *msg)
1459{
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001460 struct e1inp_sign_link *sign_link = msg->dst;
1461 struct gsm_bts *bts = sign_link->trx->bts;
Harald Welte8470bf22008-12-25 23:28:35 +00001462 struct abis_rsl_dchan_hdr *rqd_hdr = msgb_l2(msg);
1463 struct gsm48_req_ref *rqd_ref;
Harald Welte8470bf22008-12-25 23:28:35 +00001464 enum gsm_chan_t lctype;
Harald Welte2cbe0922008-12-29 04:09:31 +00001465 enum gsm_chreq_reason_t chreq_reason;
Harald Welte8470bf22008-12-25 23:28:35 +00001466 struct gsm_lchan *lchan;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001467 uint8_t rqd_ta;
Holger Hans Peter Freyther457c2a82010-09-06 08:58:42 +08001468 int is_lu;
Harald Welte8470bf22008-12-25 23:28:35 +00001469
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001470 uint16_t arfcn;
Holger Hans Peter Freytherc6d0a172012-02-03 20:10:13 +01001471 uint8_t subch;
Harald Welte52b1f982008-12-23 20:25:15 +00001472
Harald Welte8470bf22008-12-25 23:28:35 +00001473 /* parse request reference to be used in immediate assign */
1474 if (rqd_hdr->data[0] != RSL_IE_REQ_REFERENCE)
1475 return -EINVAL;
1476
1477 rqd_ref = (struct gsm48_req_ref *) &rqd_hdr->data[1];
1478
1479 /* parse access delay and use as TA */
1480 if (rqd_hdr->data[sizeof(struct gsm48_req_ref)+1] != RSL_IE_ACCESS_DELAY)
1481 return -EINVAL;
1482 rqd_ta = rqd_hdr->data[sizeof(struct gsm48_req_ref)+2];
1483
1484 /* determine channel type (SDCCH/TCH_F/TCH_H) based on
1485 * request reference RA */
Holger Hans Peter Freyther78891072010-09-06 09:36:02 +08001486 lctype = get_ctype_by_chreq(bts->network, rqd_ref->ra);
1487 chreq_reason = get_reason_by_chreq(rqd_ref->ra, bts->network->neci);
Harald Welte2cbe0922008-12-29 04:09:31 +00001488
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +02001489 osmo_counter_inc(bts->network->stats.chreq.total);
Harald Welte24ff6ee2009-12-22 00:41:05 +01001490
Holger Hans Peter Freyther457c2a82010-09-06 08:58:42 +08001491 /*
1492 * We want LOCATION UPDATES to succeed and will assign a TCH
1493 * if we have no SDCCH available.
1494 */
1495 is_lu = !!(chreq_reason == GSM_CHREQ_REASON_LOCATION_UPD);
1496
Harald Welte8470bf22008-12-25 23:28:35 +00001497 /* check availability / allocate channel */
Holger Hans Peter Freyther457c2a82010-09-06 08:58:42 +08001498 lchan = lchan_alloc(bts, lctype, is_lu);
Harald Welte8470bf22008-12-25 23:28:35 +00001499 if (!lchan) {
Harald Welte (local)2f5df852009-12-27 13:48:09 +01001500 LOGP(DRSL, LOGL_NOTICE, "BTS %d CHAN RQD: no resources for %s 0x%x\n",
Harald Welte (local)ccd88452009-12-27 18:05:25 +01001501 msg->lchan->ts->trx->bts->nr, gsm_lchant_name(lctype), rqd_ref->ra);
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +02001502 osmo_counter_inc(bts->network->stats.chreq.no_channel);
Harald Welte2862dca2010-12-23 14:39:29 +01001503 /* FIXME gather multiple CHAN RQD and reject up to 4 at the same time */
1504 if (bts->network->T3122)
1505 rsl_send_imm_ass_rej(bts, 1, rqd_ref, bts->network->T3122 & 0xff);
Harald Welte1dcc2602012-11-13 04:46:03 +01001506 return 0;
Harald Welte8470bf22008-12-25 23:28:35 +00001507 }
1508
Harald Welte8e93b792009-12-29 10:44:17 +01001509 if (lchan->state != LCHAN_S_NONE)
1510 LOGP(DRSL, LOGL_NOTICE, "%s lchan_alloc() returned channel "
Harald Welte1887f9d2009-12-29 10:52:38 +01001511 "in state %s\n", gsm_lchan_name(lchan),
1512 gsm_lchans_name(lchan->state));
Harald Welte (local)3e460312009-12-27 18:12:29 +01001513
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +08001514 /* save the RACH data as we need it after the CHAN ACT ACK */
1515 lchan->rqd_ref = talloc_zero(bts, struct gsm48_req_ref);
1516 if (!lchan->rqd_ref) {
1517 LOGP(DRSL, LOGL_ERROR, "Failed to allocate gsm48_req_ref.\n");
1518 lchan_free(lchan);
1519 return -ENOMEM;
1520 }
1521
1522 memcpy(lchan->rqd_ref, rqd_ref, sizeof(*rqd_ref));
1523 lchan->rqd_ta = rqd_ta;
1524
Harald Welte8470bf22008-12-25 23:28:35 +00001525 arfcn = lchan->ts->trx->arfcn;
1526 subch = lchan->nr;
Harald Welte52b1f982008-12-23 20:25:15 +00001527
Harald Welte08d91a52009-08-30 15:37:11 +09001528 lchan->encr.alg_id = RSL_ENC_ALG_A5(0); /* no encryption */
Harald Welte (local)0e451d02009-08-13 10:14:26 +02001529 lchan->ms_power = ms_pwr_ctl_lvl(bts->band, bts->ms_max_power);
Harald Welte0b2124b2009-08-10 00:45:40 +02001530 lchan->bs_power = 0; /* 0dB reduction, output power = Pn */
Harald Welte9943c5b2009-07-29 15:41:29 +02001531 lchan->rsl_cmode = RSL_CMOD_SPD_SIGN;
Harald Welte196d0522009-08-28 23:28:28 +09001532 lchan->tch_mode = GSM48_CMODE_SIGN;
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +08001533
Harald Weltee8bd9e82011-08-10 23:26:33 +02001534 /* Start another timer or assume the BTS sends a ACK/NACK? */
1535 lchan->act_timer.cb = lchan_act_tmr_cb;
1536 lchan->act_timer.data = lchan;
1537 osmo_timer_schedule(&lchan->act_timer, 4, 0);
1538
Andreas Eversberg2957de92011-12-16 17:45:37 +01001539 DEBUGP(DRSL, "%s Activating ARFCN(%u) SS(%u) lctype %s "
1540 "r=%s ra=0x%02x ta=%d\n", gsm_lchan_name(lchan), arfcn, subch,
1541 gsm_lchant_name(lchan->type), gsm_chreq_name(chreq_reason),
1542 rqd_ref->ra, rqd_ta);
1543
Neels Hofmeyr81516482016-07-15 01:26:03 +02001544 rsl_chan_activate_lchan(lchan, RSL_ACT_INTRA_IMM_ASS, 0);
Harald Welte52b1f982008-12-23 20:25:15 +00001545
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +08001546 return 0;
1547}
1548
1549static int rsl_send_imm_assignment(struct gsm_lchan *lchan)
1550{
1551 struct gsm_bts *bts = lchan->ts->trx->bts;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001552 uint8_t buf[GSM_MACBLOCK_LEN];
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +08001553 struct gsm48_imm_ass *ia = (struct gsm48_imm_ass *) buf;
1554
Harald Welte52b1f982008-12-23 20:25:15 +00001555 /* create IMMEDIATE ASSIGN 04.08 messge */
laforge09108bf2010-06-20 15:18:46 +02001556 memset(ia, 0, sizeof(*ia));
laforgecfa4a012010-06-21 12:08:52 +02001557 /* we set ia->l2_plen once we know the length of the MA below */
laforge09108bf2010-06-20 15:18:46 +02001558 ia->proto_discr = GSM48_PDISC_RR;
1559 ia->msg_type = GSM48_MT_RR_IMM_ASS;
1560 ia->page_mode = GSM48_PM_SAME;
1561 gsm48_lchan2chan_desc(&ia->chan_desc, lchan);
Harald Weltea39b0f22010-06-14 22:26:10 +02001562
Harald Welte8470bf22008-12-25 23:28:35 +00001563 /* use request reference extracted from CHAN_RQD */
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +08001564 memcpy(&ia->req_ref, lchan->rqd_ref, sizeof(ia->req_ref));
1565 ia->timing_advance = lchan->rqd_ta;
Harald Weltea39b0f22010-06-14 22:26:10 +02001566 if (!lchan->ts->hopping.enabled) {
laforge09108bf2010-06-20 15:18:46 +02001567 ia->mob_alloc_len = 0;
Harald Weltea39b0f22010-06-14 22:26:10 +02001568 } else {
laforge09108bf2010-06-20 15:18:46 +02001569 ia->mob_alloc_len = lchan->ts->hopping.ma_len;
1570 memcpy(ia->mob_alloc, lchan->ts->hopping.ma_data, ia->mob_alloc_len);
Harald Weltea39b0f22010-06-14 22:26:10 +02001571 }
Harald Weltea1d39a22010-06-28 18:41:27 +02001572 /* we need to subtract 1 byte from sizeof(*ia) since ia includes the l2_plen field */
1573 ia->l2_plen = GSM48_LEN2PLEN((sizeof(*ia)-1) + ia->mob_alloc_len);
Harald Welte52b1f982008-12-23 20:25:15 +00001574
Harald Welteb7e81162009-08-10 00:26:10 +02001575 /* Start timer T3101 to wait for GSM48_MT_RR_PAG_RESP */
1576 lchan->T3101.cb = t3101_expired;
1577 lchan->T3101.data = lchan;
Pablo Neira Ayusobf540cb2011-05-06 12:11:06 +02001578 osmo_timer_schedule(&lchan->T3101, bts->network->T3101, 0);
Holger Freyther3186bf22008-12-29 06:23:49 +00001579
Harald Welte52b1f982008-12-23 20:25:15 +00001580 /* send IMMEDIATE ASSIGN CMD on RSL to BTS (to send on CCCH to MS) */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001581 return rsl_imm_assign_cmd(bts, sizeof(*ia)+ia->mob_alloc_len, (uint8_t *) ia);
Harald Welte52b1f982008-12-23 20:25:15 +00001582}
1583
Holger Hans Peter Freyther54fa2c72012-02-03 20:26:25 +01001584/* current load on the CCCH */
Harald Welteea280442009-02-02 22:29:56 +00001585static int rsl_rx_ccch_load(struct msgb *msg)
1586{
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001587 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welteea280442009-02-02 22:29:56 +00001588 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
Holger Hans Peter Freyther54fa2c72012-02-03 20:26:25 +01001589 struct ccch_signal_data sd;
1590
1591 sd.bts = sign_link->trx->bts;
1592 sd.rach_slot_count = -1;
1593 sd.rach_busy_count = -1;
1594 sd.rach_access_count = -1;
Harald Welteea280442009-02-02 22:29:56 +00001595
1596 switch (rslh->data[0]) {
1597 case RSL_IE_PAGING_LOAD:
Holger Hans Peter Freyther54fa2c72012-02-03 20:26:25 +01001598 sd.pg_buf_space = rslh->data[1] << 8 | rslh->data[2];
1599 if (is_ipaccess_bts(sign_link->trx->bts) && sd.pg_buf_space == 0xffff) {
Harald Welte38e9c822010-04-19 10:24:07 +02001600 /* paging load below configured threshold, use 50 as default */
Holger Hans Peter Freyther54fa2c72012-02-03 20:26:25 +01001601 sd.pg_buf_space = 50;
Harald Welte38e9c822010-04-19 10:24:07 +02001602 }
Holger Hans Peter Freyther54fa2c72012-02-03 20:26:25 +01001603 paging_update_buffer_space(sign_link->trx->bts, sd.pg_buf_space);
1604 osmo_signal_dispatch(SS_CCCH, S_CCCH_PAGING_LOAD, &sd);
Harald Welteea280442009-02-02 22:29:56 +00001605 break;
1606 case RSL_IE_RACH_LOAD:
Holger Freyther8c563cf2009-02-03 20:08:51 +00001607 if (msg->data_len >= 7) {
Holger Hans Peter Freyther54fa2c72012-02-03 20:26:25 +01001608 sd.rach_slot_count = rslh->data[2] << 8 | rslh->data[3];
1609 sd.rach_busy_count = rslh->data[4] << 8 | rslh->data[5];
1610 sd.rach_access_count = rslh->data[6] << 8 | rslh->data[7];
1611 osmo_signal_dispatch(SS_CCCH, S_CCCH_RACH_LOAD, &sd);
Holger Freyther8c563cf2009-02-03 20:08:51 +00001612 }
Harald Welteea280442009-02-02 22:29:56 +00001613 break;
1614 default:
1615 break;
1616 }
1617
1618 return 0;
1619}
1620
Harald Welte52b1f982008-12-23 20:25:15 +00001621static int abis_rsl_rx_cchan(struct msgb *msg)
1622{
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001623 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welteea280442009-02-02 22:29:56 +00001624 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001625 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001626
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001627 msg->lchan = lchan_lookup(sign_link->trx, rslh->chan_nr);
Harald Welte8470bf22008-12-25 23:28:35 +00001628
1629 switch (rslh->c.msg_type) {
Harald Welte52b1f982008-12-23 20:25:15 +00001630 case RSL_MT_CHAN_RQD:
1631 /* MS has requested a channel on the RACH */
1632 rc = rsl_rx_chan_rqd(msg);
1633 break;
Harald Welteea280442009-02-02 22:29:56 +00001634 case RSL_MT_CCCH_LOAD_IND:
1635 /* current load on the CCCH */
1636 rc = rsl_rx_ccch_load(msg);
1637 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001638 case RSL_MT_DELETE_IND:
1639 /* CCCH overloaded, IMM_ASSIGN was dropped */
1640 case RSL_MT_CBCH_LOAD_IND:
1641 /* current load on the CBCH */
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001642 LOGP(DRSL, LOGL_NOTICE, "Unimplemented Abis RSL TRX message "
1643 "type 0x%02x\n", rslh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001644 break;
1645 default:
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001646 LOGP(DRSL, LOGL_NOTICE, "Unknown Abis RSL TRX message type "
1647 "0x%02x\n", rslh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001648 return -EINVAL;
1649 }
Harald Welte8470bf22008-12-25 23:28:35 +00001650
1651 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001652}
1653
Harald Welte4b634542008-12-27 01:55:51 +00001654static int rsl_rx_rll_err_ind(struct msgb *msg)
1655{
Holger Hans Peter Freyther164ee302013-01-16 21:07:43 +01001656 struct tlv_parsed tp;
Harald Welte4b634542008-12-27 01:55:51 +00001657 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
Holger Hans Peter Freyther164ee302013-01-16 21:07:43 +01001658 uint8_t rlm_cause;
Harald Welte4b634542008-12-27 01:55:51 +00001659
Holger Hans Peter Freyther164ee302013-01-16 21:07:43 +01001660 rsl_tlv_parse(&tp, rllh->data, msgb_l2len(msg) - sizeof(*rllh));
1661 if (!TLVP_PRESENT(&tp, RSL_IE_RLM_CAUSE)) {
1662 LOGP(DRLL, LOGL_ERROR,
1663 "%s ERROR INDICATION without mandantory cause.\n",
1664 gsm_lchan_name(msg->lchan));
1665 return -1;
1666 }
1667
1668 rlm_cause = *TLVP_VAL(&tp, RSL_IE_RLM_CAUSE);
Holger Hans Peter Freyther1e93b792014-04-19 16:45:36 +02001669 LOGP(DRLL, LOGL_ERROR, "%s ERROR INDICATION cause=%s in state=%s\n",
Harald Welte (local)19ef62a2009-12-27 18:16:36 +01001670 gsm_lchan_name(msg->lchan),
Holger Hans Peter Freyther1e93b792014-04-19 16:45:36 +02001671 rsl_rlm_cause_name(rlm_cause),
1672 gsm_lchans_name(msg->lchan->state));
1673
Harald Welteedcc5272009-08-09 13:47:35 +02001674 rll_indication(msg->lchan, rllh->link_id, BSC_RLLR_IND_ERR_IND);
Harald Welte (local)9538efc2009-12-26 23:55:00 +01001675
Holger Hans Peter Freyther164ee302013-01-16 21:07:43 +01001676 if (rlm_cause == RLL_CAUSE_T200_EXPIRED) {
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +02001677 osmo_counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rll_err);
Holger Hans Peter Freyther0e4e73a2014-04-19 17:38:33 +02001678 return rsl_rf_chan_release_err(msg->lchan);
Holger Hans Peter Freyther3ba36d52010-04-17 06:48:29 +02001679 }
Harald Welte81543bc2009-07-04 09:40:05 +02001680
Harald Welte4b634542008-12-27 01:55:51 +00001681 return 0;
1682}
Harald Weltef325eb42009-02-19 17:07:39 +00001683
Holger Hans Peter Freytherdbc5fae2010-04-08 22:39:34 +02001684static void rsl_handle_release(struct gsm_lchan *lchan)
1685{
Holger Hans Peter Freyther4b85a322010-07-29 17:09:36 +08001686 int sapi;
Holger Hans Peter Freytherf30c0dc2010-05-31 21:33:15 +08001687 struct gsm_bts *bts;
Holger Hans Peter Freyther4b85a322010-07-29 17:09:36 +08001688
Holger Hans Peter Freyther9d50a272011-12-28 12:11:40 +01001689 /*
1690 * Maybe only one link/SAPI was releasd or the error handling
1691 * was activated. Just return now and let the other code handle
1692 * it.
1693 */
Holger Hans Peter Freytherd7fd3062010-04-08 22:47:44 +02001694 if (lchan->state != LCHAN_S_REL_REQ)
Holger Hans Peter Freyther4b85a322010-07-29 17:09:36 +08001695 return;
1696
1697 for (sapi = 0; sapi < ARRAY_SIZE(lchan->sapis); ++sapi) {
1698 if (lchan->sapis[sapi] == LCHAN_SAPI_UNUSED)
1699 continue;
Harald Welte3a3c2772010-12-24 12:51:07 +01001700 LOGP(DRSL, LOGL_DEBUG, "%s waiting for SAPI=%d to be released.\n",
Holger Hans Peter Freyther4b85a322010-07-29 17:09:36 +08001701 gsm_lchan_name(lchan), sapi);
1702 return;
1703 }
1704
Holger Hans Peter Freytherd7fd3062010-04-08 22:47:44 +02001705
Holger Hans Peter Freytherb3489392011-12-28 16:21:05 +01001706 /* Stop T3109 and wait for T3111 before re-using the channel */
1707 osmo_timer_del(&lchan->T3109);
Holger Hans Peter Freytherf30c0dc2010-05-31 21:33:15 +08001708 lchan->T3111.cb = t3111_expired;
1709 lchan->T3111.data = lchan;
1710 bts = lchan->ts->trx->bts;
Pablo Neira Ayusobf540cb2011-05-06 12:11:06 +02001711 osmo_timer_schedule(&lchan->T3111, bts->network->T3111, 0);
Holger Hans Peter Freytherdbc5fae2010-04-08 22:39:34 +02001712}
1713
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +02001714/* ESTABLISH INDICATION, LOCATION AREA UPDATE REQUEST
Harald Welte52b1f982008-12-23 20:25:15 +00001715 0x02, 0x06,
1716 0x01, 0x20,
1717 0x02, 0x00,
1718 0x0b, 0x00, 0x0f, 0x05, 0x08, ... */
1719
1720static int abis_rsl_rx_rll(struct msgb *msg)
1721{
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001722 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte52b1f982008-12-23 20:25:15 +00001723 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
Harald Weltef325eb42009-02-19 17:07:39 +00001724 int rc = 0;
1725 char *ts_name;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001726 uint8_t sapi = rllh->link_id & 7;
Harald Welte8470bf22008-12-25 23:28:35 +00001727
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001728 msg->lchan = lchan_lookup(sign_link->trx, rllh->chan_nr);
Harald Welte (local)19ef62a2009-12-27 18:16:36 +01001729 ts_name = gsm_lchan_name(msg->lchan);
Harald Welte5b8ed432009-12-24 12:20:20 +01001730 DEBUGP(DRLL, "%s SAPI=%u ", ts_name, sapi);
Harald Welte52b1f982008-12-23 20:25:15 +00001731
1732 switch (rllh->c.msg_type) {
1733 case RSL_MT_DATA_IND:
Harald Weltef325eb42009-02-19 17:07:39 +00001734 DEBUGPC(DRLL, "DATA INDICATION\n");
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +02001735 if (msgb_l2len(msg) >
Harald Welte4a543e82009-02-28 13:17:55 +00001736 sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) &&
1737 rllh->data[0] == RSL_IE_L3_INFO) {
1738 msg->l3h = &rllh->data[3];
Harald Welte (local)daef6062009-08-14 11:41:12 +02001739 return gsm0408_rcvmsg(msg, rllh->link_id);
Harald Welte4a543e82009-02-28 13:17:55 +00001740 }
Harald Welte52b1f982008-12-23 20:25:15 +00001741 break;
1742 case RSL_MT_EST_IND:
Harald Weltef325eb42009-02-19 17:07:39 +00001743 DEBUGPC(DRLL, "ESTABLISH INDICATION\n");
Harald Welteb7e81162009-08-10 00:26:10 +02001744 /* lchan is established, stop T3101 */
Holger Hans Peter Freyther5ba6f482009-10-28 14:23:39 +01001745 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_MS;
Pablo Neira Ayusobf540cb2011-05-06 12:11:06 +02001746 osmo_timer_del(&msg->lchan->T3101);
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +02001747 if (msgb_l2len(msg) >
Harald Welte4a543e82009-02-28 13:17:55 +00001748 sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) &&
1749 rllh->data[0] == RSL_IE_L3_INFO) {
1750 msg->l3h = &rllh->data[3];
Harald Welte (local)daef6062009-08-14 11:41:12 +02001751 return gsm0408_rcvmsg(msg, rllh->link_id);
Harald Welte4a543e82009-02-28 13:17:55 +00001752 }
Harald Welte52b1f982008-12-23 20:25:15 +00001753 break;
Harald Welteedcc5272009-08-09 13:47:35 +02001754 case RSL_MT_EST_CONF:
Harald Welte1c409272009-08-09 14:13:58 +02001755 DEBUGPC(DRLL, "ESTABLISH CONFIRM\n");
Holger Hans Peter Freyther5ba6f482009-10-28 14:23:39 +01001756 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_NET;
Harald Welteedcc5272009-08-09 13:47:35 +02001757 rll_indication(msg->lchan, rllh->link_id,
1758 BSC_RLLR_IND_EST_CONF);
1759 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001760 case RSL_MT_REL_IND:
Harald Welted2dc1de2009-08-08 13:15:07 +02001761 /* BTS informs us of having received DISC from MS */
Harald Welte602f2b82009-08-04 02:50:21 +02001762 DEBUGPC(DRLL, "RELEASE INDICATION\n");
Holger Hans Peter Freyther5ba6f482009-10-28 14:23:39 +01001763 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_UNUSED;
Harald Welteedcc5272009-08-09 13:47:35 +02001764 rll_indication(msg->lchan, rllh->link_id,
1765 BSC_RLLR_IND_REL_IND);
Holger Hans Peter Freytherdbc5fae2010-04-08 22:39:34 +02001766 rsl_handle_release(msg->lchan);
Harald Welte2d5b6382008-12-27 19:46:06 +00001767 break;
1768 case RSL_MT_REL_CONF:
Harald Welted2dc1de2009-08-08 13:15:07 +02001769 /* BTS informs us of having received UA from MS,
1770 * in response to DISC that we've sent earlier */
Harald Welte602f2b82009-08-04 02:50:21 +02001771 DEBUGPC(DRLL, "RELEASE CONFIRMATION\n");
Holger Hans Peter Freyther5ba6f482009-10-28 14:23:39 +01001772 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_UNUSED;
Holger Hans Peter Freytherdbc5fae2010-04-08 22:39:34 +02001773 rsl_handle_release(msg->lchan);
Harald Welte4b634542008-12-27 01:55:51 +00001774 break;
1775 case RSL_MT_ERROR_IND:
Neels Hofmeyre3dc4982016-07-26 19:39:43 +02001776 DEBUGPC(DRLL, "ERROR INDICATION\n");
Harald Welte4b634542008-12-27 01:55:51 +00001777 rc = rsl_rx_rll_err_ind(msg);
1778 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001779 case RSL_MT_UNIT_DATA_IND:
Neels Hofmeyre3dc4982016-07-26 19:39:43 +02001780 DEBUGPC(DRLL, "UNIT DATA INDICATION\n");
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001781 LOGP(DRLL, LOGL_NOTICE, "unimplemented Abis RLL message "
1782 "type 0x%02x\n", rllh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001783 break;
1784 default:
Neels Hofmeyre3dc4982016-07-26 19:39:43 +02001785 DEBUGPC(DRLL, "UNKNOWN\n");
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001786 LOGP(DRLL, LOGL_NOTICE, "unknown Abis RLL message "
1787 "type 0x%02x\n", rllh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001788 }
Harald Welte8470bf22008-12-25 23:28:35 +00001789 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001790}
1791
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001792static uint8_t ipa_smod_s_for_lchan(struct gsm_lchan *lchan)
Harald Weltef4e79f22009-07-28 18:11:56 +02001793{
Harald Welte0603c9d2009-12-02 01:58:23 +05301794 switch (lchan->tch_mode) {
Harald Weltef4e79f22009-07-28 18:11:56 +02001795 case GSM48_CMODE_SPEECH_V1:
Harald Welte0603c9d2009-12-02 01:58:23 +05301796 switch (lchan->type) {
1797 case GSM_LCHAN_TCH_F:
1798 return 0x00;
1799 case GSM_LCHAN_TCH_H:
1800 return 0x03;
1801 default:
1802 break;
1803 }
Holger Hans Peter Freyther47665242014-04-04 12:14:55 +02001804 break;
Harald Weltef4e79f22009-07-28 18:11:56 +02001805 case GSM48_CMODE_SPEECH_EFR:
Harald Welte0603c9d2009-12-02 01:58:23 +05301806 switch (lchan->type) {
1807 case GSM_LCHAN_TCH_F:
1808 return 0x01;
1809 /* there's no half-rate EFR */
1810 default:
1811 break;
1812 }
Holger Hans Peter Freyther47665242014-04-04 12:14:55 +02001813 break;
Harald Weltef4e79f22009-07-28 18:11:56 +02001814 case GSM48_CMODE_SPEECH_AMR:
Harald Welte0603c9d2009-12-02 01:58:23 +05301815 switch (lchan->type) {
1816 case GSM_LCHAN_TCH_F:
1817 return 0x02;
1818 case GSM_LCHAN_TCH_H:
1819 return 0x05;
1820 default:
1821 break;
1822 }
Holger Hans Peter Freyther47665242014-04-04 12:14:55 +02001823 break;
Harald Welte0603c9d2009-12-02 01:58:23 +05301824 default:
1825 break;
Harald Weltef4e79f22009-07-28 18:11:56 +02001826 }
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001827 LOGP(DRSL, LOGL_ERROR, "Cannot determine ip.access speech mode for "
Harald Welte0603c9d2009-12-02 01:58:23 +05301828 "tch_mode == 0x%02x\n", lchan->tch_mode);
Harald Weltef4e79f22009-07-28 18:11:56 +02001829 return 0;
Harald Weltef4e79f22009-07-28 18:11:56 +02001830}
1831
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001832static uint8_t ipa_rtp_pt_for_lchan(struct gsm_lchan *lchan)
Sylvain Munautb54dda42009-12-20 22:06:40 +01001833{
1834 switch (lchan->tch_mode) {
1835 case GSM48_CMODE_SPEECH_V1:
1836 switch (lchan->type) {
1837 case GSM_LCHAN_TCH_F:
1838 return RTP_PT_GSM_FULL;
1839 case GSM_LCHAN_TCH_H:
1840 return RTP_PT_GSM_HALF;
1841 default:
1842 break;
1843 }
Holger Hans Peter Freyther47665242014-04-04 12:14:55 +02001844 break;
Sylvain Munautb54dda42009-12-20 22:06:40 +01001845 case GSM48_CMODE_SPEECH_EFR:
1846 switch (lchan->type) {
1847 case GSM_LCHAN_TCH_F:
1848 return RTP_PT_GSM_EFR;
1849 /* there's no half-rate EFR */
1850 default:
1851 break;
1852 }
Holger Hans Peter Freyther47665242014-04-04 12:14:55 +02001853 break;
Sylvain Munautb54dda42009-12-20 22:06:40 +01001854 case GSM48_CMODE_SPEECH_AMR:
1855 switch (lchan->type) {
1856 case GSM_LCHAN_TCH_F:
Sylvain Munautb54dda42009-12-20 22:06:40 +01001857 case GSM_LCHAN_TCH_H:
Holger Hans Peter Freythered999b22011-07-21 10:24:46 +02001858 return RTP_PT_AMR;
Sylvain Munautb54dda42009-12-20 22:06:40 +01001859 default:
1860 break;
1861 }
Holger Hans Peter Freyther47665242014-04-04 12:14:55 +02001862 break;
Sylvain Munautb54dda42009-12-20 22:06:40 +01001863 default:
1864 break;
1865 }
1866 LOGP(DRSL, LOGL_ERROR, "Cannot determine ip.access rtp payload type for "
1867 "tch_mode == 0x%02x\n & lchan_type == %d",
1868 lchan->tch_mode, lchan->type);
1869 return 0;
1870}
1871
Harald Welte75099262009-02-16 21:12:08 +00001872/* ip.access specific RSL extensions */
Harald Welte5e3d91b2009-12-19 16:42:06 +01001873static void ipac_parse_rtp(struct gsm_lchan *lchan, struct tlv_parsed *tv)
1874{
1875 struct in_addr ip;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001876 uint16_t port, conn_id;
Harald Welte5e3d91b2009-12-19 16:42:06 +01001877
1878 if (TLVP_PRESENT(tv, RSL_IE_IPAC_LOCAL_IP)) {
Daniel Willmann8a485f02014-06-27 17:05:47 +02001879 ip.s_addr = tlvp_val32_unal(tv, RSL_IE_IPAC_LOCAL_IP);
Harald Welte5e3d91b2009-12-19 16:42:06 +01001880 DEBUGPC(DRSL, "LOCAL_IP=%s ", inet_ntoa(ip));
1881 lchan->abis_ip.bound_ip = ntohl(ip.s_addr);
1882 }
1883
1884 if (TLVP_PRESENT(tv, RSL_IE_IPAC_LOCAL_PORT)) {
Daniel Willmann8a485f02014-06-27 17:05:47 +02001885 port = tlvp_val16_unal(tv, RSL_IE_IPAC_LOCAL_PORT);
Harald Welte5e3d91b2009-12-19 16:42:06 +01001886 port = ntohs(port);
1887 DEBUGPC(DRSL, "LOCAL_PORT=%u ", port);
1888 lchan->abis_ip.bound_port = port;
1889 }
1890
1891 if (TLVP_PRESENT(tv, RSL_IE_IPAC_CONN_ID)) {
Daniel Willmann8a485f02014-06-27 17:05:47 +02001892 conn_id = tlvp_val16_unal(tv, RSL_IE_IPAC_CONN_ID);
Harald Welte5e3d91b2009-12-19 16:42:06 +01001893 conn_id = ntohs(conn_id);
1894 DEBUGPC(DRSL, "CON_ID=%u ", conn_id);
1895 lchan->abis_ip.conn_id = conn_id;
1896 }
1897
1898 if (TLVP_PRESENT(tv, RSL_IE_IPAC_RTP_PAYLOAD2)) {
1899 lchan->abis_ip.rtp_payload2 =
1900 *TLVP_VAL(tv, RSL_IE_IPAC_RTP_PAYLOAD2);
1901 DEBUGPC(DRSL, "RTP_PAYLOAD2=0x%02x ",
1902 lchan->abis_ip.rtp_payload2);
1903 }
1904
1905 if (TLVP_PRESENT(tv, RSL_IE_IPAC_SPEECH_MODE)) {
1906 lchan->abis_ip.speech_mode =
1907 *TLVP_VAL(tv, RSL_IE_IPAC_SPEECH_MODE);
1908 DEBUGPC(DRSL, "speech_mode=0x%02x ",
1909 lchan->abis_ip.speech_mode);
1910 }
1911
1912 if (TLVP_PRESENT(tv, RSL_IE_IPAC_REMOTE_IP)) {
Daniel Willmann8a485f02014-06-27 17:05:47 +02001913 ip.s_addr = tlvp_val32_unal(tv, RSL_IE_IPAC_REMOTE_IP);
Harald Welte5e3d91b2009-12-19 16:42:06 +01001914 DEBUGPC(DRSL, "REMOTE_IP=%s ", inet_ntoa(ip));
1915 lchan->abis_ip.connect_ip = ntohl(ip.s_addr);
1916 }
1917
1918 if (TLVP_PRESENT(tv, RSL_IE_IPAC_REMOTE_PORT)) {
Daniel Willmann8a485f02014-06-27 17:05:47 +02001919 port = tlvp_val16_unal(tv, RSL_IE_IPAC_REMOTE_PORT);
Harald Welte5e3d91b2009-12-19 16:42:06 +01001920 port = ntohs(port);
1921 DEBUGPC(DRSL, "REMOTE_PORT=%u ", port);
1922 lchan->abis_ip.connect_port = port;
1923 }
1924}
1925
Harald Welte647db842013-02-03 12:06:58 +01001926/*! \brief Issue IPA RSL CRCX to configure RTP on BTS side
1927 * \param[in] lchan Logical Channel for which we issue CRCX
1928 */
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001929int rsl_ipacc_crcx(struct gsm_lchan *lchan)
Harald Welte75099262009-02-16 21:12:08 +00001930{
1931 struct msgb *msg = rsl_msgb_alloc();
1932 struct abis_rsl_dchan_hdr *dh;
1933
1934 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001935 init_dchan_hdr(dh, RSL_MT_IPAC_CRCX);
Harald Welte75099262009-02-16 21:12:08 +00001936 dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
Harald Weltef6093a42011-06-25 10:02:33 +02001937 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte75099262009-02-16 21:12:08 +00001938
Harald Weltef4e79f22009-07-28 18:11:56 +02001939 /* 0x1- == receive-only, 0x-1 == EFR codec */
Harald Welte5e3d91b2009-12-19 16:42:06 +01001940 lchan->abis_ip.speech_mode = 0x10 | ipa_smod_s_for_lchan(lchan);
Sylvain Munautb54dda42009-12-20 22:06:40 +01001941 lchan->abis_ip.rtp_payload = ipa_rtp_pt_for_lchan(lchan);
Harald Welte5e3d91b2009-12-19 16:42:06 +01001942 msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, lchan->abis_ip.speech_mode);
Sylvain Munautb54dda42009-12-20 22:06:40 +01001943 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD, lchan->abis_ip.rtp_payload);
Harald Weltef4e79f22009-07-28 18:11:56 +02001944
Sylvain Munautb54dda42009-12-20 22:06:40 +01001945 DEBUGP(DRSL, "%s IPAC_BIND speech_mode=0x%02x RTP_PAYLOAD=%d\n",
1946 gsm_lchan_name(lchan), lchan->abis_ip.speech_mode,
1947 lchan->abis_ip.rtp_payload);
Harald Weltef4e79f22009-07-28 18:11:56 +02001948
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001949 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte75099262009-02-16 21:12:08 +00001950
1951 return abis_rsl_sendmsg(msg);
1952}
1953
Harald Welte647db842013-02-03 12:06:58 +01001954/*! \brief Issue IPA RSL MDCX to configure MGW-side of RTP
1955 * \param[in] lchan Logical Channel for which we issue MDCX
1956 * \param[in] ip Remote (MGW) IP address for RTP
1957 * \param[in] port Remote (MGW) UDP port number for RTP
1958 * \param[in] rtp_payload2 Contents of RTP PAYLOAD 2 IE
1959 */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001960int rsl_ipacc_mdcx(struct gsm_lchan *lchan, uint32_t ip, uint16_t port,
1961 uint8_t rtp_payload2)
Harald Welte75099262009-02-16 21:12:08 +00001962{
1963 struct msgb *msg = rsl_msgb_alloc();
1964 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001965 uint32_t *att_ip;
Harald Weltef4e79f22009-07-28 18:11:56 +02001966 struct in_addr ia;
Harald Welte75099262009-02-16 21:12:08 +00001967
1968 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001969 init_dchan_hdr(dh, RSL_MT_IPAC_MDCX);
Harald Welte75099262009-02-16 21:12:08 +00001970 dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
Harald Weltef6093a42011-06-25 10:02:33 +02001971 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte75099262009-02-16 21:12:08 +00001972
Harald Welte5e3d91b2009-12-19 16:42:06 +01001973 /* we need to store these now as MDCX_ACK does not return them :( */
1974 lchan->abis_ip.rtp_payload2 = rtp_payload2;
1975 lchan->abis_ip.connect_port = port;
1976 lchan->abis_ip.connect_ip = ip;
1977
Harald Welte58ca5b72009-07-29 12:12:18 +02001978 /* 0x0- == both directions, 0x-1 == EFR codec */
Harald Welte5e3d91b2009-12-19 16:42:06 +01001979 lchan->abis_ip.speech_mode = 0x00 | ipa_smod_s_for_lchan(lchan);
Sylvain Munautb54dda42009-12-20 22:06:40 +01001980 lchan->abis_ip.rtp_payload = ipa_rtp_pt_for_lchan(lchan);
Harald Welte58ca5b72009-07-29 12:12:18 +02001981
Harald Weltef4e79f22009-07-28 18:11:56 +02001982 ia.s_addr = htonl(ip);
Sylvain Munautb54dda42009-12-20 22:06:40 +01001983 DEBUGP(DRSL, "%s IPAC_MDCX IP=%s PORT=%d RTP_PAYLOAD=%d RTP_PAYLOAD2=%d "
1984 "CONN_ID=%d speech_mode=0x%02x\n", gsm_lchan_name(lchan),
1985 inet_ntoa(ia), port, lchan->abis_ip.rtp_payload, rtp_payload2,
1986 lchan->abis_ip.conn_id, lchan->abis_ip.speech_mode);
Harald Weltef4e79f22009-07-28 18:11:56 +02001987
Harald Welte5e3d91b2009-12-19 16:42:06 +01001988 msgb_tv16_put(msg, RSL_IE_IPAC_CONN_ID, lchan->abis_ip.conn_id);
1989 msgb_v_put(msg, RSL_IE_IPAC_REMOTE_IP);
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001990 att_ip = (uint32_t *) msgb_put(msg, sizeof(ip));
Harald Welte5e3d91b2009-12-19 16:42:06 +01001991 *att_ip = ia.s_addr;
1992 msgb_tv16_put(msg, RSL_IE_IPAC_REMOTE_PORT, port);
1993 msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, lchan->abis_ip.speech_mode);
Sylvain Munautb54dda42009-12-20 22:06:40 +01001994 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD, lchan->abis_ip.rtp_payload);
Harald Weltef4e79f22009-07-28 18:11:56 +02001995 if (rtp_payload2)
1996 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD2, rtp_payload2);
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001997
1998 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte75099262009-02-16 21:12:08 +00001999
2000 return abis_rsl_sendmsg(msg);
2001}
2002
Harald Weltea72273e2009-12-20 16:51:09 +01002003/* tell BTS to connect RTP stream to our local RTP socket */
2004int rsl_ipacc_mdcx_to_rtpsock(struct gsm_lchan *lchan)
2005{
2006 struct rtp_socket *rs = lchan->abis_ip.rtp_socket;
2007 int rc;
2008
2009 rc = rsl_ipacc_mdcx(lchan, ntohl(rs->rtp.sin_local.sin_addr.s_addr),
2010 ntohs(rs->rtp.sin_local.sin_port),
2011 /* FIXME: use RTP payload of bound socket, not BTS*/
2012 lchan->abis_ip.rtp_payload2);
2013
2014 return rc;
2015}
2016
Harald Welte53cd7ac2010-12-23 12:59:52 +01002017int rsl_ipacc_pdch_activate(struct gsm_bts_trx_ts *ts, int act)
Harald Welte9c880c92009-10-24 10:29:22 +02002018{
2019 struct msgb *msg = rsl_msgb_alloc();
2020 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02002021 uint8_t msg_type;
Harald Welte4563eab2010-03-28 14:42:09 +08002022
Neels Hofmeyr32019882016-06-15 15:32:29 +02002023 if (ts->flags & TS_F_PDCH_PENDING_MASK) {
2024 LOGP(DRSL, LOGL_ERROR,
2025 "%s PDCH %s requested, but a PDCH%s%s is still pending\n",
2026 gsm_ts_name(ts),
2027 act ? "ACT" : "DEACT",
2028 ts->flags & TS_F_PDCH_ACT_PENDING? " ACT" : "",
2029 ts->flags & TS_F_PDCH_DEACT_PENDING? " DEACT" : "");
2030 return -EINVAL;
2031 }
2032
2033 if (act){
Neels Hofmeyr9ddd8e62016-07-06 14:39:04 +02002034 /* Callers should heed the GPRS mode. */
2035 OSMO_ASSERT(ts->trx->bts->gprs.mode != BTS_GPRS_NONE);
Harald Welte4563eab2010-03-28 14:42:09 +08002036 msg_type = RSL_MT_IPAC_PDCH_ACT;
Neels Hofmeyr32019882016-06-15 15:32:29 +02002037 ts->flags |= TS_F_PDCH_ACT_PENDING;
2038 } else {
Harald Welte4563eab2010-03-28 14:42:09 +08002039 msg_type = RSL_MT_IPAC_PDCH_DEACT;
Neels Hofmeyr32019882016-06-15 15:32:29 +02002040 ts->flags |= TS_F_PDCH_DEACT_PENDING;
2041 }
2042 /* TODO add timeout to cancel PDCH DE/ACT */
Harald Welte9c880c92009-10-24 10:29:22 +02002043
2044 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Harald Welte4563eab2010-03-28 14:42:09 +08002045 init_dchan_hdr(dh, msg_type);
Harald Welte9c880c92009-10-24 10:29:22 +02002046 dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
Harald Weltef6093a42011-06-25 10:02:33 +02002047 dh->chan_nr = gsm_ts2chan_nr(ts, 0);
Harald Welte9c880c92009-10-24 10:29:22 +02002048
Neels Hofmeyr9f5d2312016-05-31 17:51:41 +02002049 DEBUGP(DRSL, "%s IPAC PDCH %sACT\n", gsm_ts_name(ts),
Harald Welte4563eab2010-03-28 14:42:09 +08002050 act ? "" : "DE");
Harald Welte9c880c92009-10-24 10:29:22 +02002051
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02002052 msg->dst = ts->trx->rsl_link;
Harald Welte9c880c92009-10-24 10:29:22 +02002053
2054 return abis_rsl_sendmsg(msg);
2055}
2056
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01002057static int abis_rsl_rx_ipacc_crcx_ack(struct msgb *msg)
Harald Welte75099262009-02-16 21:12:08 +00002058{
2059 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
2060 struct tlv_parsed tv;
Harald Welte2c828992009-12-02 01:56:49 +05302061 struct gsm_lchan *lchan = msg->lchan;
Harald Welte75099262009-02-16 21:12:08 +00002062
2063 /* the BTS has acknowledged a local bind, it now tells us the IP
2064 * address and port number to which it has bound the given logical
2065 * channel */
2066
2067 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
2068 if (!TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_PORT) ||
2069 !TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_IP) ||
Harald Welte86c162d2009-07-12 09:45:05 +02002070 !TLVP_PRESENT(&tv, RSL_IE_IPAC_CONN_ID)) {
Harald Welteb1d4c8e2009-12-17 23:10:46 +01002071 LOGP(DRSL, LOGL_NOTICE, "mandatory IE missing");
Harald Welte75099262009-02-16 21:12:08 +00002072 return -EINVAL;
2073 }
Harald Welte17f5bf62009-12-20 15:42:44 +01002074
Harald Welte5e3d91b2009-12-19 16:42:06 +01002075 ipac_parse_rtp(lchan, &tv);
Harald Welte17f5bf62009-12-20 15:42:44 +01002076
Pablo Neira Ayusobbc5b992011-05-06 12:12:31 +02002077 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_CRCX_ACK, msg->lchan);
Harald Welte167df882009-02-17 14:35:45 +00002078
Harald Welte75099262009-02-16 21:12:08 +00002079 return 0;
2080}
2081
Harald Welte5e3d91b2009-12-19 16:42:06 +01002082static int abis_rsl_rx_ipacc_mdcx_ack(struct msgb *msg)
2083{
2084 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
2085 struct tlv_parsed tv;
2086 struct gsm_lchan *lchan = msg->lchan;
2087
2088 /* the BTS has acknowledged a remote connect request and
2089 * it now tells us the IP address and port number to which it has
2090 * connected the given logical channel */
2091
2092 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
2093 ipac_parse_rtp(lchan, &tv);
Pablo Neira Ayusobbc5b992011-05-06 12:12:31 +02002094 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_MDCX_ACK, msg->lchan);
Harald Welte5e3d91b2009-12-19 16:42:06 +01002095
2096 return 0;
2097}
2098
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01002099static int abis_rsl_rx_ipacc_dlcx_ind(struct msgb *msg)
Harald Welte75099262009-02-16 21:12:08 +00002100{
2101 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
2102 struct tlv_parsed tv;
2103
2104 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
Harald Welte75099262009-02-16 21:12:08 +00002105
Harald Welte8830e072009-07-28 17:58:09 +02002106 if (TLVP_PRESENT(&tv, RSL_IE_CAUSE))
Harald Welte5b8ed432009-12-24 12:20:20 +01002107 print_rsl_cause(LOGL_DEBUG, TLVP_VAL(&tv, RSL_IE_CAUSE),
Harald Welte8830e072009-07-28 17:58:09 +02002108 TLVP_LEN(&tv, RSL_IE_CAUSE));
Harald Welte75099262009-02-16 21:12:08 +00002109
Pablo Neira Ayusobbc5b992011-05-06 12:12:31 +02002110 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_DLCX_IND, msg->lchan);
Harald Welte888b1142009-07-28 18:02:05 +02002111
Harald Welte75099262009-02-16 21:12:08 +00002112 return 0;
2113}
2114
2115static int abis_rsl_rx_ipacc(struct msgb *msg)
2116{
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02002117 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte75099262009-02-16 21:12:08 +00002118 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
Harald Welte5b8ed432009-12-24 12:20:20 +01002119 char *ts_name;
Harald Welte75099262009-02-16 21:12:08 +00002120 int rc = 0;
2121
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02002122 msg->lchan = lchan_lookup(sign_link->trx, rllh->chan_nr);
Harald Welte (local)19ef62a2009-12-27 18:16:36 +01002123 ts_name = gsm_lchan_name(msg->lchan);
Harald Welte75099262009-02-16 21:12:08 +00002124
2125 switch (rllh->c.msg_type) {
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01002126 case RSL_MT_IPAC_CRCX_ACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01002127 DEBUGP(DRSL, "%s IPAC_CRCX_ACK ", ts_name);
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01002128 rc = abis_rsl_rx_ipacc_crcx_ack(msg);
Harald Welte75099262009-02-16 21:12:08 +00002129 break;
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01002130 case RSL_MT_IPAC_CRCX_NACK:
Harald Welte75099262009-02-16 21:12:08 +00002131 /* somehow the BTS was unable to bind the lchan to its local
2132 * port?!? */
Harald Welte5b8ed432009-12-24 12:20:20 +01002133 LOGP(DRSL, LOGL_ERROR, "%s IPAC_CRCX_NACK\n", ts_name);
Harald Welte75099262009-02-16 21:12:08 +00002134 break;
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01002135 case RSL_MT_IPAC_MDCX_ACK:
Harald Welte75099262009-02-16 21:12:08 +00002136 /* the BTS tells us that a connect operation was successful */
Harald Welte5b8ed432009-12-24 12:20:20 +01002137 DEBUGP(DRSL, "%s IPAC_MDCX_ACK ", ts_name);
Harald Welte5e3d91b2009-12-19 16:42:06 +01002138 rc = abis_rsl_rx_ipacc_mdcx_ack(msg);
Harald Welte75099262009-02-16 21:12:08 +00002139 break;
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01002140 case RSL_MT_IPAC_MDCX_NACK:
Harald Welte75099262009-02-16 21:12:08 +00002141 /* somehow the BTS was unable to connect the lchan to a remote
2142 * port */
Harald Welte5b8ed432009-12-24 12:20:20 +01002143 LOGP(DRSL, LOGL_ERROR, "%s IPAC_MDCX_NACK\n", ts_name);
Harald Welte75099262009-02-16 21:12:08 +00002144 break;
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01002145 case RSL_MT_IPAC_DLCX_IND:
Harald Welte5b8ed432009-12-24 12:20:20 +01002146 DEBUGP(DRSL, "%s IPAC_DLCX_IND ", ts_name);
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01002147 rc = abis_rsl_rx_ipacc_dlcx_ind(msg);
Harald Welte75099262009-02-16 21:12:08 +00002148 break;
2149 default:
Harald Welte5b8ed432009-12-24 12:20:20 +01002150 LOGP(DRSL, LOGL_NOTICE, "Unknown ip.access msg_type 0x%02x\n",
Harald Welteb1d4c8e2009-12-17 23:10:46 +01002151 rllh->c.msg_type);
Harald Welte75099262009-02-16 21:12:08 +00002152 break;
2153 }
Harald Welte6dab0552009-05-01 17:21:37 +00002154 DEBUGPC(DRSL, "\n");
Harald Welte75099262009-02-16 21:12:08 +00002155
2156 return rc;
2157}
2158
2159
Harald Welte52b1f982008-12-23 20:25:15 +00002160/* Entry-point where L2 RSL from BTS enters */
Harald Welte8470bf22008-12-25 23:28:35 +00002161int abis_rsl_rcvmsg(struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +00002162{
Holger Hans Peter Freyther19bab732009-11-20 15:14:01 +01002163 struct abis_rsl_common_hdr *rslh;
Harald Welte8f5e2392009-02-03 12:57:37 +00002164 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00002165
Holger Hans Peter Freyther19bab732009-11-20 15:14:01 +01002166 if (!msg) {
2167 DEBUGP(DRSL, "Empty RSL msg?..\n");
2168 return -1;
2169 }
2170
2171 if (msgb_l2len(msg) < sizeof(*rslh)) {
2172 DEBUGP(DRSL, "Truncated RSL message with l2len: %u\n", msgb_l2len(msg));
Harald Weltef25b55e2012-05-31 20:22:34 +02002173 msgb_free(msg);
Holger Hans Peter Freyther19bab732009-11-20 15:14:01 +01002174 return -1;
2175 }
2176
2177 rslh = msgb_l2(msg);
2178
Harald Welte52b1f982008-12-23 20:25:15 +00002179 switch (rslh->msg_discr & 0xfe) {
2180 case ABIS_RSL_MDISC_RLL:
2181 rc = abis_rsl_rx_rll(msg);
2182 break;
2183 case ABIS_RSL_MDISC_DED_CHAN:
2184 rc = abis_rsl_rx_dchan(msg);
2185 break;
2186 case ABIS_RSL_MDISC_COM_CHAN:
Harald Welte52b1f982008-12-23 20:25:15 +00002187 rc = abis_rsl_rx_cchan(msg);
2188 break;
Harald Welte8470bf22008-12-25 23:28:35 +00002189 case ABIS_RSL_MDISC_TRX:
2190 rc = abis_rsl_rx_trx(msg);
2191 break;
Harald Welte52b1f982008-12-23 20:25:15 +00002192 case ABIS_RSL_MDISC_LOC:
Harald Welteb1d4c8e2009-12-17 23:10:46 +01002193 LOGP(DRSL, LOGL_NOTICE, "unimplemented RSL msg disc 0x%02x\n",
Harald Welte8f5e2392009-02-03 12:57:37 +00002194 rslh->msg_discr);
2195 break;
Harald Welte75099262009-02-16 21:12:08 +00002196 case ABIS_RSL_MDISC_IPACCESS:
2197 rc = abis_rsl_rx_ipacc(msg);
2198 break;
Harald Welte52b1f982008-12-23 20:25:15 +00002199 default:
Harald Welteb1d4c8e2009-12-17 23:10:46 +01002200 LOGP(DRSL, LOGL_NOTICE, "unknown RSL message discriminator "
2201 "0x%02x\n", rslh->msg_discr);
Harald Weltef25b55e2012-05-31 20:22:34 +02002202 rc = -EINVAL;
Harald Welte52b1f982008-12-23 20:25:15 +00002203 }
Harald Welte4f4a3902008-12-26 00:04:49 +00002204 msgb_free(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00002205 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00002206}
Holger Freyther3b72a892009-02-04 00:31:39 +00002207
Holger Hans Peter Freyther8cb4a0f2010-07-21 15:54:32 +08002208int rsl_sms_cb_command(struct gsm_bts *bts, uint8_t chan_number,
Harald Welte30f1f372014-12-28 15:00:45 +01002209 struct rsl_ie_cb_cmd_type cb_command,
2210 const uint8_t *data, int len)
Holger Hans Peter Freyther8cb4a0f2010-07-21 15:54:32 +08002211{
2212 struct abis_rsl_dchan_hdr *dh;
2213 struct msgb *cb_cmd;
2214
2215 cb_cmd = rsl_msgb_alloc();
2216 if (!cb_cmd)
2217 return -1;
2218
Harald Welte30f1f372014-12-28 15:00:45 +01002219 dh = (struct abis_rsl_dchan_hdr *) msgb_put(cb_cmd, sizeof(*dh));
Holger Hans Peter Freyther8cb4a0f2010-07-21 15:54:32 +08002220 init_dchan_hdr(dh, RSL_MT_SMS_BC_CMD);
Harald Welte30f1f372014-12-28 15:00:45 +01002221 dh->c.msg_discr = ABIS_RSL_MDISC_COM_CHAN;
2222 dh->chan_nr = chan_number; /* TODO: check the chan config */
Holger Hans Peter Freyther8cb4a0f2010-07-21 15:54:32 +08002223
Harald Welte30f1f372014-12-28 15:00:45 +01002224 msgb_tv_put(cb_cmd, RSL_IE_CB_CMD_TYPE, *(uint8_t*)&cb_command);
Holger Hans Peter Freyther8cb4a0f2010-07-21 15:54:32 +08002225 msgb_tlv_put(cb_cmd, RSL_IE_SMSCB_MSG, len, data);
2226
Harald Welte30f1f372014-12-28 15:00:45 +01002227 cb_cmd->dst = bts->c0->rsl_link;
Holger Hans Peter Freyther8cb4a0f2010-07-21 15:54:32 +08002228
2229 return abis_rsl_sendmsg(cb_cmd);
2230}
Dieter Spaar16646022011-07-28 00:01:50 +02002231
2232int rsl_nokia_si_begin(struct gsm_bts_trx *trx)
2233{
2234 struct abis_rsl_common_hdr *ch;
2235 struct msgb *msg = rsl_msgb_alloc();
2236
2237 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
2238 ch->msg_discr = ABIS_RSL_MDISC_TRX;
2239 ch->msg_type = 0x40; /* Nokia SI Begin */
2240
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02002241 msg->dst = trx->rsl_link;
Dieter Spaar16646022011-07-28 00:01:50 +02002242
2243 return abis_rsl_sendmsg(msg);
2244}
2245
2246int rsl_nokia_si_end(struct gsm_bts_trx *trx)
2247{
2248 struct abis_rsl_common_hdr *ch;
2249 struct msgb *msg = rsl_msgb_alloc();
2250
2251 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
2252 ch->msg_discr = ABIS_RSL_MDISC_TRX;
2253 ch->msg_type = 0x41; /* Nokia SI End */
2254
2255 msgb_tv_put(msg, 0xFD, 0x00); /* Nokia Pagemode Info, No paging reorganisation required */
2256
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02002257 msg->dst = trx->rsl_link;
Dieter Spaar16646022011-07-28 00:01:50 +02002258
2259 return abis_rsl_sendmsg(msg);
2260}
2261
2262int rsl_bs_power_control(struct gsm_bts_trx *trx, uint8_t channel, uint8_t reduction)
2263{
2264 struct abis_rsl_common_hdr *ch;
2265 struct msgb *msg = rsl_msgb_alloc();
2266
2267 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
2268 ch->msg_discr = ABIS_RSL_MDISC_DED_CHAN;
2269 ch->msg_type = RSL_MT_BS_POWER_CONTROL;
2270
2271 msgb_tv_put(msg, RSL_IE_CHAN_NR, channel);
2272 msgb_tv_put(msg, RSL_IE_BS_POWER, reduction); /* reduction in 2dB steps */
2273
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02002274 msg->dst = trx->rsl_link;
Dieter Spaar16646022011-07-28 00:01:50 +02002275
2276 return abis_rsl_sendmsg(msg);
2277}
Holger Hans Peter Freyther85825352011-12-27 22:24:17 +01002278
2279/**
2280 * Release all allocated SAPIs starting from @param start and
2281 * release them with the given release mode. Once the release
2282 * confirmation arrives it will be attempted to release the
2283 * the RF channel.
2284 */
2285int rsl_release_sapis_from(struct gsm_lchan *lchan, int start,
2286 enum rsl_rel_mode release_mode)
2287{
2288 int no_sapi = 1;
2289 int sapi;
2290
2291 for (sapi = start; sapi < ARRAY_SIZE(lchan->sapis); ++sapi) {
2292 uint8_t link_id;
2293 if (lchan->sapis[sapi] == LCHAN_SAPI_UNUSED)
2294 continue;
2295
2296 link_id = sapi;
2297 if (lchan->type == GSM_LCHAN_TCH_F || lchan->type == GSM_LCHAN_TCH_H)
2298 link_id |= 0x40;
2299 rsl_release_request(lchan, link_id, release_mode);
2300 no_sapi = 0;
2301 }
2302
2303 return no_sapi;
2304}
Holger Hans Peter Freytherb3489392011-12-28 16:21:05 +01002305
2306int rsl_start_t3109(struct gsm_lchan *lchan)
2307{
2308 struct gsm_bts *bts = lchan->ts->trx->bts;
2309
2310 /* Disabled, mostly legacy code */
2311 if (bts->network->T3109 == 0)
2312 return -1;
2313
2314 lchan->T3109.cb = t3109_expired;
2315 lchan->T3109.data = lchan;
2316 osmo_timer_schedule(&lchan->T3109, bts->network->T3109, 0);
2317 return 0;
2318}
Holger Hans Peter Freyther006e3d82012-12-25 23:45:14 +01002319
2320/**
2321 * \brief directly RF Channel Release the lchan
2322 *
2323 * When no SAPI was allocated, directly release the logical channel. This
2324 * should only be called from chan_alloc.c on channel release handling. In
2325 * case no SAPI was established the RF Channel can be directly released,
2326 */
2327int rsl_direct_rf_release(struct gsm_lchan *lchan)
2328{
2329 int i;
2330 for (i = 0; i < ARRAY_SIZE(lchan->sapis); ++i) {
2331 if (lchan->sapis[i] != LCHAN_SAPI_UNUSED) {
2332 LOGP(DRSL, LOGL_ERROR, "%s SAPI(%d) still allocated.\n",
2333 gsm_lchan_name(lchan), i);
2334 return -1;
2335 }
2336 }
2337
2338 /* Now release it */
2339 return rsl_rf_chan_release(lchan, 0, SACCH_NONE);
2340}