blob: 95d5c1ea7dcd54a2fbe8ee6bff9789ba697b5a12 [file] [log] [blame]
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +02001/* GSM Radio Signalling Link messages on the A-bis interface
Harald Welte59b04682009-06-10 05:40:52 +08002 * 3GPP TS 08.58 version 8.6.0 Release 1999 / ETSI TS 100 596 V8.6.0 */
3
Harald Weltea22d36b2010-03-04 10:33:10 +01004/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
Harald Welte59b04682009-06-10 05:40:52 +08005 *
6 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
Harald Welte0e3e88e2011-01-01 15:25:50 +01009 * it under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
Harald Welte59b04682009-06-10 05:40:52 +080011 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Harald Welte0e3e88e2011-01-01 15:25:50 +010016 * GNU Affero General Public License for more details.
Harald Welte59b04682009-06-10 05:40:52 +080017 *
Harald Welte0e3e88e2011-01-01 15:25:50 +010018 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Harald Welte59b04682009-06-10 05:40:52 +080020 *
21 */
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <errno.h>
Harald Welte59b04682009-06-10 05:40:52 +080026#include <netinet/in.h>
27#include <arpa/inet.h>
28
29#include <openbsc/gsm_data.h>
30#include <openbsc/gsm_04_08.h>
Pablo Neira Ayusodd5fff42011-03-22 16:47:59 +010031#include <osmocom/gsm/gsm_utils.h>
Harald Welte59b04682009-06-10 05:40:52 +080032#include <openbsc/abis_rsl.h>
33#include <openbsc/chan_alloc.h>
Harald Welteed9a5ab2009-08-09 13:47:35 +020034#include <openbsc/bsc_rll.h>
Harald Welte59b04682009-06-10 05:40:52 +080035#include <openbsc/debug.h>
Pablo Neira Ayusodd5fff42011-03-22 16:47:59 +010036#include <osmocom/gsm/tlv.h>
Harald Welte59b04682009-06-10 05:40:52 +080037#include <openbsc/paging.h>
38#include <openbsc/signal.h>
Harald Weltec20bd1d2009-11-29 19:07:28 +010039#include <openbsc/meas_rep.h>
Harald Welte50517742009-12-20 15:42:44 +010040#include <openbsc/rtp_proxy.h>
Pablo Neira Ayuso42e41df2011-08-17 22:44:07 +020041#include <osmocom/abis/e1_input.h>
Pablo Neira Ayusodd5fff42011-03-22 16:47:59 +010042#include <osmocom/gsm/rsl.h>
Pablo Neira Ayusodd5fff42011-03-22 16:47:59 +010043#include <osmocom/core/talloc.h>
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +080044
Harald Welte59b04682009-06-10 05:40:52 +080045#define RSL_ALLOC_SIZE 1024
46#define RSL_ALLOC_HEADROOM 128
47
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +080048static int rsl_send_imm_assignment(struct gsm_lchan *lchan);
49
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +010050static void send_lchan_signal(int sig_no, struct gsm_lchan *lchan,
51 struct gsm_meas_rep *resp)
52{
53 struct lchan_signal_data sig;
54 sig.lchan = lchan;
55 sig.mr = resp;
Pablo Neira Ayusoef717c62011-05-06 12:12:31 +020056 osmo_signal_dispatch(SS_LCHAN, sig_no, &sig);
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +010057}
58
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +020059static uint8_t mdisc_by_msgtype(uint8_t msg_type)
Harald Welte59b04682009-06-10 05:40:52 +080060{
61 /* mask off the transparent bit ? */
62 msg_type &= 0xfe;
63
64 if ((msg_type & 0xf0) == 0x00)
65 return ABIS_RSL_MDISC_RLL;
66 if ((msg_type & 0xf0) == 0x10) {
67 if (msg_type >= 0x19 && msg_type <= 0x22)
68 return ABIS_RSL_MDISC_TRX;
69 else
70 return ABIS_RSL_MDISC_COM_CHAN;
71 }
72 if ((msg_type & 0xe0) == 0x20)
73 return ABIS_RSL_MDISC_DED_CHAN;
74
75 return ABIS_RSL_MDISC_LOC;
76}
77
78static inline void init_dchan_hdr(struct abis_rsl_dchan_hdr *dh,
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +020079 uint8_t msg_type)
Harald Welte59b04682009-06-10 05:40:52 +080080{
81 dh->c.msg_discr = mdisc_by_msgtype(msg_type);
82 dh->c.msg_type = msg_type;
83 dh->ie_chan = RSL_IE_CHAN_NR;
84}
85
Harald Welte59b04682009-06-10 05:40:52 +080086/* determine logical channel based on TRX and channel number IE */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +020087struct gsm_lchan *lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr)
Harald Welte59b04682009-06-10 05:40:52 +080088{
89 struct gsm_lchan *lchan;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +020090 uint8_t ts_nr = chan_nr & 0x07;
91 uint8_t cbits = chan_nr >> 3;
92 uint8_t lch_idx;
Harald Welte59b04682009-06-10 05:40:52 +080093 struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr];
94
95 if (cbits == 0x01) {
96 lch_idx = 0; /* TCH/F */
Harald Welte37884ed2009-10-24 10:25:50 +020097 if (ts->pchan != GSM_PCHAN_TCH_F &&
98 ts->pchan != GSM_PCHAN_PDCH &&
99 ts->pchan != GSM_PCHAN_TCH_F_PDCH)
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100100 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte59b04682009-06-10 05:40:52 +0800101 chan_nr, ts->pchan);
102 } else if ((cbits & 0x1e) == 0x02) {
103 lch_idx = cbits & 0x1; /* TCH/H */
104 if (ts->pchan != GSM_PCHAN_TCH_H)
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100105 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte59b04682009-06-10 05:40:52 +0800106 chan_nr, ts->pchan);
107 } else if ((cbits & 0x1c) == 0x04) {
108 lch_idx = cbits & 0x3; /* SDCCH/4 */
109 if (ts->pchan != GSM_PCHAN_CCCH_SDCCH4)
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100110 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte59b04682009-06-10 05:40:52 +0800111 chan_nr, ts->pchan);
112 } else if ((cbits & 0x18) == 0x08) {
113 lch_idx = cbits & 0x7; /* SDCCH/8 */
114 if (ts->pchan != GSM_PCHAN_SDCCH8_SACCH8C)
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100115 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte59b04682009-06-10 05:40:52 +0800116 chan_nr, ts->pchan);
117 } else if (cbits == 0x10 || cbits == 0x11 || cbits == 0x12) {
118 lch_idx = 0;
119 if (ts->pchan != GSM_PCHAN_CCCH &&
120 ts->pchan != GSM_PCHAN_CCCH_SDCCH4)
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100121 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte59b04682009-06-10 05:40:52 +0800122 chan_nr, ts->pchan);
123 /* FIXME: we should not return first sdcch4 !!! */
124 } else {
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100125 LOGP(DRSL, LOGL_ERROR, "unknown chan_nr=0x%02x\n", chan_nr);
Harald Welte59b04682009-06-10 05:40:52 +0800126 return NULL;
127 }
128
129 lchan = &ts->lchan[lch_idx];
Harald Welte51d2a592010-03-26 21:28:59 +0800130 log_set_context(BSC_CTX_LCHAN, lchan);
Holger Hans Peter Freyther1a95fa82010-06-28 15:47:12 +0800131 if (lchan->conn)
132 log_set_context(BSC_CTX_SUBSCR, lchan->conn->subscr);
Harald Welte59b04682009-06-10 05:40:52 +0800133
134 return lchan;
135}
136
Harald Welte59b04682009-06-10 05:40:52 +0800137/* As per TS 03.03 Section 2.2, the IMSI has 'not more than 15 digits' */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200138uint64_t str_to_imsi(const char *imsi_str)
Harald Welte59b04682009-06-10 05:40:52 +0800139{
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200140 uint64_t ret;
Harald Welte59b04682009-06-10 05:40:52 +0800141
142 ret = strtoull(imsi_str, NULL, 10);
143
144 return ret;
145}
146
Harald Welte59b04682009-06-10 05:40:52 +0800147static struct msgb *rsl_msgb_alloc(void)
148{
Harald Welte9cfc9352009-06-26 19:39:35 +0200149 return msgb_alloc_headroom(RSL_ALLOC_SIZE, RSL_ALLOC_HEADROOM,
150 "RSL");
Harald Welte59b04682009-06-10 05:40:52 +0800151}
152
153#define MACBLOCK_SIZE 23
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200154static void pad_macblock(uint8_t *out, const uint8_t *in, int len)
Harald Welte59b04682009-06-10 05:40:52 +0800155{
156 memcpy(out, in, len);
157
158 if (len < MACBLOCK_SIZE)
159 memset(out+len, 0x2b, MACBLOCK_SIZE-len);
160}
161
Harald Welted2dd9de2009-08-30 15:37:11 +0900162/* Chapter 9.3.7: Encryption Information */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200163static int build_encr_info(uint8_t *out, struct gsm_lchan *lchan)
Harald Welted2dd9de2009-08-30 15:37:11 +0900164{
165 *out++ = lchan->encr.alg_id & 0xff;
166 if (lchan->encr.key_len)
167 memcpy(out, lchan->encr.key, lchan->encr.key_len);
168 return lchan->encr.key_len + 1;
169}
170
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200171static void print_rsl_cause(int lvl, const uint8_t *cause_v, uint8_t cause_len)
Harald Weltef1a168d2009-07-28 17:58:09 +0200172{
Harald Welte59b04682009-06-10 05:40:52 +0800173 int i;
174
Harald Weltede4477a2009-12-24 12:20:20 +0100175 LOGPC(DRSL, lvl, "CAUSE=0x%02x(%s) ",
Harald Weltef1a168d2009-07-28 17:58:09 +0200176 cause_v[0], rsl_err_name(cause_v[0]));
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +0200177 for (i = 1; i < cause_len-1; i++)
Harald Weltede4477a2009-12-24 12:20:20 +0100178 LOGPC(DRSL, lvl, "%02x ", cause_v[i]);
Harald Welte59b04682009-06-10 05:40:52 +0800179}
180
Harald Welte32951ea2011-08-10 23:26:33 +0200181static void lchan_act_tmr_cb(void *data)
182{
183 struct gsm_lchan *lchan = data;
184
Holger Hans Peter Freytherb050e3e2012-12-06 19:00:35 +0100185 LOGP(DRSL, LOGL_ERROR, "%s Timeout during activation!\n",
Harald Welte32951ea2011-08-10 23:26:33 +0200186 gsm_lchan_name(lchan));
187
Daniel Willmann2731e732011-08-11 04:44:12 +0200188 rsl_lchan_set_state(lchan, LCHAN_S_NONE);
189 lchan_free(lchan);
Harald Welte32951ea2011-08-10 23:26:33 +0200190}
191
192static void lchan_deact_tmr_cb(void *data)
193{
194 struct gsm_lchan *lchan = data;
195
Holger Hans Peter Freytherb050e3e2012-12-06 19:00:35 +0100196 LOGP(DRSL, LOGL_ERROR, "%s Timeout during deactivation!\n",
Harald Welte32951ea2011-08-10 23:26:33 +0200197 gsm_lchan_name(lchan));
198
Holger Hans Peter Freyther7a663792012-01-14 21:56:37 +0100199 if (lchan->state != LCHAN_S_REL_ERR)
200 rsl_lchan_set_state(lchan, LCHAN_S_NONE);
Daniel Willmann2731e732011-08-11 04:44:12 +0200201 lchan_free(lchan);
Harald Welte32951ea2011-08-10 23:26:33 +0200202}
203
204
Harald Welte59b04682009-06-10 05:40:52 +0800205/* Send a BCCH_INFO message as per Chapter 8.5.1 */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200206int rsl_bcch_info(struct gsm_bts_trx *trx, uint8_t type,
207 const uint8_t *data, int len)
Harald Welte59b04682009-06-10 05:40:52 +0800208{
209 struct abis_rsl_dchan_hdr *dh;
210 struct msgb *msg = rsl_msgb_alloc();
211
212 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof*dh);
213 init_dchan_hdr(dh, RSL_MT_BCCH_INFO);
214 dh->chan_nr = RSL_CHAN_BCCH;
215
216 msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
217 msgb_tlv_put(msg, RSL_IE_FULL_BCCH_INFO, len, data);
218
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200219 msg->dst = trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800220
221 return abis_rsl_sendmsg(msg);
222}
223
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200224int rsl_sacch_filling(struct gsm_bts_trx *trx, uint8_t type,
225 const uint8_t *data, int len)
Harald Welte59b04682009-06-10 05:40:52 +0800226{
227 struct abis_rsl_common_hdr *ch;
228 struct msgb *msg = rsl_msgb_alloc();
229
230 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
231 ch->msg_discr = ABIS_RSL_MDISC_TRX;
232 ch->msg_type = RSL_MT_SACCH_FILL;
233
234 msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
235 msgb_tl16v_put(msg, RSL_IE_L3_INFO, len, data);
236
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200237 msg->dst = trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800238
239 return abis_rsl_sendmsg(msg);
240}
241
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200242int rsl_sacch_info_modify(struct gsm_lchan *lchan, uint8_t type,
243 const uint8_t *data, int len)
Harald Welte10b7d8f2011-01-13 23:16:03 +0100244{
245 struct abis_rsl_dchan_hdr *dh;
246 struct msgb *msg = rsl_msgb_alloc();
Harald Weltee6d51f92011-06-25 10:02:33 +0200247 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte10b7d8f2011-01-13 23:16:03 +0100248
249 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
250 init_dchan_hdr(dh, RSL_MT_SACCH_INFO_MODIFY);
251 dh->chan_nr = chan_nr;
252
253 msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
254 msgb_tl16v_put(msg, RSL_IE_L3_INFO, len, data);
255
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200256 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte10b7d8f2011-01-13 23:16:03 +0100257
258 return abis_rsl_sendmsg(msg);
259}
260
Harald Welte91afe4c2009-06-20 18:15:19 +0200261int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db)
262{
263 struct abis_rsl_dchan_hdr *dh;
Harald Welteed831842009-06-27 03:09:08 +0200264 struct msgb *msg;
Harald Weltee6d51f92011-06-25 10:02:33 +0200265 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte91afe4c2009-06-20 18:15:19 +0200266
267 db = abs(db);
268 if (db > 30)
269 return -EINVAL;
270
Harald Welteed831842009-06-27 03:09:08 +0200271 msg = rsl_msgb_alloc();
272
Harald Welte91afe4c2009-06-20 18:15:19 +0200273 lchan->bs_power = db/2;
274 if (fpc)
275 lchan->bs_power |= 0x10;
276
277 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
278 init_dchan_hdr(dh, RSL_MT_BS_POWER_CONTROL);
279 dh->chan_nr = chan_nr;
280
281 msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power);
282
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200283 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte91afe4c2009-06-20 18:15:19 +0200284
285 return abis_rsl_sendmsg(msg);
286}
287
Harald Welte91afe4c2009-06-20 18:15:19 +0200288int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm)
289{
290 struct abis_rsl_dchan_hdr *dh;
Harald Welteed831842009-06-27 03:09:08 +0200291 struct msgb *msg;
Harald Weltee6d51f92011-06-25 10:02:33 +0200292 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte91afe4c2009-06-20 18:15:19 +0200293 int ctl_lvl;
294
Harald Weltec4dcda02009-08-09 14:45:18 +0200295 ctl_lvl = ms_pwr_ctl_lvl(lchan->ts->trx->bts->band, dbm);
Harald Welte91afe4c2009-06-20 18:15:19 +0200296 if (ctl_lvl < 0)
297 return ctl_lvl;
298
Harald Welteed831842009-06-27 03:09:08 +0200299 msg = rsl_msgb_alloc();
300
Harald Welte91afe4c2009-06-20 18:15:19 +0200301 lchan->ms_power = ctl_lvl;
302
303 if (fpc)
304 lchan->ms_power |= 0x20;
305
306 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
307 init_dchan_hdr(dh, RSL_MT_MS_POWER_CONTROL);
308 dh->chan_nr = chan_nr;
309
310 msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power);
311
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200312 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte91afe4c2009-06-20 18:15:19 +0200313
314 return abis_rsl_sendmsg(msg);
315}
316
Harald Welte39274f42009-07-29 15:41:29 +0200317static int channel_mode_from_lchan(struct rsl_ie_chan_mode *cm,
318 struct gsm_lchan *lchan)
319{
320 memset(cm, 0, sizeof(cm));
321
322 /* FIXME: what to do with data calls ? */
Holger Hans Peter Freyther21d63ff2010-09-06 09:25:48 +0800323 if (lchan->ts->trx->bts->network->dtx_enabled)
324 cm->dtx_dtu = 0x03;
325 else
326 cm->dtx_dtu = 0x00;
Harald Welte39274f42009-07-29 15:41:29 +0200327
328 /* set TCH Speech/Data */
329 cm->spd_ind = lchan->rsl_cmode;
330
Harald Welte951e3512009-11-27 08:55:16 +0100331 if (lchan->rsl_cmode == RSL_CMOD_SPD_SIGN &&
332 lchan->tch_mode != GSM48_CMODE_SIGN)
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100333 LOGP(DRSL, LOGL_ERROR, "unsupported: rsl_mode == signalling, "
Harald Welte951e3512009-11-27 08:55:16 +0100334 "but tch_mode != signalling\n");
335
Harald Welte39274f42009-07-29 15:41:29 +0200336 switch (lchan->type) {
337 case GSM_LCHAN_SDCCH:
338 cm->chan_rt = RSL_CMOD_CRT_SDCCH;
339 break;
340 case GSM_LCHAN_TCH_F:
341 cm->chan_rt = RSL_CMOD_CRT_TCH_Bm;
342 break;
343 case GSM_LCHAN_TCH_H:
344 cm->chan_rt = RSL_CMOD_CRT_TCH_Lm;
345 break;
346 case GSM_LCHAN_NONE:
347 case GSM_LCHAN_UNKNOWN:
348 default:
349 return -EINVAL;
350 }
351
352 switch (lchan->tch_mode) {
353 case GSM48_CMODE_SIGN:
354 cm->chan_rate = 0;
355 break;
356 case GSM48_CMODE_SPEECH_V1:
357 cm->chan_rate = RSL_CMOD_SP_GSM1;
358 break;
359 case GSM48_CMODE_SPEECH_EFR:
360 cm->chan_rate = RSL_CMOD_SP_GSM2;
361 break;
362 case GSM48_CMODE_SPEECH_AMR:
363 cm->chan_rate = RSL_CMOD_SP_GSM3;
364 break;
365 case GSM48_CMODE_DATA_14k5:
Harald Welte39274f42009-07-29 15:41:29 +0200366 case GSM48_CMODE_DATA_12k0:
Harald Welte39274f42009-07-29 15:41:29 +0200367 case GSM48_CMODE_DATA_6k0:
Harald Weltee75a47d2012-08-24 15:33:56 +0200368 switch (lchan->csd_mode) {
369 case LCHAN_CSD_M_NT:
370 /* non-transparent CSD with RLP */
371 switch (lchan->tch_mode) {
372 case GSM48_CMODE_DATA_14k5:
373 cm->chan_rate = RSL_CMOD_SP_NT_14k5;
374 break;
375 case GSM48_CMODE_DATA_12k0:
376 cm->chan_rate = RSL_CMOD_SP_NT_12k0;
377 break;
378 case GSM48_CMODE_DATA_6k0:
379 cm->chan_rate = RSL_CMOD_SP_NT_6k0;
380 break;
381 default:
382 return -EINVAL;
383 }
384 break;
385 /* transparent data services below */
386 case LCHAN_CSD_M_T_1200_75:
387 cm->chan_rate = RSL_CMOD_CSD_T_1200_75;
388 break;
389 case LCHAN_CSD_M_T_600:
390 cm->chan_rate = RSL_CMOD_CSD_T_600;
391 break;
392 case LCHAN_CSD_M_T_1200:
393 cm->chan_rate = RSL_CMOD_CSD_T_1200;
394 break;
395 case LCHAN_CSD_M_T_2400:
396 cm->chan_rate = RSL_CMOD_CSD_T_2400;
397 break;
398 case LCHAN_CSD_M_T_9600:
399 cm->chan_rate = RSL_CMOD_CSD_T_9600;
400 break;
401 case LCHAN_CSD_M_T_14400:
402 cm->chan_rate = RSL_CMOD_CSD_T_14400;
403 break;
404 case LCHAN_CSD_M_T_29000:
405 cm->chan_rate = RSL_CMOD_CSD_T_29000;
406 break;
407 case LCHAN_CSD_M_T_32000:
408 cm->chan_rate = RSL_CMOD_CSD_T_32000;
409 break;
410 default:
411 return -EINVAL;
412 }
Harald Welte39274f42009-07-29 15:41:29 +0200413 default:
414 return -EINVAL;
415 }
416
417 return 0;
418}
419
Harald Welte59b04682009-06-10 05:40:52 +0800420/* Chapter 8.4.1 */
421#if 0
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200422int rsl_chan_activate(struct gsm_bts_trx *trx, uint8_t chan_nr,
423 uint8_t act_type,
Harald Welte59b04682009-06-10 05:40:52 +0800424 struct rsl_ie_chan_mode *chan_mode,
425 struct rsl_ie_chan_ident *chan_ident,
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200426 uint8_t bs_power, uint8_t ms_power,
427 uint8_t ta)
Harald Welte59b04682009-06-10 05:40:52 +0800428{
429 struct abis_rsl_dchan_hdr *dh;
430 struct msgb *msg = rsl_msgb_alloc();
431
432 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
433 init_dchan_hdr(dh, RSL_MT_CHAN_ACTIV);
434 dh->chan_nr = chan_nr;
435
436 msgb_tv_put(msg, RSL_IE_ACT_TYPE, act_type);
437 /* For compatibility with Phase 1 */
438 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(*chan_mode),
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200439 (uint8_t *) chan_mode);
Harald Welte59b04682009-06-10 05:40:52 +0800440 msgb_tlv_put(msg, RSL_IE_CHAN_IDENT, 4,
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200441 (uint8_t *) chan_ident);
Harald Welte59b04682009-06-10 05:40:52 +0800442#if 0
443 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, 1,
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200444 (uint8_t *) &encr_info);
Harald Welte59b04682009-06-10 05:40:52 +0800445#endif
446 msgb_tv_put(msg, RSL_IE_BS_POWER, bs_power);
447 msgb_tv_put(msg, RSL_IE_MS_POWER, ms_power);
448 msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta);
449
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200450 msg->dst = trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800451
452 return abis_rsl_sendmsg(msg);
453}
454#endif
455
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200456int rsl_chan_activate_lchan(struct gsm_lchan *lchan, uint8_t act_type,
457 uint8_t ta, uint8_t ho_ref)
Harald Welte59b04682009-06-10 05:40:52 +0800458{
459 struct abis_rsl_dchan_hdr *dh;
Harald Welteed831842009-06-27 03:09:08 +0200460 struct msgb *msg;
Harald Welte39274f42009-07-29 15:41:29 +0200461 int rc;
Harald Weltedea24e92010-06-29 17:53:45 +0200462 uint8_t *len;
Harald Welte59b04682009-06-10 05:40:52 +0800463
Harald Weltee6d51f92011-06-25 10:02:33 +0200464 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte59b04682009-06-10 05:40:52 +0800465 struct rsl_ie_chan_mode cm;
laforgef723cf02010-06-20 21:38:19 +0200466 struct gsm48_chan_desc cd;
Harald Welte59b04682009-06-10 05:40:52 +0800467
Harald Welte39274f42009-07-29 15:41:29 +0200468 rc = channel_mode_from_lchan(&cm, lchan);
469 if (rc < 0)
470 return rc;
Harald Welte59b04682009-06-10 05:40:52 +0800471
Holger Hans Peter Freyther11b01402010-06-30 11:56:43 +0800472 memset(&cd, 0, sizeof(cd));
laforgef723cf02010-06-20 21:38:19 +0200473 gsm48_lchan2chan_desc(&cd, lchan);
Harald Welte59b04682009-06-10 05:40:52 +0800474
Harald Welteed831842009-06-27 03:09:08 +0200475 msg = rsl_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800476 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
477 init_dchan_hdr(dh, RSL_MT_CHAN_ACTIV);
478 dh->chan_nr = chan_nr;
479
480 msgb_tv_put(msg, RSL_IE_ACT_TYPE, act_type);
Harald Welte59b04682009-06-10 05:40:52 +0800481 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200482 (uint8_t *) &cm);
Holger Hans Peter Freyther11b01402010-06-30 11:56:43 +0800483
484 /*
485 * The Channel Identification is needed for Phase1 phones
486 * and it contains the GSM48 Channel Description and the
487 * Mobile Allocation. The GSM 08.58 asks for the Mobile
488 * Allocation to have a length of zero. We are using the
489 * msgb_l3len to calculate the length of both messages.
490 */
laforgef723cf02010-06-20 21:38:19 +0200491 msgb_v_put(msg, RSL_IE_CHAN_IDENT);
Harald Weltedea24e92010-06-29 17:53:45 +0200492 len = msgb_put(msg, 1);
Dieter Spaar18a55f62011-07-27 23:40:33 +0200493 msgb_tv_fixed_put(msg, GSM48_IE_CHANDESC_2, sizeof(cd), (const uint8_t *) &cd);
Holger Hans Peter Freyther4cab4422010-06-30 12:06:20 +0800494
495 if (lchan->ts->hopping.enabled)
496 msgb_tlv_put(msg, GSM48_IE_MA_AFTER, lchan->ts->hopping.ma_len,
497 lchan->ts->hopping.ma_data);
498 else
499 msgb_tlv_put(msg, GSM48_IE_MA_AFTER, 0, NULL);
Holger Hans Peter Freyther11b01402010-06-30 11:56:43 +0800500
501 /* update the calculated size */
502 msg->l3h = len + 1;
503 *len = msgb_l3len(msg);
504
Harald Welted2dd9de2009-08-30 15:37:11 +0900505 if (lchan->encr.alg_id > RSL_ENC_ALG_A5(0)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200506 uint8_t encr_info[MAX_A5_KEY_LEN+2];
Harald Welted2dd9de2009-08-30 15:37:11 +0900507 rc = build_encr_info(encr_info, lchan);
508 if (rc > 0)
509 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, rc, encr_info);
510 }
511
Harald Welteb90d7bd2009-12-17 00:31:10 +0100512 switch (act_type) {
513 case RSL_ACT_INTER_ASYNC:
514 case RSL_ACT_INTER_SYNC:
515 msgb_tv_put(msg, RSL_IE_HANDO_REF, ho_ref);
516 break;
517 default:
518 break;
519 }
520
Harald Welte59b04682009-06-10 05:40:52 +0800521 msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power);
522 msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power);
523 msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta);
524
Holger Hans Peter Freyther6fe8ab92010-01-28 04:45:05 +0100525 if (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR)
526 msgb_tlv_put(msg, RSL_IE_MR_CONFIG, sizeof(lchan->mr_conf),
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200527 (uint8_t *) &lchan->mr_conf);
Holger Hans Peter Freyther6fe8ab92010-01-28 04:45:05 +0100528
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200529 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800530
531 return abis_rsl_sendmsg(msg);
532}
533
Harald Welte8e770492009-07-29 11:38:15 +0200534/* Chapter 8.4.9: Modify channel mode on BTS side */
Harald Welte59b04682009-06-10 05:40:52 +0800535int rsl_chan_mode_modify_req(struct gsm_lchan *lchan)
536{
537 struct abis_rsl_dchan_hdr *dh;
Harald Welteed831842009-06-27 03:09:08 +0200538 struct msgb *msg;
Harald Welte39274f42009-07-29 15:41:29 +0200539 int rc;
Harald Welte59b04682009-06-10 05:40:52 +0800540
Harald Weltee6d51f92011-06-25 10:02:33 +0200541 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte59b04682009-06-10 05:40:52 +0800542 struct rsl_ie_chan_mode cm;
543
Harald Welte39274f42009-07-29 15:41:29 +0200544 rc = channel_mode_from_lchan(&cm, lchan);
545 if (rc < 0)
546 return rc;
Harald Welte59b04682009-06-10 05:40:52 +0800547
Harald Welteed831842009-06-27 03:09:08 +0200548 msg = rsl_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800549 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
550 init_dchan_hdr(dh, RSL_MT_MODE_MODIFY_REQ);
551 dh->chan_nr = chan_nr;
552
553 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200554 (uint8_t *) &cm);
Harald Welted2dd9de2009-08-30 15:37:11 +0900555
556 if (lchan->encr.alg_id > RSL_ENC_ALG_A5(0)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200557 uint8_t encr_info[MAX_A5_KEY_LEN+2];
Harald Welted2dd9de2009-08-30 15:37:11 +0900558 rc = build_encr_info(encr_info, lchan);
559 if (rc > 0)
560 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, rc, encr_info);
561 }
562
Holger Hans Peter Freyther3cce58f2009-11-18 22:57:02 +0100563 if (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR) {
564 msgb_tlv_put(msg, RSL_IE_MR_CONFIG, sizeof(lchan->mr_conf),
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200565 (uint8_t *) &lchan->mr_conf);
Holger Hans Peter Freyther3cce58f2009-11-18 22:57:02 +0100566 }
567
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200568 msg->dst = lchan->ts->trx->rsl_link;
Harald Welted2dd9de2009-08-30 15:37:11 +0900569
570 return abis_rsl_sendmsg(msg);
571}
572
573/* Chapter 8.4.6: Send the encryption command with given L3 info */
574int rsl_encryption_cmd(struct msgb *msg)
575{
576 struct abis_rsl_dchan_hdr *dh;
577 struct gsm_lchan *lchan = msg->lchan;
Harald Weltee6d51f92011-06-25 10:02:33 +0200578 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200579 uint8_t encr_info[MAX_A5_KEY_LEN+2];
580 uint8_t l3_len = msg->len;
Harald Welted2dd9de2009-08-30 15:37:11 +0900581 int rc;
582
583 /* First push the L3 IE tag and length */
584 msgb_tv16_push(msg, RSL_IE_L3_INFO, l3_len);
585
586 /* then the link identifier (SAPI0, main sign link) */
587 msgb_tv_push(msg, RSL_IE_LINK_IDENT, 0);
588
589 /* then encryption information */
590 rc = build_encr_info(encr_info, lchan);
591 if (rc <= 0)
592 return rc;
593 msgb_tlv_push(msg, RSL_IE_ENCR_INFO, rc, encr_info);
594
595 /* and finally the DCHAN header */
596 dh = (struct abis_rsl_dchan_hdr *) msgb_push(msg, sizeof(*dh));
597 init_dchan_hdr(dh, RSL_MT_ENCR_CMD);
598 dh->chan_nr = chan_nr;
Harald Welte59b04682009-06-10 05:40:52 +0800599
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200600 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800601
602 return abis_rsl_sendmsg(msg);
603}
604
Harald Welte85a163c2009-08-10 11:43:22 +0200605/* Chapter 8.4.5 / 4.6: Deactivate the SACCH after 04.08 RR CHAN RELEASE */
Harald Welteafe3c232009-07-19 18:36:49 +0200606int rsl_deact_sacch(struct gsm_lchan *lchan)
607{
608 struct abis_rsl_dchan_hdr *dh;
609 struct msgb *msg = rsl_msgb_alloc();
610
611 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
612 init_dchan_hdr(dh, RSL_MT_DEACTIVATE_SACCH);
Harald Weltee6d51f92011-06-25 10:02:33 +0200613 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welteafe3c232009-07-19 18:36:49 +0200614
615 msg->lchan = lchan;
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200616 msg->dst = lchan->ts->trx->rsl_link;
Harald Welteafe3c232009-07-19 18:36:49 +0200617
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +0100618 DEBUGP(DRSL, "%s DEACTivate SACCH CMD\n", gsm_lchan_name(lchan));
Harald Welteafe3c232009-07-19 18:36:49 +0200619
620 return abis_rsl_sendmsg(msg);
621}
622
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800623static void error_timeout_cb(void *data)
624{
625 struct gsm_lchan *lchan = data;
626 if (lchan->state != LCHAN_S_REL_ERR) {
627 LOGP(DRSL, LOGL_ERROR, "%s error timeout but not in error state: %d\n",
628 gsm_lchan_name(lchan), lchan->state);
629 return;
630 }
631
632 /* go back to the none state */
633 LOGP(DRSL, LOGL_NOTICE, "%s is back in operation.\n", gsm_lchan_name(lchan));
Holger Hans Peter Freyther456fb9d2010-06-08 11:53:33 +0800634 rsl_lchan_set_state(lchan, LCHAN_S_NONE);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800635}
636
Harald Welte08011e22011-03-04 13:41:31 +0100637static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan);
638
Harald Welte85a163c2009-08-10 11:43:22 +0200639/* Chapter 8.4.14 / 4.7: Tell BTS to release the radio channel */
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800640static int rsl_rf_chan_release(struct gsm_lchan *lchan, int error)
Harald Welte59b04682009-06-10 05:40:52 +0800641{
642 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800643 struct msgb *msg;
Harald Welte08011e22011-03-04 13:41:31 +0100644 int rc;
Harald Welte59b04682009-06-10 05:40:52 +0800645
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800646 if (lchan->state == LCHAN_S_REL_ERR) {
647 LOGP(DRSL, LOGL_NOTICE, "%s is in error state not sending release.\n",
648 gsm_lchan_name(lchan));
649 return -1;
650 }
651
652 msg = rsl_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800653 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
654 init_dchan_hdr(dh, RSL_MT_RF_CHAN_REL);
Harald Weltee6d51f92011-06-25 10:02:33 +0200655 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte59b04682009-06-10 05:40:52 +0800656
657 msg->lchan = lchan;
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200658 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800659
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800660 DEBUGP(DRSL, "%s RF Channel Release CMD due error %d\n", gsm_lchan_name(lchan), error);
661
662 if (error) {
663 /*
664 * the nanoBTS sends RLL release indications after the channel release. This can
665 * be a problem when we have reassigned the channel to someone else and then can
666 * not figure out who used this channel.
667 */
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200668 struct e1inp_sign_link *sign_link = msg->dst;
669
Holger Hans Peter Freyther456fb9d2010-06-08 11:53:33 +0800670 rsl_lchan_set_state(lchan, LCHAN_S_REL_ERR);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800671 lchan->error_timer.data = lchan;
672 lchan->error_timer.cb = error_timeout_cb;
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +0200673 osmo_timer_schedule(&lchan->error_timer,
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200674 sign_link->trx->bts->network->T3111 + 2, 0);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800675 }
Harald Welte59b04682009-06-10 05:40:52 +0800676
Harald Welte32951ea2011-08-10 23:26:33 +0200677 /* Start another timer or assume the BTS sends a ACK/NACK? */
678 lchan->act_timer.cb = lchan_deact_tmr_cb;
679 lchan->act_timer.data = lchan;
680 osmo_timer_schedule(&lchan->act_timer, 4, 0);
681
Harald Welte08011e22011-03-04 13:41:31 +0100682 rc = abis_rsl_sendmsg(msg);
683
Harald Welte85a163c2009-08-10 11:43:22 +0200684 /* BTS will respond by RF CHAN REL ACK */
Harald Welte6bddd822011-01-14 23:18:59 +0100685#ifdef HSL_SR_1_0
Harald Welte08011e22011-03-04 13:41:31 +0100686 /* The HSL Femto seems to 'forget' sending a REL ACK for TS1...TS7 */
687 if (lchan->ts->trx->bts->type == GSM_BTS_TYPE_HSL_FEMTO && lchan->ts->nr != 0)
688 rc = rsl_rx_rf_chan_rel_ack(lchan);
Harald Welte6bddd822011-01-14 23:18:59 +0100689#endif
Harald Welte08011e22011-03-04 13:41:31 +0100690
691 return rc;
Harald Welte59b04682009-06-10 05:40:52 +0800692}
693
Harald Welte9773f6c2011-01-14 14:16:16 +0100694static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan)
695{
696
697 DEBUGP(DRSL, "%s RF CHANNEL RELEASE ACK\n", gsm_lchan_name(lchan));
698
Harald Welte32951ea2011-08-10 23:26:33 +0200699 osmo_timer_del(&lchan->act_timer);
700
Harald Welte9773f6c2011-01-14 14:16:16 +0100701 if (lchan->state != LCHAN_S_REL_REQ && lchan->state != LCHAN_S_REL_ERR)
702 LOGP(DRSL, LOGL_NOTICE, "%s CHAN REL ACK but state %s\n",
703 gsm_lchan_name(lchan),
704 gsm_lchans_name(lchan->state));
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +0200705 osmo_timer_del(&lchan->T3111);
Harald Welte9773f6c2011-01-14 14:16:16 +0100706 /* we have an error timer pending to release that */
707 if (lchan->state != LCHAN_S_REL_ERR)
708 rsl_lchan_set_state(lchan, LCHAN_S_NONE);
709 lchan_free(lchan);
710
711 return 0;
712}
713
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200714int rsl_paging_cmd(struct gsm_bts *bts, uint8_t paging_group, uint8_t len,
715 uint8_t *ms_ident, uint8_t chan_needed)
Harald Welte59b04682009-06-10 05:40:52 +0800716{
717 struct abis_rsl_dchan_hdr *dh;
718 struct msgb *msg = rsl_msgb_alloc();
719
720 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
721 init_dchan_hdr(dh, RSL_MT_PAGING_CMD);
722 dh->chan_nr = RSL_CHAN_PCH_AGCH;
723
724 msgb_tv_put(msg, RSL_IE_PAGING_GROUP, paging_group);
725 msgb_tlv_put(msg, RSL_IE_MS_IDENTITY, len-2, ms_ident+2);
726 msgb_tv_put(msg, RSL_IE_CHAN_NEEDED, chan_needed);
727
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200728 msg->dst = bts->c0->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800729
730 return abis_rsl_sendmsg(msg);
731}
732
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200733int imsi_str2bcd(uint8_t *bcd_out, const char *str_in)
Harald Welte59b04682009-06-10 05:40:52 +0800734{
735 int i, len = strlen(str_in);
736
737 for (i = 0; i < len; i++) {
738 int num = str_in[i] - 0x30;
739 if (num < 0 || num > 9)
740 return -1;
741 if (i % 2 == 0)
742 bcd_out[i/2] = num;
743 else
744 bcd_out[i/2] |= (num << 4);
745 }
746
747 return 0;
748}
749
750/* Chapter 8.5.6 */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200751int rsl_imm_assign_cmd(struct gsm_bts *bts, uint8_t len, uint8_t *val)
Harald Welte59b04682009-06-10 05:40:52 +0800752{
753 struct msgb *msg = rsl_msgb_alloc();
754 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200755 uint8_t buf[MACBLOCK_SIZE];
Harald Welte59b04682009-06-10 05:40:52 +0800756
757 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
758 init_dchan_hdr(dh, RSL_MT_IMMEDIATE_ASSIGN_CMD);
759 dh->chan_nr = RSL_CHAN_PCH_AGCH;
760
761 switch (bts->type) {
762 case GSM_BTS_TYPE_BS11:
763 msgb_tlv_put(msg, RSL_IE_IMM_ASS_INFO, len, val);
764 break;
765 default:
766 /* If phase 2, construct a FULL_IMM_ASS_INFO */
767 pad_macblock(buf, val, len);
768 msgb_tlv_put(msg, RSL_IE_FULL_IMM_ASS_INFO, MACBLOCK_SIZE, buf);
769 break;
770 }
771
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200772 msg->dst = bts->c0->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800773
774 return abis_rsl_sendmsg(msg);
775}
776
Harald Welte4684e632009-08-10 09:51:40 +0200777/* Send Siemens specific MS RF Power Capability Indication */
Harald Welte12090752009-08-10 10:07:33 +0200778int rsl_siemens_mrpci(struct gsm_lchan *lchan, struct rsl_mrpci *mrpci)
Harald Welte4684e632009-08-10 09:51:40 +0200779{
780 struct msgb *msg = rsl_msgb_alloc();
781 struct abis_rsl_dchan_hdr *dh;
782
783 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
784 init_dchan_hdr(dh, RSL_MT_SIEMENS_MRPCI);
Harald Welte874a5b42009-08-10 11:26:14 +0200785 dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
Harald Weltee6d51f92011-06-25 10:02:33 +0200786 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200787 msgb_tv_put(msg, RSL_IE_SIEMENS_MRPCI, *(uint8_t *)mrpci);
Harald Welte4684e632009-08-10 09:51:40 +0200788
Harald Weltede4477a2009-12-24 12:20:20 +0100789 DEBUGP(DRSL, "%s TX Siemens MRPCI 0x%02x\n",
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200790 gsm_lchan_name(lchan), *(uint8_t *)mrpci);
Harald Welte874a5b42009-08-10 11:26:14 +0200791
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200792 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte874a5b42009-08-10 11:26:14 +0200793
Harald Welte4684e632009-08-10 09:51:40 +0200794 return abis_rsl_sendmsg(msg);
795}
796
797
Harald Welte59b04682009-06-10 05:40:52 +0800798/* Send "DATA REQUEST" message with given L3 Info payload */
799/* Chapter 8.3.1 */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200800int rsl_data_request(struct msgb *msg, uint8_t link_id)
Harald Welte59b04682009-06-10 05:40:52 +0800801{
Harald Welte59b04682009-06-10 05:40:52 +0800802 if (msg->lchan == NULL) {
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100803 LOGP(DRSL, LOGL_ERROR, "cannot send DATA REQUEST to unknown lchan\n");
Harald Welte59b04682009-06-10 05:40:52 +0800804 return -EINVAL;
805 }
806
Harald Weltee6d51f92011-06-25 10:02:33 +0200807 rsl_rll_push_l3(msg, RSL_MT_DATA_REQ, gsm_lchan2chan_nr(msg->lchan),
Harald Weltea22d36b2010-03-04 10:33:10 +0100808 link_id, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800809
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200810 msg->dst = msg->lchan->ts->trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800811
812 return abis_rsl_sendmsg(msg);
813}
814
Harald Welteed9a5ab2009-08-09 13:47:35 +0200815/* Send "ESTABLISH REQUEST" message with given L3 Info payload */
816/* Chapter 8.3.1 */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200817int rsl_establish_request(struct gsm_lchan *lchan, uint8_t link_id)
Harald Welteed9a5ab2009-08-09 13:47:35 +0200818{
Harald Weltea22d36b2010-03-04 10:33:10 +0100819 struct msgb *msg;
Harald Welteed9a5ab2009-08-09 13:47:35 +0200820
Harald Weltee6d51f92011-06-25 10:02:33 +0200821 msg = rsl_rll_simple(RSL_MT_EST_REQ, gsm_lchan2chan_nr(lchan),
Harald Weltea22d36b2010-03-04 10:33:10 +0100822 link_id, 0);
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200823 msg->dst = lchan->ts->trx->rsl_link;
Harald Welteed9a5ab2009-08-09 13:47:35 +0200824
Harald Welte17091bd2012-04-26 19:42:19 +0200825 DEBUGP(DRLL, "%s RSL RLL ESTABLISH REQ (link_id=0x%02x)\n",
826 gsm_lchan_name(lchan), link_id);
827
Harald Welteed9a5ab2009-08-09 13:47:35 +0200828 return abis_rsl_sendmsg(msg);
829}
830
Harald Welte0f2e3c12009-08-08 13:15:07 +0200831/* Chapter 8.3.7 Request the release of multiframe mode of RLL connection.
832 This is what higher layers should call. The BTS then responds with
833 RELEASE CONFIRM, which we in turn use to trigger RSL CHANNEL RELEASE,
834 which in turn is acknowledged by RSL CHANNEL RELEASE ACK, which calls
835 lchan_free() */
Holger Hans Peter Freyther2806c792012-12-06 12:01:38 +0100836int rsl_release_request(struct gsm_lchan *lchan, uint8_t link_id,
837 enum rsl_rel_mode release_mode)
Harald Welte0f2e3c12009-08-08 13:15:07 +0200838{
Harald Welte0f2e3c12009-08-08 13:15:07 +0200839
Harald Weltea22d36b2010-03-04 10:33:10 +0100840 struct msgb *msg;
841
Harald Weltee6d51f92011-06-25 10:02:33 +0200842 msg = rsl_rll_simple(RSL_MT_REL_REQ, gsm_lchan2chan_nr(lchan),
Harald Weltea22d36b2010-03-04 10:33:10 +0100843 link_id, 0);
Holger Hans Peter Freytherbcea9a72010-06-08 11:57:45 +0800844 /* 0 is normal release, 1 is local end */
Holger Hans Peter Freyther2806c792012-12-06 12:01:38 +0100845 msgb_tv_put(msg, RSL_IE_RELEASE_MODE, release_mode);
Harald Welte0f2e3c12009-08-08 13:15:07 +0200846
Harald Weltec88a4432009-12-29 10:44:17 +0100847 /* FIXME: start some timer in case we don't receive a REL ACK ? */
848
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200849 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte0f2e3c12009-08-08 13:15:07 +0200850
Harald Welte17091bd2012-04-26 19:42:19 +0200851 DEBUGP(DRLL, "%s RSL RLL RELEASE REQ (link_id=0x%02x, reason=%u)\n",
Holger Hans Peter Freyther2806c792012-12-06 12:01:38 +0100852 gsm_lchan_name(lchan), link_id, release_mode);
Harald Welte17091bd2012-04-26 19:42:19 +0200853
Harald Welte0f2e3c12009-08-08 13:15:07 +0200854 return abis_rsl_sendmsg(msg);
855}
856
Holger Hans Peter Freyther68914a02010-04-10 00:12:31 +0200857int rsl_lchan_set_state(struct gsm_lchan *lchan, int state)
858{
859 lchan->state = state;
860 return 0;
861}
862
Harald Welte59b04682009-06-10 05:40:52 +0800863/* Chapter 8.4.2: Channel Activate Acknowledge */
864static int rsl_rx_chan_act_ack(struct msgb *msg)
865{
866 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
867
868 /* BTS has confirmed channel activation, we now need
869 * to assign the activated channel to the MS */
870 if (rslh->ie_chan != RSL_IE_CHAN_NR)
871 return -EINVAL;
Harald Welte6720a432009-11-29 22:45:52 +0100872
Harald Welte32951ea2011-08-10 23:26:33 +0200873 osmo_timer_del(&msg->lchan->act_timer);
874
Harald Weltec88a4432009-12-29 10:44:17 +0100875 if (msg->lchan->state != LCHAN_S_ACT_REQ)
Harald Welteab2534c2009-12-29 10:52:38 +0100876 LOGP(DRSL, LOGL_NOTICE, "%s CHAN ACT ACK, but state %s\n",
877 gsm_lchan_name(msg->lchan),
878 gsm_lchans_name(msg->lchan->state));
Holger Hans Peter Freyther68914a02010-04-10 00:12:31 +0200879 rsl_lchan_set_state(msg->lchan, LCHAN_S_ACTIVE);
Harald Welte4baa9c52009-12-21 13:27:11 +0100880
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +0800881 if (msg->lchan->rqd_ref) {
882 rsl_send_imm_assignment(msg->lchan);
883 talloc_free(msg->lchan->rqd_ref);
884 msg->lchan->rqd_ref = NULL;
885 msg->lchan->rqd_ta = 0;
886 }
887
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +0100888 send_lchan_signal(S_LCHAN_ACTIVATE_ACK, msg->lchan, NULL);
Harald Welte6720a432009-11-29 22:45:52 +0100889
Harald Welte59b04682009-06-10 05:40:52 +0800890 return 0;
891}
892
893/* Chapter 8.4.3: Channel Activate NACK */
894static int rsl_rx_chan_act_nack(struct msgb *msg)
895{
896 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
897 struct tlv_parsed tp;
898
Harald Welte32951ea2011-08-10 23:26:33 +0200899 osmo_timer_del(&msg->lchan->act_timer);
900
Daniel Willmann9e9d44c2011-08-11 04:54:23 +0200901 LOGP(DRSL, LOGL_ERROR, "%s CHANNEL ACTIVATE NACK ",
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +0100902 gsm_lchan_name(msg->lchan));
Harald Welte (local)ed6d7622009-12-27 11:48:11 +0100903
Harald Welte59b04682009-06-10 05:40:52 +0800904 /* BTS has rejected channel activation ?!? */
905 if (dh->ie_chan != RSL_IE_CHAN_NR)
906 return -EINVAL;
907
908 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
Harald Welte (local)c3be50c2009-12-27 18:12:29 +0100909 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200910 const uint8_t *cause = TLVP_VAL(&tp, RSL_IE_CAUSE);
Harald Welte (local)c3be50c2009-12-27 18:12:29 +0100911 print_rsl_cause(LOGL_ERROR, cause,
Harald Weltef1a168d2009-07-28 17:58:09 +0200912 TLVP_LEN(&tp, RSL_IE_CAUSE));
Harald Welte (local)c3be50c2009-12-27 18:12:29 +0100913 if (*cause != RSL_ERR_RCH_ALR_ACTV_ALLOC)
Holger Hans Peter Freyther68914a02010-04-10 00:12:31 +0200914 rsl_lchan_set_state(msg->lchan, LCHAN_S_NONE);
Daniel Willmann245ee032011-08-11 04:47:11 +0200915 else
916 rsl_rf_chan_release(msg->lchan, 1);
917
Harald Welte (local)c3be50c2009-12-27 18:12:29 +0100918 } else
Holger Hans Peter Freyther68914a02010-04-10 00:12:31 +0200919 rsl_lchan_set_state(msg->lchan, LCHAN_S_NONE);
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +0200920
Harald Welte (local)ed6d7622009-12-27 11:48:11 +0100921 LOGPC(DRSL, LOGL_ERROR, "\n");
922
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +0100923 send_lchan_signal(S_LCHAN_ACTIVATE_NACK, msg->lchan, NULL);
Harald Welte6720a432009-11-29 22:45:52 +0100924
Harald Weltecddb9802009-08-09 19:50:08 +0200925 lchan_free(msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +0800926 return 0;
927}
928
929/* Chapter 8.4.4: Connection Failure Indication */
930static int rsl_rx_conn_fail(struct msgb *msg)
931{
932 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
933 struct tlv_parsed tp;
934
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100935 /* FIXME: print which channel */
Harald Welte (local)4bd76642009-12-26 22:33:09 +0100936 LOGP(DRSL, LOGL_NOTICE, "%s CONNECTION FAIL: RELEASING ",
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +0100937 gsm_lchan_name(msg->lchan));
Harald Welte59b04682009-06-10 05:40:52 +0800938
939 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
940
Harald Weltef1a168d2009-07-28 17:58:09 +0200941 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
Harald Weltede4477a2009-12-24 12:20:20 +0100942 print_rsl_cause(LOGL_NOTICE, TLVP_VAL(&tp, RSL_IE_CAUSE),
Harald Weltef1a168d2009-07-28 17:58:09 +0200943 TLVP_LEN(&tp, RSL_IE_CAUSE));
944
Harald Welte (local)4bd76642009-12-26 22:33:09 +0100945 LOGPC(DRSL, LOGL_NOTICE, "\n");
Harald Welte59b04682009-06-10 05:40:52 +0800946 /* FIXME: only free it after channel release ACK */
Pablo Neira Ayuso1c450742011-05-06 12:13:10 +0200947 osmo_counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rf_fail);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800948 return rsl_rf_chan_release(msg->lchan, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800949}
950
Harald Weltec20bd1d2009-11-29 19:07:28 +0100951static void print_meas_rep_uni(struct gsm_meas_rep_unidir *mru,
952 const char *prefix)
953{
Harald Welte0e4fa782009-12-16 16:52:07 +0100954 DEBUGPC(DMEAS, "RXL-FULL-%s=%3ddBm RXL-SUB-%s=%3ddBm ",
955 prefix, rxlev2dbm(mru->full.rx_lev),
956 prefix, rxlev2dbm(mru->sub.rx_lev));
Harald Weltec20bd1d2009-11-29 19:07:28 +0100957 DEBUGPC(DMEAS, "RXQ-FULL-%s=%d RXQ-SUB-%s=%d ",
958 prefix, mru->full.rx_qual, prefix, mru->sub.rx_qual);
959}
960
Harald Welte50290cc2012-07-02 17:12:08 +0200961static void print_meas_rep(struct gsm_lchan *lchan, struct gsm_meas_rep *mr)
Harald Weltec20bd1d2009-11-29 19:07:28 +0100962{
Harald Welte0e4fa782009-12-16 16:52:07 +0100963 int i;
Harald Welte50290cc2012-07-02 17:12:08 +0200964 char *name = "";
Harald Welte0e4fa782009-12-16 16:52:07 +0100965
Harald Welte50290cc2012-07-02 17:12:08 +0200966 if (lchan && lchan->conn && lchan->conn->subscr)
967 name = subscr_name(lchan->conn->subscr);
968
969 DEBUGP(DMEAS, "[%s] MEASUREMENT RESULT NR=%d ", name, mr->nr);
Harald Weltec20bd1d2009-11-29 19:07:28 +0100970
971 if (mr->flags & MEAS_REP_F_DL_DTX)
972 DEBUGPC(DMEAS, "DTXd ");
973
974 print_meas_rep_uni(&mr->ul, "ul");
975 DEBUGPC(DMEAS, "BS_POWER=%d ", mr->bs_power);
976 if (mr->flags & MEAS_REP_F_MS_TO)
977 DEBUGPC(DMEAS, "MS_TO=%d ", mr->ms_timing_offset);
978
979 if (mr->flags & MEAS_REP_F_MS_L1) {
Harald Welte0e4fa782009-12-16 16:52:07 +0100980 DEBUGPC(DMEAS, "L1_MS_PWR=%3ddBm ", mr->ms_l1.pwr);
Harald Weltec20bd1d2009-11-29 19:07:28 +0100981 DEBUGPC(DMEAS, "L1_FPC=%u ",
982 mr->flags & MEAS_REP_F_FPC ? 1 : 0);
983 DEBUGPC(DMEAS, "L1_TA=%u ", mr->ms_l1.ta);
984 }
985
986 if (mr->flags & MEAS_REP_F_UL_DTX)
987 DEBUGPC(DMEAS, "DTXu ");
988 if (mr->flags & MEAS_REP_F_BA1)
989 DEBUGPC(DMEAS, "BA1 ");
990 if (!(mr->flags & MEAS_REP_F_DL_VALID))
991 DEBUGPC(DMEAS, "NOT VALID ");
992 else
993 print_meas_rep_uni(&mr->dl, "dl");
994
995 DEBUGPC(DMEAS, "NUM_NEIGH=%u\n", mr->num_cell);
Harald Welte0b833f82009-12-19 18:33:05 +0100996 if (mr->num_cell == 7)
997 return;
Harald Welte0e4fa782009-12-16 16:52:07 +0100998 for (i = 0; i < mr->num_cell; i++) {
999 struct gsm_meas_rep_cell *mrc = &mr->cell[i];
Harald Welte350c2d32009-12-25 23:02:22 +01001000 DEBUGP(DMEAS, "IDX=%u ARFCN=%u BSIC=%u => %d dBm\n",
1001 mrc->neigh_idx, mrc->arfcn, mrc->bsic, rxlev2dbm(mrc->rxlev));
Harald Welte0e4fa782009-12-16 16:52:07 +01001002 }
Harald Weltec20bd1d2009-11-29 19:07:28 +01001003}
1004
Harald Welte59b04682009-06-10 05:40:52 +08001005static int rsl_rx_meas_res(struct msgb *msg)
1006{
1007 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1008 struct tlv_parsed tp;
Harald Weltef9476812009-12-15 21:36:05 +01001009 struct gsm_meas_rep *mr = lchan_next_meas_rep(msg->lchan);
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001010 uint8_t len;
1011 const uint8_t *val;
Harald Weltec20bd1d2009-11-29 19:07:28 +01001012 int rc;
Harald Welte59b04682009-06-10 05:40:52 +08001013
Harald Welte4baa9c52009-12-21 13:27:11 +01001014 /* check if this channel is actually active */
1015 /* FIXME: maybe this check should be way more generic/centralized */
Harald Weltec88a4432009-12-29 10:44:17 +01001016 if (msg->lchan->state != LCHAN_S_ACTIVE) {
Holger Hans Peter Freyther67a2e292010-07-29 14:50:57 +08001017 LOGP(DRSL, LOGL_DEBUG, "%s: MEAS RES for inactive channel\n",
Harald Weltec88a4432009-12-29 10:44:17 +01001018 gsm_lchan_name(msg->lchan));
Harald Welte4baa9c52009-12-21 13:27:11 +01001019 return 0;
Harald Weltec88a4432009-12-29 10:44:17 +01001020 }
Harald Welte4baa9c52009-12-21 13:27:11 +01001021
Harald Weltef9476812009-12-15 21:36:05 +01001022 memset(mr, 0, sizeof(*mr));
Harald Welteaa0efa12009-12-16 23:29:34 +01001023 mr->lchan = msg->lchan;
Harald Welte4efcc542009-11-30 19:16:47 +01001024
Harald Welte59b04682009-06-10 05:40:52 +08001025 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
1026
Harald Weltec20bd1d2009-11-29 19:07:28 +01001027 if (!TLVP_PRESENT(&tp, RSL_IE_MEAS_RES_NR) ||
1028 !TLVP_PRESENT(&tp, RSL_IE_UPLINK_MEAS) ||
1029 !TLVP_PRESENT(&tp, RSL_IE_BS_POWER))
1030 return -EIO;
1031
1032 /* Mandatory Parts */
Harald Weltef9476812009-12-15 21:36:05 +01001033 mr->nr = *TLVP_VAL(&tp, RSL_IE_MEAS_RES_NR);
Harald Weltec20bd1d2009-11-29 19:07:28 +01001034
1035 len = TLVP_LEN(&tp, RSL_IE_UPLINK_MEAS);
1036 val = TLVP_VAL(&tp, RSL_IE_UPLINK_MEAS);
1037 if (len >= 3) {
1038 if (val[0] & 0x40)
Harald Weltef9476812009-12-15 21:36:05 +01001039 mr->flags |= MEAS_REP_F_DL_DTX;
1040 mr->ul.full.rx_lev = val[0] & 0x3f;
1041 mr->ul.sub.rx_lev = val[1] & 0x3f;
1042 mr->ul.full.rx_qual = val[2]>>3 & 0x7;
1043 mr->ul.sub.rx_qual = val[2] & 0x7;
Harald Welte59b04682009-06-10 05:40:52 +08001044 }
Harald Weltec20bd1d2009-11-29 19:07:28 +01001045
Harald Weltef9476812009-12-15 21:36:05 +01001046 mr->bs_power = *TLVP_VAL(&tp, RSL_IE_BS_POWER);
Harald Weltec20bd1d2009-11-29 19:07:28 +01001047
1048 /* Optional Parts */
Harald Welte59b04682009-06-10 05:40:52 +08001049 if (TLVP_PRESENT(&tp, RSL_IE_MS_TIMING_OFFSET))
Harald Weltef9476812009-12-15 21:36:05 +01001050 mr->ms_timing_offset =
Harald Weltec20bd1d2009-11-29 19:07:28 +01001051 *TLVP_VAL(&tp, RSL_IE_MS_TIMING_OFFSET);
1052
Harald Weltea1467eb2009-06-20 18:44:35 +02001053 if (TLVP_PRESENT(&tp, RSL_IE_L1_INFO)) {
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001054 struct e1inp_sign_link *sign_link = msg->dst;
1055
Harald Weltec20bd1d2009-11-29 19:07:28 +01001056 val = TLVP_VAL(&tp, RSL_IE_L1_INFO);
Harald Weltef9476812009-12-15 21:36:05 +01001057 mr->flags |= MEAS_REP_F_MS_L1;
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001058 mr->ms_l1.pwr = ms_pwr_dbm(sign_link->trx->bts->band, val[0] >> 3);
Harald Weltec20bd1d2009-11-29 19:07:28 +01001059 if (val[0] & 0x04)
Harald Weltef9476812009-12-15 21:36:05 +01001060 mr->flags |= MEAS_REP_F_FPC;
1061 mr->ms_l1.ta = val[1];
Andreas Eversbergfe56cf82011-12-24 11:49:05 +01001062 /* BS11 and Nokia reports TA shifted by 2 bits */
1063 if (msg->lchan->ts->trx->bts->type == GSM_BTS_TYPE_BS11
1064 || msg->lchan->ts->trx->bts->type == GSM_BTS_TYPE_NOKIA_SITE)
Andreas Eversberg0f18e5e2011-12-16 17:45:37 +01001065 mr->ms_l1.ta >>= 2;
Harald Weltea1467eb2009-06-20 18:44:35 +02001066 }
Harald Welte59b04682009-06-10 05:40:52 +08001067 if (TLVP_PRESENT(&tp, RSL_IE_L3_INFO)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001068 msg->l3h = (uint8_t *) TLVP_VAL(&tp, RSL_IE_L3_INFO);
Harald Weltef9476812009-12-15 21:36:05 +01001069 rc = gsm48_parse_meas_rep(mr, msg);
Harald Weltec20bd1d2009-11-29 19:07:28 +01001070 if (rc < 0)
1071 return rc;
1072 }
1073
Harald Welte50290cc2012-07-02 17:12:08 +02001074 print_meas_rep(msg->lchan, mr);
Harald Welte59b04682009-06-10 05:40:52 +08001075
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +01001076 send_lchan_signal(S_LCHAN_MEAS_REP, msg->lchan, mr);
Harald Welte4efcc542009-11-30 19:16:47 +01001077
Harald Welte59b04682009-06-10 05:40:52 +08001078 return 0;
1079}
1080
Harald Welte6720a432009-11-29 22:45:52 +01001081/* Chapter 8.4.7 */
1082static int rsl_rx_hando_det(struct msgb *msg)
1083{
1084 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1085 struct tlv_parsed tp;
1086
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001087 DEBUGP(DRSL, "%s HANDOVER DETECT ", gsm_lchan_name(msg->lchan));
Harald Welte6720a432009-11-29 22:45:52 +01001088
1089 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
1090
1091 if (TLVP_PRESENT(&tp, RSL_IE_ACCESS_DELAY))
1092 DEBUGPC(DRSL, "access delay = %u\n",
1093 *TLVP_VAL(&tp, RSL_IE_ACCESS_DELAY));
1094 else
1095 DEBUGPC(DRSL, "\n");
1096
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +01001097 send_lchan_signal(S_LCHAN_HANDOVER_DETECT, msg->lchan, NULL);
Harald Welte6720a432009-11-29 22:45:52 +01001098
1099 return 0;
1100}
1101
Harald Welte59b04682009-06-10 05:40:52 +08001102static int abis_rsl_rx_dchan(struct msgb *msg)
1103{
1104 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
1105 int rc = 0;
1106 char *ts_name;
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001107 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001108
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001109 msg->lchan = lchan_lookup(sign_link->trx, rslh->chan_nr);
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001110 ts_name = gsm_lchan_name(msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001111
Harald Welte59b04682009-06-10 05:40:52 +08001112 switch (rslh->c.msg_type) {
1113 case RSL_MT_CHAN_ACTIV_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001114 DEBUGP(DRSL, "%s CHANNEL ACTIVATE ACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001115 rc = rsl_rx_chan_act_ack(msg);
1116 break;
1117 case RSL_MT_CHAN_ACTIV_NACK:
Harald Welte59b04682009-06-10 05:40:52 +08001118 rc = rsl_rx_chan_act_nack(msg);
1119 break;
1120 case RSL_MT_CONN_FAIL:
1121 rc = rsl_rx_conn_fail(msg);
1122 break;
1123 case RSL_MT_MEAS_RES:
1124 rc = rsl_rx_meas_res(msg);
1125 break;
Harald Welte6720a432009-11-29 22:45:52 +01001126 case RSL_MT_HANDO_DET:
1127 rc = rsl_rx_hando_det(msg);
1128 break;
Harald Welte59b04682009-06-10 05:40:52 +08001129 case RSL_MT_RF_CHAN_REL_ACK:
Harald Welte9773f6c2011-01-14 14:16:16 +01001130 rc = rsl_rx_rf_chan_rel_ack(msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001131 break;
1132 case RSL_MT_MODE_MODIFY_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001133 DEBUGP(DRSL, "%s CHANNEL MODE MODIFY ACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001134 break;
1135 case RSL_MT_MODE_MODIFY_NACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001136 LOGP(DRSL, LOGL_ERROR, "%s CHANNEL MODE MODIFY NACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001137 break;
Harald Welteaed946e2009-10-24 10:29:22 +02001138 case RSL_MT_IPAC_PDCH_ACT_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001139 DEBUGPC(DRSL, "%s IPAC PDCH ACT ACK\n", ts_name);
Harald Welte2b361522010-03-28 14:42:09 +08001140 msg->lchan->ts->flags |= TS_F_PDCH_MODE;
Harald Welteaed946e2009-10-24 10:29:22 +02001141 break;
1142 case RSL_MT_IPAC_PDCH_ACT_NACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001143 LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH ACT NACK\n", ts_name);
Harald Welteaed946e2009-10-24 10:29:22 +02001144 break;
1145 case RSL_MT_IPAC_PDCH_DEACT_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001146 DEBUGP(DRSL, "%s IPAC PDCH DEACT ACK\n", ts_name);
Harald Welte2b361522010-03-28 14:42:09 +08001147 msg->lchan->ts->flags &= ~TS_F_PDCH_MODE;
Harald Welteaed946e2009-10-24 10:29:22 +02001148 break;
1149 case RSL_MT_IPAC_PDCH_DEACT_NACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001150 LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH DEACT NACK\n", ts_name);
Harald Welteaed946e2009-10-24 10:29:22 +02001151 break;
Harald Welte59b04682009-06-10 05:40:52 +08001152 case RSL_MT_PHY_CONTEXT_CONF:
1153 case RSL_MT_PREPROC_MEAS_RES:
1154 case RSL_MT_TALKER_DET:
1155 case RSL_MT_LISTENER_DET:
1156 case RSL_MT_REMOTE_CODEC_CONF_REP:
1157 case RSL_MT_MR_CODEC_MOD_ACK:
1158 case RSL_MT_MR_CODEC_MOD_NACK:
1159 case RSL_MT_MR_CODEC_MOD_PER:
Harald Weltede4477a2009-12-24 12:20:20 +01001160 LOGP(DRSL, LOGL_NOTICE, "%s Unimplemented Abis RSL DChan "
1161 "msg 0x%02x\n", ts_name, rslh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001162 break;
1163 default:
Harald Weltede4477a2009-12-24 12:20:20 +01001164 LOGP(DRSL, LOGL_NOTICE, "%s unknown Abis RSL DChan msg 0x%02x\n",
1165 ts_name, rslh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001166 return -EINVAL;
1167 }
1168
1169 return rc;
1170}
1171
1172static int rsl_rx_error_rep(struct msgb *msg)
1173{
1174 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
Harald Weltef1a168d2009-07-28 17:58:09 +02001175 struct tlv_parsed tp;
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001176 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001177
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001178 LOGP(DRSL, LOGL_ERROR, "%s ERROR REPORT ", gsm_trx_name(sign_link->trx));
Harald Weltef1a168d2009-07-28 17:58:09 +02001179
1180 rsl_tlv_parse(&tp, rslh->data, msgb_l2len(msg)-sizeof(*rslh));
1181
1182 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
Harald Weltede4477a2009-12-24 12:20:20 +01001183 print_rsl_cause(LOGL_ERROR, TLVP_VAL(&tp, RSL_IE_CAUSE),
Harald Weltef1a168d2009-07-28 17:58:09 +02001184 TLVP_LEN(&tp, RSL_IE_CAUSE));
1185
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001186 LOGPC(DRSL, LOGL_ERROR, "\n");
Harald Welte59b04682009-06-10 05:40:52 +08001187
1188 return 0;
1189}
1190
1191static int abis_rsl_rx_trx(struct msgb *msg)
1192{
1193 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001194 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001195 int rc = 0;
1196
1197 switch (rslh->msg_type) {
1198 case RSL_MT_ERROR_REPORT:
1199 rc = rsl_rx_error_rep(msg);
1200 break;
1201 case RSL_MT_RF_RES_IND:
1202 /* interference on idle channels of TRX */
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001203 //DEBUGP(DRSL, "%s RF Resource Indication\n", gsm_trx_name(sign_link->trx));
Harald Welte59b04682009-06-10 05:40:52 +08001204 break;
1205 case RSL_MT_OVERLOAD:
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +02001206 /* indicate CCCH / ACCH / processor overload */
Harald Welte (local)ab788cf2009-12-28 23:14:22 +01001207 LOGP(DRSL, LOGL_ERROR, "%s CCCH/ACCH/CPU Overload\n",
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001208 gsm_trx_name(sign_link->trx));
Harald Welte59b04682009-06-10 05:40:52 +08001209 break;
Dieter Spaar49c843e2011-07-28 00:01:50 +02001210 case 0x42: /* Nokia specific: SI End ACK */
1211 LOGP(DRSL, LOGL_INFO, "Nokia SI End ACK\n");
1212 break;
1213 case 0x43: /* Nokia specific: SI End NACK */
1214 LOGP(DRSL, LOGL_INFO, "Nokia SI End NACK\n");
1215 break;
Harald Welte59b04682009-06-10 05:40:52 +08001216 default:
Harald Welte (local)ab788cf2009-12-28 23:14:22 +01001217 LOGP(DRSL, LOGL_NOTICE, "%s Unknown Abis RSL TRX message "
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001218 "type 0x%02x\n", gsm_trx_name(sign_link->trx), rslh->msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001219 return -EINVAL;
1220 }
1221 return rc;
1222}
1223
Harald Welte427dbc42009-08-10 00:26:10 +02001224/* If T3101 expires, we never received a response to IMMEDIATE ASSIGN */
1225static void t3101_expired(void *data)
1226{
1227 struct gsm_lchan *lchan = data;
1228
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +08001229 rsl_rf_chan_release(lchan, 1);
Harald Welte427dbc42009-08-10 00:26:10 +02001230}
1231
Holger Hans Peter Freyther4a00c062010-05-31 21:33:15 +08001232/* If T3111 expires, we will send the RF Channel Request */
1233static void t3111_expired(void *data)
1234{
1235 struct gsm_lchan *lchan = data;
1236
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +08001237 rsl_rf_chan_release(lchan, 0);
Holger Hans Peter Freyther4a00c062010-05-31 21:33:15 +08001238}
1239
laforge50312e82010-06-21 12:08:52 +02001240#define GSM48_LEN2PLEN(a) (((a) << 2) | 1)
1241
Harald Weltea00fdd72010-12-23 14:39:29 +01001242/* Format an IMM ASS REJ according to 04.08 Chapter 9.1.20 */
1243static int rsl_send_imm_ass_rej(struct gsm_bts *bts,
1244 unsigned int num_req_refs,
1245 struct gsm48_req_ref *rqd_refs,
1246 uint8_t wait_ind)
1247{
1248 uint8_t buf[GSM_MACBLOCK_LEN];
1249 struct gsm48_imm_ass_rej *iar = (struct gsm48_imm_ass_rej *)buf;
1250
1251 /* create IMMEDIATE ASSIGN REJECT 04.08 message */
1252 memset(iar, 0, sizeof(*iar));
1253 iar->proto_discr = GSM48_PDISC_RR;
1254 iar->msg_type = GSM48_MT_RR_IMM_ASS;
1255 iar->page_mode = GSM48_PM_SAME;
1256
1257 memcpy(&iar->req_ref1, &rqd_refs[0], sizeof(iar->req_ref1));
1258 iar->wait_ind1 = wait_ind;
1259
1260 if (num_req_refs >= 2)
1261 memcpy(&iar->req_ref2, &rqd_refs[1], sizeof(iar->req_ref2));
1262 else
1263 memcpy(&iar->req_ref2, &rqd_refs[0], sizeof(iar->req_ref2));
1264 iar->wait_ind2 = wait_ind;
1265
1266 if (num_req_refs >= 3)
1267 memcpy(&iar->req_ref3, &rqd_refs[2], sizeof(iar->req_ref3));
1268 else
1269 memcpy(&iar->req_ref3, &rqd_refs[0], sizeof(iar->req_ref3));
1270 iar->wait_ind3 = wait_ind;
1271
1272 if (num_req_refs >= 4)
1273 memcpy(&iar->req_ref4, &rqd_refs[3], sizeof(iar->req_ref4));
1274 else
1275 memcpy(&iar->req_ref4, &rqd_refs[0], sizeof(iar->req_ref4));
1276 iar->wait_ind4 = wait_ind;
1277
1278 return rsl_imm_assign_cmd(bts, sizeof(iar), (uint8_t *) iar);
1279}
1280
Harald Welte59b04682009-06-10 05:40:52 +08001281/* MS has requested a channel on the RACH */
1282static int rsl_rx_chan_rqd(struct msgb *msg)
1283{
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001284 struct e1inp_sign_link *sign_link = msg->dst;
1285 struct gsm_bts *bts = sign_link->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +08001286 struct abis_rsl_dchan_hdr *rqd_hdr = msgb_l2(msg);
1287 struct gsm48_req_ref *rqd_ref;
Harald Welte59b04682009-06-10 05:40:52 +08001288 enum gsm_chan_t lctype;
1289 enum gsm_chreq_reason_t chreq_reason;
1290 struct gsm_lchan *lchan;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001291 uint8_t rqd_ta;
Holger Hans Peter Freytherdb392032010-09-06 08:58:42 +08001292 int is_lu;
Harald Welte59b04682009-06-10 05:40:52 +08001293
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001294 uint16_t arfcn;
Holger Hans Peter Freytherefd75b52012-02-03 20:10:13 +01001295 uint8_t subch;
Harald Welte59b04682009-06-10 05:40:52 +08001296
1297 /* parse request reference to be used in immediate assign */
1298 if (rqd_hdr->data[0] != RSL_IE_REQ_REFERENCE)
1299 return -EINVAL;
1300
1301 rqd_ref = (struct gsm48_req_ref *) &rqd_hdr->data[1];
1302
1303 /* parse access delay and use as TA */
1304 if (rqd_hdr->data[sizeof(struct gsm48_req_ref)+1] != RSL_IE_ACCESS_DELAY)
1305 return -EINVAL;
1306 rqd_ta = rqd_hdr->data[sizeof(struct gsm48_req_ref)+2];
1307
1308 /* determine channel type (SDCCH/TCH_F/TCH_H) based on
1309 * request reference RA */
Holger Hans Peter Freytherf0f37f12010-09-06 09:36:02 +08001310 lctype = get_ctype_by_chreq(bts->network, rqd_ref->ra);
1311 chreq_reason = get_reason_by_chreq(rqd_ref->ra, bts->network->neci);
Harald Welte59b04682009-06-10 05:40:52 +08001312
Pablo Neira Ayuso1c450742011-05-06 12:13:10 +02001313 osmo_counter_inc(bts->network->stats.chreq.total);
Harald Welte3edc5a92009-12-22 00:41:05 +01001314
Holger Hans Peter Freytherdb392032010-09-06 08:58:42 +08001315 /*
1316 * We want LOCATION UPDATES to succeed and will assign a TCH
1317 * if we have no SDCCH available.
1318 */
1319 is_lu = !!(chreq_reason == GSM_CHREQ_REASON_LOCATION_UPD);
1320
Harald Welte59b04682009-06-10 05:40:52 +08001321 /* check availability / allocate channel */
Holger Hans Peter Freytherdb392032010-09-06 08:58:42 +08001322 lchan = lchan_alloc(bts, lctype, is_lu);
Harald Welte59b04682009-06-10 05:40:52 +08001323 if (!lchan) {
Harald Welte (local)e0bb5fa2009-12-27 13:48:09 +01001324 LOGP(DRSL, LOGL_NOTICE, "BTS %d CHAN RQD: no resources for %s 0x%x\n",
Harald Welte (local)02204d02009-12-27 18:05:25 +01001325 msg->lchan->ts->trx->bts->nr, gsm_lchant_name(lctype), rqd_ref->ra);
Pablo Neira Ayuso1c450742011-05-06 12:13:10 +02001326 osmo_counter_inc(bts->network->stats.chreq.no_channel);
Harald Weltea00fdd72010-12-23 14:39:29 +01001327 /* FIXME gather multiple CHAN RQD and reject up to 4 at the same time */
1328 if (bts->network->T3122)
1329 rsl_send_imm_ass_rej(bts, 1, rqd_ref, bts->network->T3122 & 0xff);
Harald Welte59b04682009-06-10 05:40:52 +08001330 return -ENOMEM;
1331 }
1332
Harald Weltec88a4432009-12-29 10:44:17 +01001333 if (lchan->state != LCHAN_S_NONE)
1334 LOGP(DRSL, LOGL_NOTICE, "%s lchan_alloc() returned channel "
Harald Welteab2534c2009-12-29 10:52:38 +01001335 "in state %s\n", gsm_lchan_name(lchan),
1336 gsm_lchans_name(lchan->state));
Harald Welte (local)c3be50c2009-12-27 18:12:29 +01001337
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001338 /* save the RACH data as we need it after the CHAN ACT ACK */
1339 lchan->rqd_ref = talloc_zero(bts, struct gsm48_req_ref);
1340 if (!lchan->rqd_ref) {
1341 LOGP(DRSL, LOGL_ERROR, "Failed to allocate gsm48_req_ref.\n");
1342 lchan_free(lchan);
1343 return -ENOMEM;
1344 }
1345
Holger Hans Peter Freyther161cec12011-12-29 23:33:04 +01001346 rsl_lchan_set_state(lchan, LCHAN_S_ACT_REQ);
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001347 memcpy(lchan->rqd_ref, rqd_ref, sizeof(*rqd_ref));
1348 lchan->rqd_ta = rqd_ta;
1349
Harald Welte59b04682009-06-10 05:40:52 +08001350 arfcn = lchan->ts->trx->arfcn;
1351 subch = lchan->nr;
1352
Harald Welted2dd9de2009-08-30 15:37:11 +09001353 lchan->encr.alg_id = RSL_ENC_ALG_A5(0); /* no encryption */
Harald Welte (local)cbd46102009-08-13 10:14:26 +02001354 lchan->ms_power = ms_pwr_ctl_lvl(bts->band, bts->ms_max_power);
Harald Welte9a229e12009-08-10 00:45:40 +02001355 lchan->bs_power = 0; /* 0dB reduction, output power = Pn */
Harald Welte39274f42009-07-29 15:41:29 +02001356 lchan->rsl_cmode = RSL_CMOD_SPD_SIGN;
Harald Welte77234e12009-08-28 23:28:28 +09001357 lchan->tch_mode = GSM48_CMODE_SIGN;
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001358
Harald Welte32951ea2011-08-10 23:26:33 +02001359 /* Start another timer or assume the BTS sends a ACK/NACK? */
1360 lchan->act_timer.cb = lchan_act_tmr_cb;
1361 lchan->act_timer.data = lchan;
1362 osmo_timer_schedule(&lchan->act_timer, 4, 0);
1363
Andreas Eversberg0f18e5e2011-12-16 17:45:37 +01001364 DEBUGP(DRSL, "%s Activating ARFCN(%u) SS(%u) lctype %s "
1365 "r=%s ra=0x%02x ta=%d\n", gsm_lchan_name(lchan), arfcn, subch,
1366 gsm_lchant_name(lchan->type), gsm_chreq_name(chreq_reason),
1367 rqd_ref->ra, rqd_ta);
1368
1369 /* BS11 requires TA shifted by 2 bits */
1370 if (bts->type == GSM_BTS_TYPE_BS11)
1371 rqd_ta <<= 2;
Harald Welteb90d7bd2009-12-17 00:31:10 +01001372 rsl_chan_activate_lchan(lchan, 0x00, rqd_ta, 0);
Harald Welte59b04682009-06-10 05:40:52 +08001373
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001374 return 0;
1375}
1376
1377static int rsl_send_imm_assignment(struct gsm_lchan *lchan)
1378{
1379 struct gsm_bts *bts = lchan->ts->trx->bts;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001380 uint8_t buf[GSM_MACBLOCK_LEN];
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001381 struct gsm48_imm_ass *ia = (struct gsm48_imm_ass *) buf;
1382
Harald Welte59b04682009-06-10 05:40:52 +08001383 /* create IMMEDIATE ASSIGN 04.08 messge */
laforgee06d5982010-06-20 15:18:46 +02001384 memset(ia, 0, sizeof(*ia));
laforge50312e82010-06-21 12:08:52 +02001385 /* we set ia->l2_plen once we know the length of the MA below */
laforgee06d5982010-06-20 15:18:46 +02001386 ia->proto_discr = GSM48_PDISC_RR;
1387 ia->msg_type = GSM48_MT_RR_IMM_ASS;
1388 ia->page_mode = GSM48_PM_SAME;
1389 gsm48_lchan2chan_desc(&ia->chan_desc, lchan);
Harald Weltea42a93f2010-06-14 22:26:10 +02001390
Harald Welte59b04682009-06-10 05:40:52 +08001391 /* use request reference extracted from CHAN_RQD */
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001392 memcpy(&ia->req_ref, lchan->rqd_ref, sizeof(ia->req_ref));
1393 ia->timing_advance = lchan->rqd_ta;
Harald Weltea42a93f2010-06-14 22:26:10 +02001394 if (!lchan->ts->hopping.enabled) {
laforgee06d5982010-06-20 15:18:46 +02001395 ia->mob_alloc_len = 0;
Harald Weltea42a93f2010-06-14 22:26:10 +02001396 } else {
laforgee06d5982010-06-20 15:18:46 +02001397 ia->mob_alloc_len = lchan->ts->hopping.ma_len;
1398 memcpy(ia->mob_alloc, lchan->ts->hopping.ma_data, ia->mob_alloc_len);
Harald Weltea42a93f2010-06-14 22:26:10 +02001399 }
Harald Welte07f32182010-06-28 18:41:27 +02001400 /* we need to subtract 1 byte from sizeof(*ia) since ia includes the l2_plen field */
1401 ia->l2_plen = GSM48_LEN2PLEN((sizeof(*ia)-1) + ia->mob_alloc_len);
Harald Welte59b04682009-06-10 05:40:52 +08001402
Harald Welte427dbc42009-08-10 00:26:10 +02001403 /* Start timer T3101 to wait for GSM48_MT_RR_PAG_RESP */
1404 lchan->T3101.cb = t3101_expired;
1405 lchan->T3101.data = lchan;
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +02001406 osmo_timer_schedule(&lchan->T3101, bts->network->T3101, 0);
Harald Welte59b04682009-06-10 05:40:52 +08001407
1408 /* send IMMEDIATE ASSIGN CMD on RSL to BTS (to send on CCCH to MS) */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001409 return rsl_imm_assign_cmd(bts, sizeof(*ia)+ia->mob_alloc_len, (uint8_t *) ia);
Harald Welte59b04682009-06-10 05:40:52 +08001410}
1411
Holger Hans Peter Freyther285af692012-02-03 20:26:25 +01001412/* current load on the CCCH */
Harald Welte59b04682009-06-10 05:40:52 +08001413static int rsl_rx_ccch_load(struct msgb *msg)
1414{
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001415 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001416 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
Holger Hans Peter Freyther285af692012-02-03 20:26:25 +01001417 struct ccch_signal_data sd;
1418
1419 sd.bts = sign_link->trx->bts;
1420 sd.rach_slot_count = -1;
1421 sd.rach_busy_count = -1;
1422 sd.rach_access_count = -1;
Harald Welte59b04682009-06-10 05:40:52 +08001423
1424 switch (rslh->data[0]) {
1425 case RSL_IE_PAGING_LOAD:
Holger Hans Peter Freyther285af692012-02-03 20:26:25 +01001426 sd.pg_buf_space = rslh->data[1] << 8 | rslh->data[2];
1427 if (is_ipaccess_bts(sign_link->trx->bts) && sd.pg_buf_space == 0xffff) {
Harald Welte008a4922010-04-19 10:24:07 +02001428 /* paging load below configured threshold, use 50 as default */
Holger Hans Peter Freyther285af692012-02-03 20:26:25 +01001429 sd.pg_buf_space = 50;
Harald Welte008a4922010-04-19 10:24:07 +02001430 }
Holger Hans Peter Freyther285af692012-02-03 20:26:25 +01001431 paging_update_buffer_space(sign_link->trx->bts, sd.pg_buf_space);
1432 osmo_signal_dispatch(SS_CCCH, S_CCCH_PAGING_LOAD, &sd);
Harald Welte59b04682009-06-10 05:40:52 +08001433 break;
1434 case RSL_IE_RACH_LOAD:
1435 if (msg->data_len >= 7) {
Holger Hans Peter Freyther285af692012-02-03 20:26:25 +01001436 sd.rach_slot_count = rslh->data[2] << 8 | rslh->data[3];
1437 sd.rach_busy_count = rslh->data[4] << 8 | rslh->data[5];
1438 sd.rach_access_count = rslh->data[6] << 8 | rslh->data[7];
1439 osmo_signal_dispatch(SS_CCCH, S_CCCH_RACH_LOAD, &sd);
Harald Welte59b04682009-06-10 05:40:52 +08001440 }
1441 break;
1442 default:
1443 break;
1444 }
1445
1446 return 0;
1447}
1448
1449static int abis_rsl_rx_cchan(struct msgb *msg)
1450{
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001451 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001452 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
1453 int rc = 0;
1454
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001455 msg->lchan = lchan_lookup(sign_link->trx, rslh->chan_nr);
Harald Welte59b04682009-06-10 05:40:52 +08001456
1457 switch (rslh->c.msg_type) {
1458 case RSL_MT_CHAN_RQD:
1459 /* MS has requested a channel on the RACH */
1460 rc = rsl_rx_chan_rqd(msg);
1461 break;
1462 case RSL_MT_CCCH_LOAD_IND:
1463 /* current load on the CCCH */
1464 rc = rsl_rx_ccch_load(msg);
1465 break;
1466 case RSL_MT_DELETE_IND:
1467 /* CCCH overloaded, IMM_ASSIGN was dropped */
1468 case RSL_MT_CBCH_LOAD_IND:
1469 /* current load on the CBCH */
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001470 LOGP(DRSL, LOGL_NOTICE, "Unimplemented Abis RSL TRX message "
1471 "type 0x%02x\n", rslh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001472 break;
1473 default:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001474 LOGP(DRSL, LOGL_NOTICE, "Unknown Abis RSL TRX message type "
1475 "0x%02x\n", rslh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001476 return -EINVAL;
1477 }
1478
1479 return rc;
1480}
1481
1482static int rsl_rx_rll_err_ind(struct msgb *msg)
1483{
1484 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001485 uint8_t *rlm_cause = rllh->data;
Harald Welte59b04682009-06-10 05:40:52 +08001486
Harald Welte (local)bd76cce2009-12-26 23:55:00 +01001487 LOGP(DRLL, LOGL_ERROR, "%s ERROR INDICATION cause=%s\n",
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001488 gsm_lchan_name(msg->lchan),
Harald Welteb30935e2010-03-25 12:13:02 +08001489 rsl_rlm_cause_name(rlm_cause[1]));
Harald Welteed9a5ab2009-08-09 13:47:35 +02001490
1491 rll_indication(msg->lchan, rllh->link_id, BSC_RLLR_IND_ERR_IND);
Harald Welte (local)bd76cce2009-12-26 23:55:00 +01001492
Holger Hans Peter Freyther27942e92010-04-17 06:48:29 +02001493 if (rlm_cause[1] == RLL_CAUSE_T200_EXPIRED) {
Pablo Neira Ayuso1c450742011-05-06 12:13:10 +02001494 osmo_counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rll_err);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +08001495 return rsl_rf_chan_release(msg->lchan, 1);
Holger Hans Peter Freyther27942e92010-04-17 06:48:29 +02001496 }
Harald Welte692f5852009-07-04 09:40:05 +02001497
Harald Welte59b04682009-06-10 05:40:52 +08001498 return 0;
1499}
1500
Holger Hans Peter Freyther65f08522010-04-08 22:39:34 +02001501static void rsl_handle_release(struct gsm_lchan *lchan)
1502{
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001503 int sapi;
Holger Hans Peter Freyther4a00c062010-05-31 21:33:15 +08001504 struct gsm_bts *bts;
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001505
1506 /* maybe we have only brought down one RLL */
Holger Hans Peter Freytherd26cbc82010-04-08 22:47:44 +02001507 if (lchan->state != LCHAN_S_REL_REQ)
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001508 return;
1509
1510 for (sapi = 0; sapi < ARRAY_SIZE(lchan->sapis); ++sapi) {
1511 if (lchan->sapis[sapi] == LCHAN_SAPI_UNUSED)
1512 continue;
Harald Welte497aa982010-12-24 12:51:07 +01001513 LOGP(DRSL, LOGL_DEBUG, "%s waiting for SAPI=%d to be released.\n",
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001514 gsm_lchan_name(lchan), sapi);
1515 return;
1516 }
1517
Holger Hans Peter Freytherd26cbc82010-04-08 22:47:44 +02001518
1519
Holger Hans Peter Freyther4a00c062010-05-31 21:33:15 +08001520 /* wait a bit to send the RF Channel Release */
1521 lchan->T3111.cb = t3111_expired;
1522 lchan->T3111.data = lchan;
1523 bts = lchan->ts->trx->bts;
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +02001524 osmo_timer_schedule(&lchan->T3111, bts->network->T3111, 0);
Holger Hans Peter Freyther65f08522010-04-08 22:39:34 +02001525}
1526
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +02001527/* ESTABLISH INDICATION, LOCATION AREA UPDATE REQUEST
Harald Welte59b04682009-06-10 05:40:52 +08001528 0x02, 0x06,
1529 0x01, 0x20,
1530 0x02, 0x00,
1531 0x0b, 0x00, 0x0f, 0x05, 0x08, ... */
1532
1533static int abis_rsl_rx_rll(struct msgb *msg)
1534{
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001535 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001536 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
1537 int rc = 0;
1538 char *ts_name;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001539 uint8_t sapi = rllh->link_id & 7;
Harald Welte59b04682009-06-10 05:40:52 +08001540
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001541 msg->lchan = lchan_lookup(sign_link->trx, rllh->chan_nr);
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001542 ts_name = gsm_lchan_name(msg->lchan);
Harald Weltede4477a2009-12-24 12:20:20 +01001543 DEBUGP(DRLL, "%s SAPI=%u ", ts_name, sapi);
Harald Welte59b04682009-06-10 05:40:52 +08001544
1545 switch (rllh->c.msg_type) {
1546 case RSL_MT_DATA_IND:
1547 DEBUGPC(DRLL, "DATA INDICATION\n");
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +02001548 if (msgb_l2len(msg) >
Harald Welte59b04682009-06-10 05:40:52 +08001549 sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) &&
1550 rllh->data[0] == RSL_IE_L3_INFO) {
1551 msg->l3h = &rllh->data[3];
Harald Welte (local)64994ce2009-08-14 11:41:12 +02001552 return gsm0408_rcvmsg(msg, rllh->link_id);
Harald Welte59b04682009-06-10 05:40:52 +08001553 }
1554 break;
1555 case RSL_MT_EST_IND:
1556 DEBUGPC(DRLL, "ESTABLISH INDICATION\n");
Harald Welte427dbc42009-08-10 00:26:10 +02001557 /* lchan is established, stop T3101 */
Holger Hans Peter Freytherd8318052009-10-28 14:23:39 +01001558 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_MS;
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +02001559 osmo_timer_del(&msg->lchan->T3101);
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +02001560 if (msgb_l2len(msg) >
Harald Welte59b04682009-06-10 05:40:52 +08001561 sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) &&
1562 rllh->data[0] == RSL_IE_L3_INFO) {
1563 msg->l3h = &rllh->data[3];
Harald Welte (local)64994ce2009-08-14 11:41:12 +02001564 return gsm0408_rcvmsg(msg, rllh->link_id);
Harald Welte59b04682009-06-10 05:40:52 +08001565 }
1566 break;
Harald Welteed9a5ab2009-08-09 13:47:35 +02001567 case RSL_MT_EST_CONF:
Harald Welte61402172009-08-09 14:13:58 +02001568 DEBUGPC(DRLL, "ESTABLISH CONFIRM\n");
Holger Hans Peter Freytherd8318052009-10-28 14:23:39 +01001569 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_NET;
Harald Welteed9a5ab2009-08-09 13:47:35 +02001570 rll_indication(msg->lchan, rllh->link_id,
1571 BSC_RLLR_IND_EST_CONF);
1572 break;
Harald Welte59b04682009-06-10 05:40:52 +08001573 case RSL_MT_REL_IND:
Harald Welte0f2e3c12009-08-08 13:15:07 +02001574 /* BTS informs us of having received DISC from MS */
Harald Welteb6601442009-08-04 02:50:21 +02001575 DEBUGPC(DRLL, "RELEASE INDICATION\n");
Holger Hans Peter Freytherd8318052009-10-28 14:23:39 +01001576 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_UNUSED;
Harald Welteed9a5ab2009-08-09 13:47:35 +02001577 rll_indication(msg->lchan, rllh->link_id,
1578 BSC_RLLR_IND_REL_IND);
Holger Hans Peter Freyther65f08522010-04-08 22:39:34 +02001579 rsl_handle_release(msg->lchan);
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001580 rsl_lchan_rll_release(msg->lchan, rllh->link_id);
Harald Welte59b04682009-06-10 05:40:52 +08001581 break;
1582 case RSL_MT_REL_CONF:
Harald Welte0f2e3c12009-08-08 13:15:07 +02001583 /* BTS informs us of having received UA from MS,
1584 * in response to DISC that we've sent earlier */
Harald Welteb6601442009-08-04 02:50:21 +02001585 DEBUGPC(DRLL, "RELEASE CONFIRMATION\n");
Holger Hans Peter Freytherd8318052009-10-28 14:23:39 +01001586 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_UNUSED;
Holger Hans Peter Freyther65f08522010-04-08 22:39:34 +02001587 rsl_handle_release(msg->lchan);
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001588 rsl_lchan_rll_release(msg->lchan, rllh->link_id);
Harald Welte59b04682009-06-10 05:40:52 +08001589 break;
1590 case RSL_MT_ERROR_IND:
Harald Welte59b04682009-06-10 05:40:52 +08001591 rc = rsl_rx_rll_err_ind(msg);
1592 break;
1593 case RSL_MT_UNIT_DATA_IND:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001594 LOGP(DRLL, LOGL_NOTICE, "unimplemented Abis RLL message "
1595 "type 0x%02x\n", rllh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001596 break;
1597 default:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001598 LOGP(DRLL, LOGL_NOTICE, "unknown Abis RLL message "
1599 "type 0x%02x\n", rllh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001600 }
Harald Welte59b04682009-06-10 05:40:52 +08001601 return rc;
1602}
1603
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001604static uint8_t ipa_smod_s_for_lchan(struct gsm_lchan *lchan)
Harald Welte98d79f92009-07-28 18:11:56 +02001605{
Harald Welteb284b472009-12-02 01:58:23 +05301606 switch (lchan->tch_mode) {
Harald Welte98d79f92009-07-28 18:11:56 +02001607 case GSM48_CMODE_SPEECH_V1:
Harald Welteb284b472009-12-02 01:58:23 +05301608 switch (lchan->type) {
1609 case GSM_LCHAN_TCH_F:
1610 return 0x00;
1611 case GSM_LCHAN_TCH_H:
1612 return 0x03;
1613 default:
1614 break;
1615 }
Harald Welte98d79f92009-07-28 18:11:56 +02001616 case GSM48_CMODE_SPEECH_EFR:
Harald Welteb284b472009-12-02 01:58:23 +05301617 switch (lchan->type) {
1618 case GSM_LCHAN_TCH_F:
1619 return 0x01;
1620 /* there's no half-rate EFR */
1621 default:
1622 break;
1623 }
Harald Welte98d79f92009-07-28 18:11:56 +02001624 case GSM48_CMODE_SPEECH_AMR:
Harald Welteb284b472009-12-02 01:58:23 +05301625 switch (lchan->type) {
1626 case GSM_LCHAN_TCH_F:
1627 return 0x02;
1628 case GSM_LCHAN_TCH_H:
1629 return 0x05;
1630 default:
1631 break;
1632 }
1633 default:
1634 break;
Harald Welte98d79f92009-07-28 18:11:56 +02001635 }
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001636 LOGP(DRSL, LOGL_ERROR, "Cannot determine ip.access speech mode for "
Harald Welteb284b472009-12-02 01:58:23 +05301637 "tch_mode == 0x%02x\n", lchan->tch_mode);
Harald Welte98d79f92009-07-28 18:11:56 +02001638 return 0;
Harald Welte98d79f92009-07-28 18:11:56 +02001639}
1640
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001641static uint8_t ipa_rtp_pt_for_lchan(struct gsm_lchan *lchan)
Sylvain Munaut1338a552009-12-20 22:06:40 +01001642{
1643 switch (lchan->tch_mode) {
1644 case GSM48_CMODE_SPEECH_V1:
1645 switch (lchan->type) {
1646 case GSM_LCHAN_TCH_F:
1647 return RTP_PT_GSM_FULL;
1648 case GSM_LCHAN_TCH_H:
1649 return RTP_PT_GSM_HALF;
1650 default:
1651 break;
1652 }
1653 case GSM48_CMODE_SPEECH_EFR:
1654 switch (lchan->type) {
1655 case GSM_LCHAN_TCH_F:
1656 return RTP_PT_GSM_EFR;
1657 /* there's no half-rate EFR */
1658 default:
1659 break;
1660 }
1661 case GSM48_CMODE_SPEECH_AMR:
1662 switch (lchan->type) {
1663 case GSM_LCHAN_TCH_F:
Sylvain Munaut1338a552009-12-20 22:06:40 +01001664 case GSM_LCHAN_TCH_H:
Holger Hans Peter Freytherd78bee82011-07-21 10:24:46 +02001665 return RTP_PT_AMR;
Sylvain Munaut1338a552009-12-20 22:06:40 +01001666 default:
1667 break;
1668 }
1669 default:
1670 break;
1671 }
1672 LOGP(DRSL, LOGL_ERROR, "Cannot determine ip.access rtp payload type for "
1673 "tch_mode == 0x%02x\n & lchan_type == %d",
1674 lchan->tch_mode, lchan->type);
1675 return 0;
1676}
1677
Harald Welte59b04682009-06-10 05:40:52 +08001678/* ip.access specific RSL extensions */
Harald Weltebffa4992009-12-19 16:42:06 +01001679static void ipac_parse_rtp(struct gsm_lchan *lchan, struct tlv_parsed *tv)
1680{
1681 struct in_addr ip;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001682 uint16_t port, conn_id;
Harald Weltebffa4992009-12-19 16:42:06 +01001683
1684 if (TLVP_PRESENT(tv, RSL_IE_IPAC_LOCAL_IP)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001685 ip.s_addr = *((uint32_t *) TLVP_VAL(tv, RSL_IE_IPAC_LOCAL_IP));
Harald Weltebffa4992009-12-19 16:42:06 +01001686 DEBUGPC(DRSL, "LOCAL_IP=%s ", inet_ntoa(ip));
1687 lchan->abis_ip.bound_ip = ntohl(ip.s_addr);
1688 }
1689
1690 if (TLVP_PRESENT(tv, RSL_IE_IPAC_LOCAL_PORT)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001691 port = *((uint16_t *) TLVP_VAL(tv, RSL_IE_IPAC_LOCAL_PORT));
Harald Weltebffa4992009-12-19 16:42:06 +01001692 port = ntohs(port);
1693 DEBUGPC(DRSL, "LOCAL_PORT=%u ", port);
1694 lchan->abis_ip.bound_port = port;
1695 }
1696
1697 if (TLVP_PRESENT(tv, RSL_IE_IPAC_CONN_ID)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001698 conn_id = *((uint16_t *) TLVP_VAL(tv, RSL_IE_IPAC_CONN_ID));
Harald Weltebffa4992009-12-19 16:42:06 +01001699 conn_id = ntohs(conn_id);
1700 DEBUGPC(DRSL, "CON_ID=%u ", conn_id);
1701 lchan->abis_ip.conn_id = conn_id;
1702 }
1703
1704 if (TLVP_PRESENT(tv, RSL_IE_IPAC_RTP_PAYLOAD2)) {
1705 lchan->abis_ip.rtp_payload2 =
1706 *TLVP_VAL(tv, RSL_IE_IPAC_RTP_PAYLOAD2);
1707 DEBUGPC(DRSL, "RTP_PAYLOAD2=0x%02x ",
1708 lchan->abis_ip.rtp_payload2);
1709 }
1710
1711 if (TLVP_PRESENT(tv, RSL_IE_IPAC_SPEECH_MODE)) {
1712 lchan->abis_ip.speech_mode =
1713 *TLVP_VAL(tv, RSL_IE_IPAC_SPEECH_MODE);
1714 DEBUGPC(DRSL, "speech_mode=0x%02x ",
1715 lchan->abis_ip.speech_mode);
1716 }
1717
1718 if (TLVP_PRESENT(tv, RSL_IE_IPAC_REMOTE_IP)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001719 ip.s_addr = *((uint32_t *) TLVP_VAL(tv, RSL_IE_IPAC_REMOTE_IP));
Harald Weltebffa4992009-12-19 16:42:06 +01001720 DEBUGPC(DRSL, "REMOTE_IP=%s ", inet_ntoa(ip));
1721 lchan->abis_ip.connect_ip = ntohl(ip.s_addr);
1722 }
1723
1724 if (TLVP_PRESENT(tv, RSL_IE_IPAC_REMOTE_PORT)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001725 port = *((uint16_t *) TLVP_VAL(tv, RSL_IE_IPAC_REMOTE_PORT));
Harald Weltebffa4992009-12-19 16:42:06 +01001726 port = ntohs(port);
1727 DEBUGPC(DRSL, "REMOTE_PORT=%u ", port);
1728 lchan->abis_ip.connect_port = port;
1729 }
1730}
1731
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001732int rsl_ipacc_crcx(struct gsm_lchan *lchan)
Harald Welte59b04682009-06-10 05:40:52 +08001733{
1734 struct msgb *msg = rsl_msgb_alloc();
1735 struct abis_rsl_dchan_hdr *dh;
1736
1737 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001738 init_dchan_hdr(dh, RSL_MT_IPAC_CRCX);
Harald Welte59b04682009-06-10 05:40:52 +08001739 dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
Harald Weltee6d51f92011-06-25 10:02:33 +02001740 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001741
Harald Welte98d79f92009-07-28 18:11:56 +02001742 /* 0x1- == receive-only, 0x-1 == EFR codec */
Harald Weltebffa4992009-12-19 16:42:06 +01001743 lchan->abis_ip.speech_mode = 0x10 | ipa_smod_s_for_lchan(lchan);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001744 lchan->abis_ip.rtp_payload = ipa_rtp_pt_for_lchan(lchan);
Harald Weltebffa4992009-12-19 16:42:06 +01001745 msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, lchan->abis_ip.speech_mode);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001746 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD, lchan->abis_ip.rtp_payload);
Harald Welte98d79f92009-07-28 18:11:56 +02001747
Sylvain Munaut1338a552009-12-20 22:06:40 +01001748 DEBUGP(DRSL, "%s IPAC_BIND speech_mode=0x%02x RTP_PAYLOAD=%d\n",
1749 gsm_lchan_name(lchan), lchan->abis_ip.speech_mode,
1750 lchan->abis_ip.rtp_payload);
Harald Welte98d79f92009-07-28 18:11:56 +02001751
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001752 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +08001753
1754 return abis_rsl_sendmsg(msg);
1755}
1756
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001757int rsl_ipacc_mdcx(struct gsm_lchan *lchan, uint32_t ip, uint16_t port,
1758 uint8_t rtp_payload2)
Harald Welte59b04682009-06-10 05:40:52 +08001759{
1760 struct msgb *msg = rsl_msgb_alloc();
1761 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001762 uint32_t *att_ip;
Harald Welte98d79f92009-07-28 18:11:56 +02001763 struct in_addr ia;
Harald Welte59b04682009-06-10 05:40:52 +08001764
1765 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001766 init_dchan_hdr(dh, RSL_MT_IPAC_MDCX);
Harald Welte59b04682009-06-10 05:40:52 +08001767 dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
Harald Weltee6d51f92011-06-25 10:02:33 +02001768 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001769
Harald Weltebffa4992009-12-19 16:42:06 +01001770 /* we need to store these now as MDCX_ACK does not return them :( */
1771 lchan->abis_ip.rtp_payload2 = rtp_payload2;
1772 lchan->abis_ip.connect_port = port;
1773 lchan->abis_ip.connect_ip = ip;
1774
Harald Weltefb4a9e92009-07-29 12:12:18 +02001775 /* 0x0- == both directions, 0x-1 == EFR codec */
Harald Weltebffa4992009-12-19 16:42:06 +01001776 lchan->abis_ip.speech_mode = 0x00 | ipa_smod_s_for_lchan(lchan);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001777 lchan->abis_ip.rtp_payload = ipa_rtp_pt_for_lchan(lchan);
Harald Weltefb4a9e92009-07-29 12:12:18 +02001778
Harald Welte98d79f92009-07-28 18:11:56 +02001779 ia.s_addr = htonl(ip);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001780 DEBUGP(DRSL, "%s IPAC_MDCX IP=%s PORT=%d RTP_PAYLOAD=%d RTP_PAYLOAD2=%d "
1781 "CONN_ID=%d speech_mode=0x%02x\n", gsm_lchan_name(lchan),
1782 inet_ntoa(ia), port, lchan->abis_ip.rtp_payload, rtp_payload2,
1783 lchan->abis_ip.conn_id, lchan->abis_ip.speech_mode);
Harald Welte98d79f92009-07-28 18:11:56 +02001784
Harald Weltebffa4992009-12-19 16:42:06 +01001785 msgb_tv16_put(msg, RSL_IE_IPAC_CONN_ID, lchan->abis_ip.conn_id);
1786 msgb_v_put(msg, RSL_IE_IPAC_REMOTE_IP);
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001787 att_ip = (uint32_t *) msgb_put(msg, sizeof(ip));
Harald Weltebffa4992009-12-19 16:42:06 +01001788 *att_ip = ia.s_addr;
1789 msgb_tv16_put(msg, RSL_IE_IPAC_REMOTE_PORT, port);
1790 msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, lchan->abis_ip.speech_mode);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001791 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD, lchan->abis_ip.rtp_payload);
Harald Welte98d79f92009-07-28 18:11:56 +02001792 if (rtp_payload2)
1793 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD2, rtp_payload2);
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001794
1795 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +08001796
1797 return abis_rsl_sendmsg(msg);
1798}
1799
Harald Welte9947d9f2009-12-20 16:51:09 +01001800/* tell BTS to connect RTP stream to our local RTP socket */
1801int rsl_ipacc_mdcx_to_rtpsock(struct gsm_lchan *lchan)
1802{
1803 struct rtp_socket *rs = lchan->abis_ip.rtp_socket;
1804 int rc;
1805
1806 rc = rsl_ipacc_mdcx(lchan, ntohl(rs->rtp.sin_local.sin_addr.s_addr),
1807 ntohs(rs->rtp.sin_local.sin_port),
1808 /* FIXME: use RTP payload of bound socket, not BTS*/
1809 lchan->abis_ip.rtp_payload2);
1810
1811 return rc;
1812}
1813
Harald Welte6f40df02010-12-23 12:59:52 +01001814int rsl_ipacc_pdch_activate(struct gsm_bts_trx_ts *ts, int act)
Harald Welteaed946e2009-10-24 10:29:22 +02001815{
1816 struct msgb *msg = rsl_msgb_alloc();
1817 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001818 uint8_t msg_type;
Harald Welte2b361522010-03-28 14:42:09 +08001819
1820 if (act)
1821 msg_type = RSL_MT_IPAC_PDCH_ACT;
1822 else
1823 msg_type = RSL_MT_IPAC_PDCH_DEACT;
Harald Welteaed946e2009-10-24 10:29:22 +02001824
1825 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Harald Welte2b361522010-03-28 14:42:09 +08001826 init_dchan_hdr(dh, msg_type);
Harald Welteaed946e2009-10-24 10:29:22 +02001827 dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
Harald Weltee6d51f92011-06-25 10:02:33 +02001828 dh->chan_nr = gsm_ts2chan_nr(ts, 0);
Harald Welteaed946e2009-10-24 10:29:22 +02001829
Harald Welte6f40df02010-12-23 12:59:52 +01001830 DEBUGP(DRSL, "%s IPAC_PDCH_%sACT\n", gsm_ts_name(ts),
Harald Welte2b361522010-03-28 14:42:09 +08001831 act ? "" : "DE");
Harald Welteaed946e2009-10-24 10:29:22 +02001832
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001833 msg->dst = ts->trx->rsl_link;
Harald Welteaed946e2009-10-24 10:29:22 +02001834
1835 return abis_rsl_sendmsg(msg);
1836}
1837
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001838static int abis_rsl_rx_ipacc_crcx_ack(struct msgb *msg)
Harald Welte59b04682009-06-10 05:40:52 +08001839{
1840 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1841 struct tlv_parsed tv;
Harald Welte87504212009-12-02 01:56:49 +05301842 struct gsm_lchan *lchan = msg->lchan;
Harald Welte59b04682009-06-10 05:40:52 +08001843
1844 /* the BTS has acknowledged a local bind, it now tells us the IP
1845 * address and port number to which it has bound the given logical
1846 * channel */
1847
1848 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
1849 if (!TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_PORT) ||
1850 !TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_IP) ||
Harald Welteb9498952009-07-12 09:45:05 +02001851 !TLVP_PRESENT(&tv, RSL_IE_IPAC_CONN_ID)) {
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001852 LOGP(DRSL, LOGL_NOTICE, "mandatory IE missing");
Harald Welte59b04682009-06-10 05:40:52 +08001853 return -EINVAL;
1854 }
Harald Welte50517742009-12-20 15:42:44 +01001855
Harald Weltebffa4992009-12-19 16:42:06 +01001856 ipac_parse_rtp(lchan, &tv);
Harald Welte50517742009-12-20 15:42:44 +01001857
Pablo Neira Ayusoef717c62011-05-06 12:12:31 +02001858 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_CRCX_ACK, msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001859
1860 return 0;
1861}
1862
Harald Weltebffa4992009-12-19 16:42:06 +01001863static int abis_rsl_rx_ipacc_mdcx_ack(struct msgb *msg)
1864{
1865 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1866 struct tlv_parsed tv;
1867 struct gsm_lchan *lchan = msg->lchan;
1868
1869 /* the BTS has acknowledged a remote connect request and
1870 * it now tells us the IP address and port number to which it has
1871 * connected the given logical channel */
1872
1873 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
1874 ipac_parse_rtp(lchan, &tv);
Pablo Neira Ayusoef717c62011-05-06 12:12:31 +02001875 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_MDCX_ACK, msg->lchan);
Harald Weltebffa4992009-12-19 16:42:06 +01001876
1877 return 0;
1878}
1879
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001880static int abis_rsl_rx_ipacc_dlcx_ind(struct msgb *msg)
Harald Welte59b04682009-06-10 05:40:52 +08001881{
1882 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1883 struct tlv_parsed tv;
1884
1885 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
Harald Welte59b04682009-06-10 05:40:52 +08001886
Harald Weltef1a168d2009-07-28 17:58:09 +02001887 if (TLVP_PRESENT(&tv, RSL_IE_CAUSE))
Harald Weltede4477a2009-12-24 12:20:20 +01001888 print_rsl_cause(LOGL_DEBUG, TLVP_VAL(&tv, RSL_IE_CAUSE),
Harald Weltef1a168d2009-07-28 17:58:09 +02001889 TLVP_LEN(&tv, RSL_IE_CAUSE));
Harald Welte59b04682009-06-10 05:40:52 +08001890
Pablo Neira Ayusoef717c62011-05-06 12:12:31 +02001891 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_DLCX_IND, msg->lchan);
Harald Welteba4e58d2009-07-28 18:02:05 +02001892
Harald Welte59b04682009-06-10 05:40:52 +08001893 return 0;
1894}
1895
1896static int abis_rsl_rx_ipacc(struct msgb *msg)
1897{
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001898 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001899 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
Harald Weltede4477a2009-12-24 12:20:20 +01001900 char *ts_name;
Harald Welte59b04682009-06-10 05:40:52 +08001901 int rc = 0;
1902
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001903 msg->lchan = lchan_lookup(sign_link->trx, rllh->chan_nr);
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001904 ts_name = gsm_lchan_name(msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001905
1906 switch (rllh->c.msg_type) {
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001907 case RSL_MT_IPAC_CRCX_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001908 DEBUGP(DRSL, "%s IPAC_CRCX_ACK ", ts_name);
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001909 rc = abis_rsl_rx_ipacc_crcx_ack(msg);
Harald Welte59b04682009-06-10 05:40:52 +08001910 break;
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001911 case RSL_MT_IPAC_CRCX_NACK:
Harald Welte59b04682009-06-10 05:40:52 +08001912 /* somehow the BTS was unable to bind the lchan to its local
1913 * port?!? */
Harald Weltede4477a2009-12-24 12:20:20 +01001914 LOGP(DRSL, LOGL_ERROR, "%s IPAC_CRCX_NACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001915 break;
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001916 case RSL_MT_IPAC_MDCX_ACK:
Harald Welte59b04682009-06-10 05:40:52 +08001917 /* the BTS tells us that a connect operation was successful */
Harald Weltede4477a2009-12-24 12:20:20 +01001918 DEBUGP(DRSL, "%s IPAC_MDCX_ACK ", ts_name);
Harald Weltebffa4992009-12-19 16:42:06 +01001919 rc = abis_rsl_rx_ipacc_mdcx_ack(msg);
Harald Welte59b04682009-06-10 05:40:52 +08001920 break;
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001921 case RSL_MT_IPAC_MDCX_NACK:
Harald Welte59b04682009-06-10 05:40:52 +08001922 /* somehow the BTS was unable to connect the lchan to a remote
1923 * port */
Harald Weltede4477a2009-12-24 12:20:20 +01001924 LOGP(DRSL, LOGL_ERROR, "%s IPAC_MDCX_NACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001925 break;
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001926 case RSL_MT_IPAC_DLCX_IND:
Harald Weltede4477a2009-12-24 12:20:20 +01001927 DEBUGP(DRSL, "%s IPAC_DLCX_IND ", ts_name);
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001928 rc = abis_rsl_rx_ipacc_dlcx_ind(msg);
Harald Welte59b04682009-06-10 05:40:52 +08001929 break;
1930 default:
Harald Weltede4477a2009-12-24 12:20:20 +01001931 LOGP(DRSL, LOGL_NOTICE, "Unknown ip.access msg_type 0x%02x\n",
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001932 rllh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001933 break;
1934 }
1935 DEBUGPC(DRSL, "\n");
1936
1937 return rc;
1938}
1939
1940
1941/* Entry-point where L2 RSL from BTS enters */
1942int abis_rsl_rcvmsg(struct msgb *msg)
1943{
Holger Hans Peter Freytherc7d94092009-11-20 15:14:01 +01001944 struct abis_rsl_common_hdr *rslh;
Harald Welte59b04682009-06-10 05:40:52 +08001945 int rc = 0;
1946
Holger Hans Peter Freytherc7d94092009-11-20 15:14:01 +01001947 if (!msg) {
1948 DEBUGP(DRSL, "Empty RSL msg?..\n");
1949 return -1;
1950 }
1951
1952 if (msgb_l2len(msg) < sizeof(*rslh)) {
1953 DEBUGP(DRSL, "Truncated RSL message with l2len: %u\n", msgb_l2len(msg));
Harald Weltece807262012-05-31 20:22:34 +02001954 msgb_free(msg);
Holger Hans Peter Freytherc7d94092009-11-20 15:14:01 +01001955 return -1;
1956 }
1957
1958 rslh = msgb_l2(msg);
1959
Harald Welte59b04682009-06-10 05:40:52 +08001960 switch (rslh->msg_discr & 0xfe) {
1961 case ABIS_RSL_MDISC_RLL:
1962 rc = abis_rsl_rx_rll(msg);
1963 break;
1964 case ABIS_RSL_MDISC_DED_CHAN:
1965 rc = abis_rsl_rx_dchan(msg);
1966 break;
1967 case ABIS_RSL_MDISC_COM_CHAN:
1968 rc = abis_rsl_rx_cchan(msg);
1969 break;
1970 case ABIS_RSL_MDISC_TRX:
1971 rc = abis_rsl_rx_trx(msg);
1972 break;
1973 case ABIS_RSL_MDISC_LOC:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001974 LOGP(DRSL, LOGL_NOTICE, "unimplemented RSL msg disc 0x%02x\n",
Harald Welte59b04682009-06-10 05:40:52 +08001975 rslh->msg_discr);
1976 break;
1977 case ABIS_RSL_MDISC_IPACCESS:
1978 rc = abis_rsl_rx_ipacc(msg);
1979 break;
1980 default:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001981 LOGP(DRSL, LOGL_NOTICE, "unknown RSL message discriminator "
1982 "0x%02x\n", rslh->msg_discr);
Harald Weltece807262012-05-31 20:22:34 +02001983 rc = -EINVAL;
Harald Welte59b04682009-06-10 05:40:52 +08001984 }
1985 msgb_free(msg);
1986 return rc;
1987}
1988
Holger Hans Peter Freytherb67f4082010-07-21 15:54:32 +08001989int rsl_sms_cb_command(struct gsm_bts *bts, uint8_t chan_number,
1990 uint8_t cb_command, const uint8_t *data, int len)
1991{
1992 struct abis_rsl_dchan_hdr *dh;
1993 struct msgb *cb_cmd;
1994
1995 cb_cmd = rsl_msgb_alloc();
1996 if (!cb_cmd)
1997 return -1;
1998
1999 dh = (struct abis_rsl_dchan_hdr *) msgb_put(cb_cmd, sizeof*dh);
2000 init_dchan_hdr(dh, RSL_MT_SMS_BC_CMD);
2001 dh->chan_nr = RSL_CHAN_SDCCH4_ACCH; /* TODO: check the chan config */
2002
2003 msgb_tv_put(cb_cmd, RSL_IE_CB_CMD_TYPE, cb_command);
2004 msgb_tlv_put(cb_cmd, RSL_IE_SMSCB_MSG, len, data);
2005
2006 cb_cmd->trx = bts->c0;
2007
2008 return abis_rsl_sendmsg(cb_cmd);
2009}
Dieter Spaar49c843e2011-07-28 00:01:50 +02002010
2011int rsl_nokia_si_begin(struct gsm_bts_trx *trx)
2012{
2013 struct abis_rsl_common_hdr *ch;
2014 struct msgb *msg = rsl_msgb_alloc();
2015
2016 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
2017 ch->msg_discr = ABIS_RSL_MDISC_TRX;
2018 ch->msg_type = 0x40; /* Nokia SI Begin */
2019
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02002020 msg->dst = trx->rsl_link;
Dieter Spaar49c843e2011-07-28 00:01:50 +02002021
2022 return abis_rsl_sendmsg(msg);
2023}
2024
2025int rsl_nokia_si_end(struct gsm_bts_trx *trx)
2026{
2027 struct abis_rsl_common_hdr *ch;
2028 struct msgb *msg = rsl_msgb_alloc();
2029
2030 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
2031 ch->msg_discr = ABIS_RSL_MDISC_TRX;
2032 ch->msg_type = 0x41; /* Nokia SI End */
2033
2034 msgb_tv_put(msg, 0xFD, 0x00); /* Nokia Pagemode Info, No paging reorganisation required */
2035
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02002036 msg->dst = trx->rsl_link;
Dieter Spaar49c843e2011-07-28 00:01:50 +02002037
2038 return abis_rsl_sendmsg(msg);
2039}
2040
2041int rsl_bs_power_control(struct gsm_bts_trx *trx, uint8_t channel, uint8_t reduction)
2042{
2043 struct abis_rsl_common_hdr *ch;
2044 struct msgb *msg = rsl_msgb_alloc();
2045
2046 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
2047 ch->msg_discr = ABIS_RSL_MDISC_DED_CHAN;
2048 ch->msg_type = RSL_MT_BS_POWER_CONTROL;
2049
2050 msgb_tv_put(msg, RSL_IE_CHAN_NR, channel);
2051 msgb_tv_put(msg, RSL_IE_BS_POWER, reduction); /* reduction in 2dB steps */
2052
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02002053 msg->dst = trx->rsl_link;
Dieter Spaar49c843e2011-07-28 00:01:50 +02002054
2055 return abis_rsl_sendmsg(msg);
2056}