blob: d74907b0a3ae59ffbd2b7d82f776c71af9c3dee3 [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 Ayusodd5fff42011-03-22 16:47:59 +010041#include <osmocom/gsm/rsl.h>
Harald Welte59b04682009-06-10 05:40:52 +080042
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
181/* Send a BCCH_INFO message as per Chapter 8.5.1 */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200182int rsl_bcch_info(struct gsm_bts_trx *trx, uint8_t type,
183 const uint8_t *data, int len)
Harald Welte59b04682009-06-10 05:40:52 +0800184{
185 struct abis_rsl_dchan_hdr *dh;
186 struct msgb *msg = rsl_msgb_alloc();
187
188 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof*dh);
189 init_dchan_hdr(dh, RSL_MT_BCCH_INFO);
190 dh->chan_nr = RSL_CHAN_BCCH;
191
192 msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
193 msgb_tlv_put(msg, RSL_IE_FULL_BCCH_INFO, len, data);
194
195 msg->trx = trx;
196
197 return abis_rsl_sendmsg(msg);
198}
199
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200200int rsl_sacch_filling(struct gsm_bts_trx *trx, uint8_t type,
201 const uint8_t *data, int len)
Harald Welte59b04682009-06-10 05:40:52 +0800202{
203 struct abis_rsl_common_hdr *ch;
204 struct msgb *msg = rsl_msgb_alloc();
205
206 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
207 ch->msg_discr = ABIS_RSL_MDISC_TRX;
208 ch->msg_type = RSL_MT_SACCH_FILL;
209
210 msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
211 msgb_tl16v_put(msg, RSL_IE_L3_INFO, len, data);
212
213 msg->trx = trx;
214
215 return abis_rsl_sendmsg(msg);
216}
217
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200218int rsl_sacch_info_modify(struct gsm_lchan *lchan, uint8_t type,
219 const uint8_t *data, int len)
Harald Welte10b7d8f2011-01-13 23:16:03 +0100220{
221 struct abis_rsl_dchan_hdr *dh;
222 struct msgb *msg = rsl_msgb_alloc();
Harald Weltee6d51f92011-06-25 10:02:33 +0200223 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte10b7d8f2011-01-13 23:16:03 +0100224
225 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
226 init_dchan_hdr(dh, RSL_MT_SACCH_INFO_MODIFY);
227 dh->chan_nr = chan_nr;
228
229 msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
230 msgb_tl16v_put(msg, RSL_IE_L3_INFO, len, data);
231
232 msg->trx = lchan->ts->trx;
233
234 return abis_rsl_sendmsg(msg);
235}
236
Harald Welte91afe4c2009-06-20 18:15:19 +0200237int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db)
238{
239 struct abis_rsl_dchan_hdr *dh;
Harald Welteed831842009-06-27 03:09:08 +0200240 struct msgb *msg;
Harald Weltee6d51f92011-06-25 10:02:33 +0200241 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte91afe4c2009-06-20 18:15:19 +0200242
243 db = abs(db);
244 if (db > 30)
245 return -EINVAL;
246
Harald Welteed831842009-06-27 03:09:08 +0200247 msg = rsl_msgb_alloc();
248
Harald Welte91afe4c2009-06-20 18:15:19 +0200249 lchan->bs_power = db/2;
250 if (fpc)
251 lchan->bs_power |= 0x10;
252
253 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
254 init_dchan_hdr(dh, RSL_MT_BS_POWER_CONTROL);
255 dh->chan_nr = chan_nr;
256
257 msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power);
258
259 msg->trx = lchan->ts->trx;
260
261 return abis_rsl_sendmsg(msg);
262}
263
Harald Welte91afe4c2009-06-20 18:15:19 +0200264int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm)
265{
266 struct abis_rsl_dchan_hdr *dh;
Harald Welteed831842009-06-27 03:09:08 +0200267 struct msgb *msg;
Harald Weltee6d51f92011-06-25 10:02:33 +0200268 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte91afe4c2009-06-20 18:15:19 +0200269 int ctl_lvl;
270
Harald Weltec4dcda02009-08-09 14:45:18 +0200271 ctl_lvl = ms_pwr_ctl_lvl(lchan->ts->trx->bts->band, dbm);
Harald Welte91afe4c2009-06-20 18:15:19 +0200272 if (ctl_lvl < 0)
273 return ctl_lvl;
274
Harald Welteed831842009-06-27 03:09:08 +0200275 msg = rsl_msgb_alloc();
276
Harald Welte91afe4c2009-06-20 18:15:19 +0200277 lchan->ms_power = ctl_lvl;
278
279 if (fpc)
280 lchan->ms_power |= 0x20;
281
282 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
283 init_dchan_hdr(dh, RSL_MT_MS_POWER_CONTROL);
284 dh->chan_nr = chan_nr;
285
286 msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power);
287
288 msg->trx = lchan->ts->trx;
289
290 return abis_rsl_sendmsg(msg);
291}
292
Harald Welte39274f42009-07-29 15:41:29 +0200293static int channel_mode_from_lchan(struct rsl_ie_chan_mode *cm,
294 struct gsm_lchan *lchan)
295{
296 memset(cm, 0, sizeof(cm));
297
298 /* FIXME: what to do with data calls ? */
Holger Hans Peter Freyther21d63ff2010-09-06 09:25:48 +0800299 if (lchan->ts->trx->bts->network->dtx_enabled)
300 cm->dtx_dtu = 0x03;
301 else
302 cm->dtx_dtu = 0x00;
Harald Welte39274f42009-07-29 15:41:29 +0200303
304 /* set TCH Speech/Data */
305 cm->spd_ind = lchan->rsl_cmode;
306
Harald Welte951e3512009-11-27 08:55:16 +0100307 if (lchan->rsl_cmode == RSL_CMOD_SPD_SIGN &&
308 lchan->tch_mode != GSM48_CMODE_SIGN)
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100309 LOGP(DRSL, LOGL_ERROR, "unsupported: rsl_mode == signalling, "
Harald Welte951e3512009-11-27 08:55:16 +0100310 "but tch_mode != signalling\n");
311
Harald Welte39274f42009-07-29 15:41:29 +0200312 switch (lchan->type) {
313 case GSM_LCHAN_SDCCH:
314 cm->chan_rt = RSL_CMOD_CRT_SDCCH;
315 break;
316 case GSM_LCHAN_TCH_F:
317 cm->chan_rt = RSL_CMOD_CRT_TCH_Bm;
318 break;
319 case GSM_LCHAN_TCH_H:
320 cm->chan_rt = RSL_CMOD_CRT_TCH_Lm;
321 break;
322 case GSM_LCHAN_NONE:
323 case GSM_LCHAN_UNKNOWN:
324 default:
325 return -EINVAL;
326 }
327
328 switch (lchan->tch_mode) {
329 case GSM48_CMODE_SIGN:
330 cm->chan_rate = 0;
331 break;
332 case GSM48_CMODE_SPEECH_V1:
333 cm->chan_rate = RSL_CMOD_SP_GSM1;
334 break;
335 case GSM48_CMODE_SPEECH_EFR:
336 cm->chan_rate = RSL_CMOD_SP_GSM2;
337 break;
338 case GSM48_CMODE_SPEECH_AMR:
339 cm->chan_rate = RSL_CMOD_SP_GSM3;
340 break;
341 case GSM48_CMODE_DATA_14k5:
342 cm->chan_rate = RSL_CMOD_SP_NT_14k5;
343 break;
344 case GSM48_CMODE_DATA_12k0:
345 cm->chan_rate = RSL_CMOD_SP_NT_12k0;
346 break;
347 case GSM48_CMODE_DATA_6k0:
348 cm->chan_rate = RSL_CMOD_SP_NT_6k0;
349 break;
350 default:
351 return -EINVAL;
352 }
353
354 return 0;
355}
356
Harald Welte59b04682009-06-10 05:40:52 +0800357/* Chapter 8.4.1 */
358#if 0
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200359int rsl_chan_activate(struct gsm_bts_trx *trx, uint8_t chan_nr,
360 uint8_t act_type,
Harald Welte59b04682009-06-10 05:40:52 +0800361 struct rsl_ie_chan_mode *chan_mode,
362 struct rsl_ie_chan_ident *chan_ident,
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200363 uint8_t bs_power, uint8_t ms_power,
364 uint8_t ta)
Harald Welte59b04682009-06-10 05:40:52 +0800365{
366 struct abis_rsl_dchan_hdr *dh;
367 struct msgb *msg = rsl_msgb_alloc();
368
369 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
370 init_dchan_hdr(dh, RSL_MT_CHAN_ACTIV);
371 dh->chan_nr = chan_nr;
372
373 msgb_tv_put(msg, RSL_IE_ACT_TYPE, act_type);
374 /* For compatibility with Phase 1 */
375 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(*chan_mode),
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200376 (uint8_t *) chan_mode);
Harald Welte59b04682009-06-10 05:40:52 +0800377 msgb_tlv_put(msg, RSL_IE_CHAN_IDENT, 4,
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200378 (uint8_t *) chan_ident);
Harald Welte59b04682009-06-10 05:40:52 +0800379#if 0
380 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, 1,
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200381 (uint8_t *) &encr_info);
Harald Welte59b04682009-06-10 05:40:52 +0800382#endif
383 msgb_tv_put(msg, RSL_IE_BS_POWER, bs_power);
384 msgb_tv_put(msg, RSL_IE_MS_POWER, ms_power);
385 msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta);
386
387 msg->trx = trx;
388
389 return abis_rsl_sendmsg(msg);
390}
391#endif
392
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200393int rsl_chan_activate_lchan(struct gsm_lchan *lchan, uint8_t act_type,
394 uint8_t ta, uint8_t ho_ref)
Harald Welte59b04682009-06-10 05:40:52 +0800395{
396 struct abis_rsl_dchan_hdr *dh;
Harald Welteed831842009-06-27 03:09:08 +0200397 struct msgb *msg;
Harald Welte39274f42009-07-29 15:41:29 +0200398 int rc;
Harald Weltedea24e92010-06-29 17:53:45 +0200399 uint8_t *len;
Harald Welte59b04682009-06-10 05:40:52 +0800400
Harald Weltee6d51f92011-06-25 10:02:33 +0200401 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte59b04682009-06-10 05:40:52 +0800402 struct rsl_ie_chan_mode cm;
laforgef723cf02010-06-20 21:38:19 +0200403 struct gsm48_chan_desc cd;
Harald Welte59b04682009-06-10 05:40:52 +0800404
Harald Welte39274f42009-07-29 15:41:29 +0200405 rc = channel_mode_from_lchan(&cm, lchan);
406 if (rc < 0)
407 return rc;
Harald Welte59b04682009-06-10 05:40:52 +0800408
Holger Hans Peter Freyther11b01402010-06-30 11:56:43 +0800409 memset(&cd, 0, sizeof(cd));
laforgef723cf02010-06-20 21:38:19 +0200410 gsm48_lchan2chan_desc(&cd, lchan);
Harald Welte59b04682009-06-10 05:40:52 +0800411
Harald Welteed831842009-06-27 03:09:08 +0200412 msg = rsl_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800413 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
414 init_dchan_hdr(dh, RSL_MT_CHAN_ACTIV);
415 dh->chan_nr = chan_nr;
416
417 msgb_tv_put(msg, RSL_IE_ACT_TYPE, act_type);
Harald Welte59b04682009-06-10 05:40:52 +0800418 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200419 (uint8_t *) &cm);
Holger Hans Peter Freyther11b01402010-06-30 11:56:43 +0800420
421 /*
422 * The Channel Identification is needed for Phase1 phones
423 * and it contains the GSM48 Channel Description and the
424 * Mobile Allocation. The GSM 08.58 asks for the Mobile
425 * Allocation to have a length of zero. We are using the
426 * msgb_l3len to calculate the length of both messages.
427 */
laforgef723cf02010-06-20 21:38:19 +0200428 msgb_v_put(msg, RSL_IE_CHAN_IDENT);
Harald Weltedea24e92010-06-29 17:53:45 +0200429 len = msgb_put(msg, 1);
Dieter Spaar18a55f62011-07-27 23:40:33 +0200430 msgb_tv_fixed_put(msg, GSM48_IE_CHANDESC_2, sizeof(cd), (const uint8_t *) &cd);
Holger Hans Peter Freyther4cab4422010-06-30 12:06:20 +0800431
432 if (lchan->ts->hopping.enabled)
433 msgb_tlv_put(msg, GSM48_IE_MA_AFTER, lchan->ts->hopping.ma_len,
434 lchan->ts->hopping.ma_data);
435 else
436 msgb_tlv_put(msg, GSM48_IE_MA_AFTER, 0, NULL);
Holger Hans Peter Freyther11b01402010-06-30 11:56:43 +0800437
438 /* update the calculated size */
439 msg->l3h = len + 1;
440 *len = msgb_l3len(msg);
441
Harald Welted2dd9de2009-08-30 15:37:11 +0900442 if (lchan->encr.alg_id > RSL_ENC_ALG_A5(0)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200443 uint8_t encr_info[MAX_A5_KEY_LEN+2];
Harald Welted2dd9de2009-08-30 15:37:11 +0900444 rc = build_encr_info(encr_info, lchan);
445 if (rc > 0)
446 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, rc, encr_info);
447 }
448
Harald Welteb90d7bd2009-12-17 00:31:10 +0100449 switch (act_type) {
450 case RSL_ACT_INTER_ASYNC:
451 case RSL_ACT_INTER_SYNC:
452 msgb_tv_put(msg, RSL_IE_HANDO_REF, ho_ref);
453 break;
454 default:
455 break;
456 }
457
Harald Welte59b04682009-06-10 05:40:52 +0800458 msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power);
459 msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power);
460 msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta);
461
Holger Hans Peter Freyther6fe8ab92010-01-28 04:45:05 +0100462 if (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR)
463 msgb_tlv_put(msg, RSL_IE_MR_CONFIG, sizeof(lchan->mr_conf),
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200464 (uint8_t *) &lchan->mr_conf);
Holger Hans Peter Freyther6fe8ab92010-01-28 04:45:05 +0100465
Harald Welte59b04682009-06-10 05:40:52 +0800466 msg->trx = lchan->ts->trx;
467
468 return abis_rsl_sendmsg(msg);
469}
470
Harald Welte8e770492009-07-29 11:38:15 +0200471/* Chapter 8.4.9: Modify channel mode on BTS side */
Harald Welte59b04682009-06-10 05:40:52 +0800472int rsl_chan_mode_modify_req(struct gsm_lchan *lchan)
473{
474 struct abis_rsl_dchan_hdr *dh;
Harald Welteed831842009-06-27 03:09:08 +0200475 struct msgb *msg;
Harald Welte39274f42009-07-29 15:41:29 +0200476 int rc;
Harald Welte59b04682009-06-10 05:40:52 +0800477
Harald Weltee6d51f92011-06-25 10:02:33 +0200478 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte59b04682009-06-10 05:40:52 +0800479 struct rsl_ie_chan_mode cm;
480
Harald Welte39274f42009-07-29 15:41:29 +0200481 rc = channel_mode_from_lchan(&cm, lchan);
482 if (rc < 0)
483 return rc;
Harald Welte59b04682009-06-10 05:40:52 +0800484
Harald Welteed831842009-06-27 03:09:08 +0200485 msg = rsl_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800486 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
487 init_dchan_hdr(dh, RSL_MT_MODE_MODIFY_REQ);
488 dh->chan_nr = chan_nr;
489
490 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200491 (uint8_t *) &cm);
Harald Welted2dd9de2009-08-30 15:37:11 +0900492
493 if (lchan->encr.alg_id > RSL_ENC_ALG_A5(0)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200494 uint8_t encr_info[MAX_A5_KEY_LEN+2];
Harald Welted2dd9de2009-08-30 15:37:11 +0900495 rc = build_encr_info(encr_info, lchan);
496 if (rc > 0)
497 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, rc, encr_info);
498 }
499
Holger Hans Peter Freyther3cce58f2009-11-18 22:57:02 +0100500 if (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR) {
501 msgb_tlv_put(msg, RSL_IE_MR_CONFIG, sizeof(lchan->mr_conf),
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200502 (uint8_t *) &lchan->mr_conf);
Holger Hans Peter Freyther3cce58f2009-11-18 22:57:02 +0100503 }
504
Harald Welted2dd9de2009-08-30 15:37:11 +0900505 msg->trx = lchan->ts->trx;
506
507 return abis_rsl_sendmsg(msg);
508}
509
510/* Chapter 8.4.6: Send the encryption command with given L3 info */
511int rsl_encryption_cmd(struct msgb *msg)
512{
513 struct abis_rsl_dchan_hdr *dh;
514 struct gsm_lchan *lchan = msg->lchan;
Harald Weltee6d51f92011-06-25 10:02:33 +0200515 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200516 uint8_t encr_info[MAX_A5_KEY_LEN+2];
517 uint8_t l3_len = msg->len;
Harald Welted2dd9de2009-08-30 15:37:11 +0900518 int rc;
519
520 /* First push the L3 IE tag and length */
521 msgb_tv16_push(msg, RSL_IE_L3_INFO, l3_len);
522
523 /* then the link identifier (SAPI0, main sign link) */
524 msgb_tv_push(msg, RSL_IE_LINK_IDENT, 0);
525
526 /* then encryption information */
527 rc = build_encr_info(encr_info, lchan);
528 if (rc <= 0)
529 return rc;
530 msgb_tlv_push(msg, RSL_IE_ENCR_INFO, rc, encr_info);
531
532 /* and finally the DCHAN header */
533 dh = (struct abis_rsl_dchan_hdr *) msgb_push(msg, sizeof(*dh));
534 init_dchan_hdr(dh, RSL_MT_ENCR_CMD);
535 dh->chan_nr = chan_nr;
Harald Welte59b04682009-06-10 05:40:52 +0800536
537 msg->trx = lchan->ts->trx;
538
539 return abis_rsl_sendmsg(msg);
540}
541
Harald Welte85a163c2009-08-10 11:43:22 +0200542/* Chapter 8.4.5 / 4.6: Deactivate the SACCH after 04.08 RR CHAN RELEASE */
Harald Welteafe3c232009-07-19 18:36:49 +0200543int rsl_deact_sacch(struct gsm_lchan *lchan)
544{
545 struct abis_rsl_dchan_hdr *dh;
546 struct msgb *msg = rsl_msgb_alloc();
547
548 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
549 init_dchan_hdr(dh, RSL_MT_DEACTIVATE_SACCH);
Harald Weltee6d51f92011-06-25 10:02:33 +0200550 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welteafe3c232009-07-19 18:36:49 +0200551
552 msg->lchan = lchan;
553 msg->trx = lchan->ts->trx;
554
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +0100555 DEBUGP(DRSL, "%s DEACTivate SACCH CMD\n", gsm_lchan_name(lchan));
Harald Welteafe3c232009-07-19 18:36:49 +0200556
557 return abis_rsl_sendmsg(msg);
558}
559
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800560static void error_timeout_cb(void *data)
561{
562 struct gsm_lchan *lchan = data;
563 if (lchan->state != LCHAN_S_REL_ERR) {
564 LOGP(DRSL, LOGL_ERROR, "%s error timeout but not in error state: %d\n",
565 gsm_lchan_name(lchan), lchan->state);
566 return;
567 }
568
569 /* go back to the none state */
570 LOGP(DRSL, LOGL_NOTICE, "%s is back in operation.\n", gsm_lchan_name(lchan));
Holger Hans Peter Freyther456fb9d2010-06-08 11:53:33 +0800571 rsl_lchan_set_state(lchan, LCHAN_S_NONE);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800572}
573
Harald Welte08011e22011-03-04 13:41:31 +0100574static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan);
575
Harald Welte85a163c2009-08-10 11:43:22 +0200576/* Chapter 8.4.14 / 4.7: Tell BTS to release the radio channel */
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800577static int rsl_rf_chan_release(struct gsm_lchan *lchan, int error)
Harald Welte59b04682009-06-10 05:40:52 +0800578{
579 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800580 struct msgb *msg;
Harald Welte08011e22011-03-04 13:41:31 +0100581 int rc;
Harald Welte59b04682009-06-10 05:40:52 +0800582
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800583 if (lchan->state == LCHAN_S_REL_ERR) {
584 LOGP(DRSL, LOGL_NOTICE, "%s is in error state not sending release.\n",
585 gsm_lchan_name(lchan));
586 return -1;
587 }
588
589 msg = rsl_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800590 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
591 init_dchan_hdr(dh, RSL_MT_RF_CHAN_REL);
Harald Weltee6d51f92011-06-25 10:02:33 +0200592 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte59b04682009-06-10 05:40:52 +0800593
594 msg->lchan = lchan;
595 msg->trx = lchan->ts->trx;
596
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800597 DEBUGP(DRSL, "%s RF Channel Release CMD due error %d\n", gsm_lchan_name(lchan), error);
598
599 if (error) {
600 /*
601 * the nanoBTS sends RLL release indications after the channel release. This can
602 * be a problem when we have reassigned the channel to someone else and then can
603 * not figure out who used this channel.
604 */
Holger Hans Peter Freyther456fb9d2010-06-08 11:53:33 +0800605 rsl_lchan_set_state(lchan, LCHAN_S_REL_ERR);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800606 lchan->error_timer.data = lchan;
607 lchan->error_timer.cb = error_timeout_cb;
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +0200608 osmo_timer_schedule(&lchan->error_timer,
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800609 msg->trx->bts->network->T3111 + 2, 0);
610 }
Harald Welte59b04682009-06-10 05:40:52 +0800611
Harald Welte08011e22011-03-04 13:41:31 +0100612 rc = abis_rsl_sendmsg(msg);
613
Harald Welte85a163c2009-08-10 11:43:22 +0200614 /* BTS will respond by RF CHAN REL ACK */
Harald Welte6bddd822011-01-14 23:18:59 +0100615#ifdef HSL_SR_1_0
Harald Welte08011e22011-03-04 13:41:31 +0100616 /* The HSL Femto seems to 'forget' sending a REL ACK for TS1...TS7 */
617 if (lchan->ts->trx->bts->type == GSM_BTS_TYPE_HSL_FEMTO && lchan->ts->nr != 0)
618 rc = rsl_rx_rf_chan_rel_ack(lchan);
Harald Welte6bddd822011-01-14 23:18:59 +0100619#endif
Harald Welte08011e22011-03-04 13:41:31 +0100620
621 return rc;
Harald Welte59b04682009-06-10 05:40:52 +0800622}
623
Harald Welte9773f6c2011-01-14 14:16:16 +0100624static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan)
625{
626
627 DEBUGP(DRSL, "%s RF CHANNEL RELEASE ACK\n", gsm_lchan_name(lchan));
628
629 if (lchan->state != LCHAN_S_REL_REQ && lchan->state != LCHAN_S_REL_ERR)
630 LOGP(DRSL, LOGL_NOTICE, "%s CHAN REL ACK but state %s\n",
631 gsm_lchan_name(lchan),
632 gsm_lchans_name(lchan->state));
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +0200633 osmo_timer_del(&lchan->T3111);
Harald Welte9773f6c2011-01-14 14:16:16 +0100634 /* we have an error timer pending to release that */
635 if (lchan->state != LCHAN_S_REL_ERR)
636 rsl_lchan_set_state(lchan, LCHAN_S_NONE);
637 lchan_free(lchan);
638
639 return 0;
640}
641
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200642int rsl_paging_cmd(struct gsm_bts *bts, uint8_t paging_group, uint8_t len,
643 uint8_t *ms_ident, uint8_t chan_needed)
Harald Welte59b04682009-06-10 05:40:52 +0800644{
645 struct abis_rsl_dchan_hdr *dh;
646 struct msgb *msg = rsl_msgb_alloc();
647
648 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
649 init_dchan_hdr(dh, RSL_MT_PAGING_CMD);
650 dh->chan_nr = RSL_CHAN_PCH_AGCH;
651
652 msgb_tv_put(msg, RSL_IE_PAGING_GROUP, paging_group);
653 msgb_tlv_put(msg, RSL_IE_MS_IDENTITY, len-2, ms_ident+2);
654 msgb_tv_put(msg, RSL_IE_CHAN_NEEDED, chan_needed);
655
656 msg->trx = bts->c0;
657
658 return abis_rsl_sendmsg(msg);
659}
660
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200661int imsi_str2bcd(uint8_t *bcd_out, const char *str_in)
Harald Welte59b04682009-06-10 05:40:52 +0800662{
663 int i, len = strlen(str_in);
664
665 for (i = 0; i < len; i++) {
666 int num = str_in[i] - 0x30;
667 if (num < 0 || num > 9)
668 return -1;
669 if (i % 2 == 0)
670 bcd_out[i/2] = num;
671 else
672 bcd_out[i/2] |= (num << 4);
673 }
674
675 return 0;
676}
677
678/* Chapter 8.5.6 */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200679int rsl_imm_assign_cmd(struct gsm_bts *bts, uint8_t len, uint8_t *val)
Harald Welte59b04682009-06-10 05:40:52 +0800680{
681 struct msgb *msg = rsl_msgb_alloc();
682 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200683 uint8_t buf[MACBLOCK_SIZE];
Harald Welte59b04682009-06-10 05:40:52 +0800684
685 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
686 init_dchan_hdr(dh, RSL_MT_IMMEDIATE_ASSIGN_CMD);
687 dh->chan_nr = RSL_CHAN_PCH_AGCH;
688
689 switch (bts->type) {
690 case GSM_BTS_TYPE_BS11:
691 msgb_tlv_put(msg, RSL_IE_IMM_ASS_INFO, len, val);
692 break;
693 default:
694 /* If phase 2, construct a FULL_IMM_ASS_INFO */
695 pad_macblock(buf, val, len);
696 msgb_tlv_put(msg, RSL_IE_FULL_IMM_ASS_INFO, MACBLOCK_SIZE, buf);
697 break;
698 }
699
700 msg->trx = bts->c0;
701
702 return abis_rsl_sendmsg(msg);
703}
704
Harald Welte4684e632009-08-10 09:51:40 +0200705/* Send Siemens specific MS RF Power Capability Indication */
Harald Welte12090752009-08-10 10:07:33 +0200706int rsl_siemens_mrpci(struct gsm_lchan *lchan, struct rsl_mrpci *mrpci)
Harald Welte4684e632009-08-10 09:51:40 +0200707{
708 struct msgb *msg = rsl_msgb_alloc();
709 struct abis_rsl_dchan_hdr *dh;
710
711 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
712 init_dchan_hdr(dh, RSL_MT_SIEMENS_MRPCI);
Harald Welte874a5b42009-08-10 11:26:14 +0200713 dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
Harald Weltee6d51f92011-06-25 10:02:33 +0200714 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200715 msgb_tv_put(msg, RSL_IE_SIEMENS_MRPCI, *(uint8_t *)mrpci);
Harald Welte4684e632009-08-10 09:51:40 +0200716
Harald Weltede4477a2009-12-24 12:20:20 +0100717 DEBUGP(DRSL, "%s TX Siemens MRPCI 0x%02x\n",
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200718 gsm_lchan_name(lchan), *(uint8_t *)mrpci);
Harald Welte874a5b42009-08-10 11:26:14 +0200719
720 msg->trx = lchan->ts->trx;
721
Harald Welte4684e632009-08-10 09:51:40 +0200722 return abis_rsl_sendmsg(msg);
723}
724
725
Harald Welte59b04682009-06-10 05:40:52 +0800726/* Send "DATA REQUEST" message with given L3 Info payload */
727/* Chapter 8.3.1 */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200728int rsl_data_request(struct msgb *msg, uint8_t link_id)
Harald Welte59b04682009-06-10 05:40:52 +0800729{
Harald Welte59b04682009-06-10 05:40:52 +0800730 if (msg->lchan == NULL) {
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100731 LOGP(DRSL, LOGL_ERROR, "cannot send DATA REQUEST to unknown lchan\n");
Harald Welte59b04682009-06-10 05:40:52 +0800732 return -EINVAL;
733 }
734
Harald Weltee6d51f92011-06-25 10:02:33 +0200735 rsl_rll_push_l3(msg, RSL_MT_DATA_REQ, gsm_lchan2chan_nr(msg->lchan),
Harald Weltea22d36b2010-03-04 10:33:10 +0100736 link_id, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800737
738 msg->trx = msg->lchan->ts->trx;
739
740 return abis_rsl_sendmsg(msg);
741}
742
Harald Welteed9a5ab2009-08-09 13:47:35 +0200743/* Send "ESTABLISH REQUEST" message with given L3 Info payload */
744/* Chapter 8.3.1 */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200745int rsl_establish_request(struct gsm_lchan *lchan, uint8_t link_id)
Harald Welteed9a5ab2009-08-09 13:47:35 +0200746{
Harald Weltea22d36b2010-03-04 10:33:10 +0100747 struct msgb *msg;
Harald Welteed9a5ab2009-08-09 13:47:35 +0200748
Harald Weltee6d51f92011-06-25 10:02:33 +0200749 msg = rsl_rll_simple(RSL_MT_EST_REQ, gsm_lchan2chan_nr(lchan),
Harald Weltea22d36b2010-03-04 10:33:10 +0100750 link_id, 0);
Harald Welteed9a5ab2009-08-09 13:47:35 +0200751 msg->trx = lchan->ts->trx;
752
753 return abis_rsl_sendmsg(msg);
754}
755
Harald Welte0f2e3c12009-08-08 13:15:07 +0200756/* Chapter 8.3.7 Request the release of multiframe mode of RLL connection.
757 This is what higher layers should call. The BTS then responds with
758 RELEASE CONFIRM, which we in turn use to trigger RSL CHANNEL RELEASE,
759 which in turn is acknowledged by RSL CHANNEL RELEASE ACK, which calls
760 lchan_free() */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200761int rsl_release_request(struct gsm_lchan *lchan, uint8_t link_id, uint8_t reason)
Harald Welte0f2e3c12009-08-08 13:15:07 +0200762{
Harald Welte0f2e3c12009-08-08 13:15:07 +0200763
Harald Weltea22d36b2010-03-04 10:33:10 +0100764 struct msgb *msg;
765
Harald Weltee6d51f92011-06-25 10:02:33 +0200766 msg = rsl_rll_simple(RSL_MT_REL_REQ, gsm_lchan2chan_nr(lchan),
Harald Weltea22d36b2010-03-04 10:33:10 +0100767 link_id, 0);
Holger Hans Peter Freytherbcea9a72010-06-08 11:57:45 +0800768 /* 0 is normal release, 1 is local end */
769 msgb_tv_put(msg, RSL_IE_RELEASE_MODE, reason);
Harald Welte0f2e3c12009-08-08 13:15:07 +0200770
Harald Weltec88a4432009-12-29 10:44:17 +0100771 /* FIXME: start some timer in case we don't receive a REL ACK ? */
772
Harald Welte0f2e3c12009-08-08 13:15:07 +0200773 msg->trx = lchan->ts->trx;
774
775 return abis_rsl_sendmsg(msg);
776}
777
Holger Hans Peter Freyther68914a02010-04-10 00:12:31 +0200778int rsl_lchan_set_state(struct gsm_lchan *lchan, int state)
779{
780 lchan->state = state;
781 return 0;
782}
783
Harald Welte59b04682009-06-10 05:40:52 +0800784/* Chapter 8.4.2: Channel Activate Acknowledge */
785static int rsl_rx_chan_act_ack(struct msgb *msg)
786{
787 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
788
789 /* BTS has confirmed channel activation, we now need
790 * to assign the activated channel to the MS */
791 if (rslh->ie_chan != RSL_IE_CHAN_NR)
792 return -EINVAL;
Harald Welte6720a432009-11-29 22:45:52 +0100793
Harald Weltec88a4432009-12-29 10:44:17 +0100794 if (msg->lchan->state != LCHAN_S_ACT_REQ)
Harald Welteab2534c2009-12-29 10:52:38 +0100795 LOGP(DRSL, LOGL_NOTICE, "%s CHAN ACT ACK, but state %s\n",
796 gsm_lchan_name(msg->lchan),
797 gsm_lchans_name(msg->lchan->state));
Holger Hans Peter Freyther68914a02010-04-10 00:12:31 +0200798 rsl_lchan_set_state(msg->lchan, LCHAN_S_ACTIVE);
Harald Welte4baa9c52009-12-21 13:27:11 +0100799
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +0800800 if (msg->lchan->rqd_ref) {
801 rsl_send_imm_assignment(msg->lchan);
802 talloc_free(msg->lchan->rqd_ref);
803 msg->lchan->rqd_ref = NULL;
804 msg->lchan->rqd_ta = 0;
805 }
806
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +0100807 send_lchan_signal(S_LCHAN_ACTIVATE_ACK, msg->lchan, NULL);
Harald Welte6720a432009-11-29 22:45:52 +0100808
Harald Welte59b04682009-06-10 05:40:52 +0800809 return 0;
810}
811
812/* Chapter 8.4.3: Channel Activate NACK */
813static int rsl_rx_chan_act_nack(struct msgb *msg)
814{
815 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
816 struct tlv_parsed tp;
817
Harald Welte (local)ed6d7622009-12-27 11:48:11 +0100818 LOGP(DRSL, LOGL_ERROR, "%s CHANNEL ACTIVATE NACK",
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +0100819 gsm_lchan_name(msg->lchan));
Harald Welte (local)ed6d7622009-12-27 11:48:11 +0100820
Harald Welte59b04682009-06-10 05:40:52 +0800821 /* BTS has rejected channel activation ?!? */
822 if (dh->ie_chan != RSL_IE_CHAN_NR)
823 return -EINVAL;
824
825 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
Harald Welte (local)c3be50c2009-12-27 18:12:29 +0100826 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200827 const uint8_t *cause = TLVP_VAL(&tp, RSL_IE_CAUSE);
Harald Welte (local)c3be50c2009-12-27 18:12:29 +0100828 print_rsl_cause(LOGL_ERROR, cause,
Harald Weltef1a168d2009-07-28 17:58:09 +0200829 TLVP_LEN(&tp, RSL_IE_CAUSE));
Harald Welte (local)c3be50c2009-12-27 18:12:29 +0100830 if (*cause != RSL_ERR_RCH_ALR_ACTV_ALLOC)
Holger Hans Peter Freyther68914a02010-04-10 00:12:31 +0200831 rsl_lchan_set_state(msg->lchan, LCHAN_S_NONE);
Harald Welte (local)c3be50c2009-12-27 18:12:29 +0100832 } else
Holger Hans Peter Freyther68914a02010-04-10 00:12:31 +0200833 rsl_lchan_set_state(msg->lchan, LCHAN_S_NONE);
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +0200834
Harald Welte (local)ed6d7622009-12-27 11:48:11 +0100835 LOGPC(DRSL, LOGL_ERROR, "\n");
836
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +0100837 send_lchan_signal(S_LCHAN_ACTIVATE_NACK, msg->lchan, NULL);
Harald Welte6720a432009-11-29 22:45:52 +0100838
Harald Weltecddb9802009-08-09 19:50:08 +0200839 lchan_free(msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +0800840 return 0;
841}
842
843/* Chapter 8.4.4: Connection Failure Indication */
844static int rsl_rx_conn_fail(struct msgb *msg)
845{
846 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
847 struct tlv_parsed tp;
848
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100849 /* FIXME: print which channel */
Harald Welte (local)4bd76642009-12-26 22:33:09 +0100850 LOGP(DRSL, LOGL_NOTICE, "%s CONNECTION FAIL: RELEASING ",
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +0100851 gsm_lchan_name(msg->lchan));
Harald Welte59b04682009-06-10 05:40:52 +0800852
853 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
854
Harald Weltef1a168d2009-07-28 17:58:09 +0200855 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
Harald Weltede4477a2009-12-24 12:20:20 +0100856 print_rsl_cause(LOGL_NOTICE, TLVP_VAL(&tp, RSL_IE_CAUSE),
Harald Weltef1a168d2009-07-28 17:58:09 +0200857 TLVP_LEN(&tp, RSL_IE_CAUSE));
858
Harald Welte (local)4bd76642009-12-26 22:33:09 +0100859 LOGPC(DRSL, LOGL_NOTICE, "\n");
Harald Welte59b04682009-06-10 05:40:52 +0800860 /* FIXME: only free it after channel release ACK */
Pablo Neira Ayuso1c450742011-05-06 12:13:10 +0200861 osmo_counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rf_fail);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800862 return rsl_rf_chan_release(msg->lchan, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800863}
864
Harald Weltec20bd1d2009-11-29 19:07:28 +0100865static void print_meas_rep_uni(struct gsm_meas_rep_unidir *mru,
866 const char *prefix)
867{
Harald Welte0e4fa782009-12-16 16:52:07 +0100868 DEBUGPC(DMEAS, "RXL-FULL-%s=%3ddBm RXL-SUB-%s=%3ddBm ",
869 prefix, rxlev2dbm(mru->full.rx_lev),
870 prefix, rxlev2dbm(mru->sub.rx_lev));
Harald Weltec20bd1d2009-11-29 19:07:28 +0100871 DEBUGPC(DMEAS, "RXQ-FULL-%s=%d RXQ-SUB-%s=%d ",
872 prefix, mru->full.rx_qual, prefix, mru->sub.rx_qual);
873}
874
875static void print_meas_rep(struct gsm_meas_rep *mr)
876{
Harald Welte0e4fa782009-12-16 16:52:07 +0100877 int i;
878
Harald Weltec20bd1d2009-11-29 19:07:28 +0100879 DEBUGP(DMEAS, "MEASUREMENT RESULT NR=%d ", mr->nr);
880
881 if (mr->flags & MEAS_REP_F_DL_DTX)
882 DEBUGPC(DMEAS, "DTXd ");
883
884 print_meas_rep_uni(&mr->ul, "ul");
885 DEBUGPC(DMEAS, "BS_POWER=%d ", mr->bs_power);
886 if (mr->flags & MEAS_REP_F_MS_TO)
887 DEBUGPC(DMEAS, "MS_TO=%d ", mr->ms_timing_offset);
888
889 if (mr->flags & MEAS_REP_F_MS_L1) {
Harald Welte0e4fa782009-12-16 16:52:07 +0100890 DEBUGPC(DMEAS, "L1_MS_PWR=%3ddBm ", mr->ms_l1.pwr);
Harald Weltec20bd1d2009-11-29 19:07:28 +0100891 DEBUGPC(DMEAS, "L1_FPC=%u ",
892 mr->flags & MEAS_REP_F_FPC ? 1 : 0);
893 DEBUGPC(DMEAS, "L1_TA=%u ", mr->ms_l1.ta);
894 }
895
896 if (mr->flags & MEAS_REP_F_UL_DTX)
897 DEBUGPC(DMEAS, "DTXu ");
898 if (mr->flags & MEAS_REP_F_BA1)
899 DEBUGPC(DMEAS, "BA1 ");
900 if (!(mr->flags & MEAS_REP_F_DL_VALID))
901 DEBUGPC(DMEAS, "NOT VALID ");
902 else
903 print_meas_rep_uni(&mr->dl, "dl");
904
905 DEBUGPC(DMEAS, "NUM_NEIGH=%u\n", mr->num_cell);
Harald Welte0b833f82009-12-19 18:33:05 +0100906 if (mr->num_cell == 7)
907 return;
Harald Welte0e4fa782009-12-16 16:52:07 +0100908 for (i = 0; i < mr->num_cell; i++) {
909 struct gsm_meas_rep_cell *mrc = &mr->cell[i];
Harald Welte350c2d32009-12-25 23:02:22 +0100910 DEBUGP(DMEAS, "IDX=%u ARFCN=%u BSIC=%u => %d dBm\n",
911 mrc->neigh_idx, mrc->arfcn, mrc->bsic, rxlev2dbm(mrc->rxlev));
Harald Welte0e4fa782009-12-16 16:52:07 +0100912 }
Harald Weltec20bd1d2009-11-29 19:07:28 +0100913}
914
Harald Welte59b04682009-06-10 05:40:52 +0800915static int rsl_rx_meas_res(struct msgb *msg)
916{
917 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
918 struct tlv_parsed tp;
Harald Weltef9476812009-12-15 21:36:05 +0100919 struct gsm_meas_rep *mr = lchan_next_meas_rep(msg->lchan);
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200920 uint8_t len;
921 const uint8_t *val;
Harald Weltec20bd1d2009-11-29 19:07:28 +0100922 int rc;
Harald Welte59b04682009-06-10 05:40:52 +0800923
Harald Welte4baa9c52009-12-21 13:27:11 +0100924 /* check if this channel is actually active */
925 /* FIXME: maybe this check should be way more generic/centralized */
Harald Weltec88a4432009-12-29 10:44:17 +0100926 if (msg->lchan->state != LCHAN_S_ACTIVE) {
Holger Hans Peter Freyther67a2e292010-07-29 14:50:57 +0800927 LOGP(DRSL, LOGL_DEBUG, "%s: MEAS RES for inactive channel\n",
Harald Weltec88a4432009-12-29 10:44:17 +0100928 gsm_lchan_name(msg->lchan));
Harald Welte4baa9c52009-12-21 13:27:11 +0100929 return 0;
Harald Weltec88a4432009-12-29 10:44:17 +0100930 }
Harald Welte4baa9c52009-12-21 13:27:11 +0100931
Harald Weltef9476812009-12-15 21:36:05 +0100932 memset(mr, 0, sizeof(*mr));
Harald Welteaa0efa12009-12-16 23:29:34 +0100933 mr->lchan = msg->lchan;
Harald Welte4efcc542009-11-30 19:16:47 +0100934
Harald Welte59b04682009-06-10 05:40:52 +0800935 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
936
Harald Weltec20bd1d2009-11-29 19:07:28 +0100937 if (!TLVP_PRESENT(&tp, RSL_IE_MEAS_RES_NR) ||
938 !TLVP_PRESENT(&tp, RSL_IE_UPLINK_MEAS) ||
939 !TLVP_PRESENT(&tp, RSL_IE_BS_POWER))
940 return -EIO;
941
942 /* Mandatory Parts */
Harald Weltef9476812009-12-15 21:36:05 +0100943 mr->nr = *TLVP_VAL(&tp, RSL_IE_MEAS_RES_NR);
Harald Weltec20bd1d2009-11-29 19:07:28 +0100944
945 len = TLVP_LEN(&tp, RSL_IE_UPLINK_MEAS);
946 val = TLVP_VAL(&tp, RSL_IE_UPLINK_MEAS);
947 if (len >= 3) {
948 if (val[0] & 0x40)
Harald Weltef9476812009-12-15 21:36:05 +0100949 mr->flags |= MEAS_REP_F_DL_DTX;
950 mr->ul.full.rx_lev = val[0] & 0x3f;
951 mr->ul.sub.rx_lev = val[1] & 0x3f;
952 mr->ul.full.rx_qual = val[2]>>3 & 0x7;
953 mr->ul.sub.rx_qual = val[2] & 0x7;
Harald Welte59b04682009-06-10 05:40:52 +0800954 }
Harald Weltec20bd1d2009-11-29 19:07:28 +0100955
Harald Weltef9476812009-12-15 21:36:05 +0100956 mr->bs_power = *TLVP_VAL(&tp, RSL_IE_BS_POWER);
Harald Weltec20bd1d2009-11-29 19:07:28 +0100957
958 /* Optional Parts */
Harald Welte59b04682009-06-10 05:40:52 +0800959 if (TLVP_PRESENT(&tp, RSL_IE_MS_TIMING_OFFSET))
Harald Weltef9476812009-12-15 21:36:05 +0100960 mr->ms_timing_offset =
Harald Weltec20bd1d2009-11-29 19:07:28 +0100961 *TLVP_VAL(&tp, RSL_IE_MS_TIMING_OFFSET);
962
Harald Weltea1467eb2009-06-20 18:44:35 +0200963 if (TLVP_PRESENT(&tp, RSL_IE_L1_INFO)) {
Harald Weltec20bd1d2009-11-29 19:07:28 +0100964 val = TLVP_VAL(&tp, RSL_IE_L1_INFO);
Harald Weltef9476812009-12-15 21:36:05 +0100965 mr->flags |= MEAS_REP_F_MS_L1;
966 mr->ms_l1.pwr = ms_pwr_dbm(msg->trx->bts->band, val[0] >> 3);
Harald Weltec20bd1d2009-11-29 19:07:28 +0100967 if (val[0] & 0x04)
Harald Weltef9476812009-12-15 21:36:05 +0100968 mr->flags |= MEAS_REP_F_FPC;
969 mr->ms_l1.ta = val[1];
Harald Weltea1467eb2009-06-20 18:44:35 +0200970 }
Harald Welte59b04682009-06-10 05:40:52 +0800971 if (TLVP_PRESENT(&tp, RSL_IE_L3_INFO)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200972 msg->l3h = (uint8_t *) TLVP_VAL(&tp, RSL_IE_L3_INFO);
Harald Weltef9476812009-12-15 21:36:05 +0100973 rc = gsm48_parse_meas_rep(mr, msg);
Harald Weltec20bd1d2009-11-29 19:07:28 +0100974 if (rc < 0)
975 return rc;
976 }
977
Harald Weltef9476812009-12-15 21:36:05 +0100978 print_meas_rep(mr);
Harald Welte59b04682009-06-10 05:40:52 +0800979
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +0100980 send_lchan_signal(S_LCHAN_MEAS_REP, msg->lchan, mr);
Harald Welte4efcc542009-11-30 19:16:47 +0100981
Harald Welte59b04682009-06-10 05:40:52 +0800982 return 0;
983}
984
Harald Welte6720a432009-11-29 22:45:52 +0100985/* Chapter 8.4.7 */
986static int rsl_rx_hando_det(struct msgb *msg)
987{
988 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
989 struct tlv_parsed tp;
990
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +0100991 DEBUGP(DRSL, "%s HANDOVER DETECT ", gsm_lchan_name(msg->lchan));
Harald Welte6720a432009-11-29 22:45:52 +0100992
993 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
994
995 if (TLVP_PRESENT(&tp, RSL_IE_ACCESS_DELAY))
996 DEBUGPC(DRSL, "access delay = %u\n",
997 *TLVP_VAL(&tp, RSL_IE_ACCESS_DELAY));
998 else
999 DEBUGPC(DRSL, "\n");
1000
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +01001001 send_lchan_signal(S_LCHAN_HANDOVER_DETECT, msg->lchan, NULL);
Harald Welte6720a432009-11-29 22:45:52 +01001002
1003 return 0;
1004}
1005
Harald Welte59b04682009-06-10 05:40:52 +08001006static int abis_rsl_rx_dchan(struct msgb *msg)
1007{
1008 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
1009 int rc = 0;
1010 char *ts_name;
1011
1012 msg->lchan = lchan_lookup(msg->trx, rslh->chan_nr);
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001013 ts_name = gsm_lchan_name(msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001014
Harald Welte59b04682009-06-10 05:40:52 +08001015 switch (rslh->c.msg_type) {
1016 case RSL_MT_CHAN_ACTIV_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001017 DEBUGP(DRSL, "%s CHANNEL ACTIVATE ACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001018 rc = rsl_rx_chan_act_ack(msg);
1019 break;
1020 case RSL_MT_CHAN_ACTIV_NACK:
Harald Welte59b04682009-06-10 05:40:52 +08001021 rc = rsl_rx_chan_act_nack(msg);
1022 break;
1023 case RSL_MT_CONN_FAIL:
1024 rc = rsl_rx_conn_fail(msg);
1025 break;
1026 case RSL_MT_MEAS_RES:
1027 rc = rsl_rx_meas_res(msg);
1028 break;
Harald Welte6720a432009-11-29 22:45:52 +01001029 case RSL_MT_HANDO_DET:
1030 rc = rsl_rx_hando_det(msg);
1031 break;
Harald Welte59b04682009-06-10 05:40:52 +08001032 case RSL_MT_RF_CHAN_REL_ACK:
Harald Welte9773f6c2011-01-14 14:16:16 +01001033 rc = rsl_rx_rf_chan_rel_ack(msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001034 break;
1035 case RSL_MT_MODE_MODIFY_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001036 DEBUGP(DRSL, "%s CHANNEL MODE MODIFY ACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001037 break;
1038 case RSL_MT_MODE_MODIFY_NACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001039 LOGP(DRSL, LOGL_ERROR, "%s CHANNEL MODE MODIFY NACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001040 break;
Harald Welteaed946e2009-10-24 10:29:22 +02001041 case RSL_MT_IPAC_PDCH_ACT_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001042 DEBUGPC(DRSL, "%s IPAC PDCH ACT ACK\n", ts_name);
Harald Welte2b361522010-03-28 14:42:09 +08001043 msg->lchan->ts->flags |= TS_F_PDCH_MODE;
Harald Welteaed946e2009-10-24 10:29:22 +02001044 break;
1045 case RSL_MT_IPAC_PDCH_ACT_NACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001046 LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH ACT NACK\n", ts_name);
Harald Welteaed946e2009-10-24 10:29:22 +02001047 break;
1048 case RSL_MT_IPAC_PDCH_DEACT_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001049 DEBUGP(DRSL, "%s IPAC PDCH DEACT ACK\n", ts_name);
Harald Welte2b361522010-03-28 14:42:09 +08001050 msg->lchan->ts->flags &= ~TS_F_PDCH_MODE;
Harald Welteaed946e2009-10-24 10:29:22 +02001051 break;
1052 case RSL_MT_IPAC_PDCH_DEACT_NACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001053 LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH DEACT NACK\n", ts_name);
Harald Welteaed946e2009-10-24 10:29:22 +02001054 break;
Harald Welte59b04682009-06-10 05:40:52 +08001055 case RSL_MT_PHY_CONTEXT_CONF:
1056 case RSL_MT_PREPROC_MEAS_RES:
1057 case RSL_MT_TALKER_DET:
1058 case RSL_MT_LISTENER_DET:
1059 case RSL_MT_REMOTE_CODEC_CONF_REP:
1060 case RSL_MT_MR_CODEC_MOD_ACK:
1061 case RSL_MT_MR_CODEC_MOD_NACK:
1062 case RSL_MT_MR_CODEC_MOD_PER:
Harald Weltede4477a2009-12-24 12:20:20 +01001063 LOGP(DRSL, LOGL_NOTICE, "%s Unimplemented Abis RSL DChan "
1064 "msg 0x%02x\n", ts_name, rslh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001065 break;
1066 default:
Harald Weltede4477a2009-12-24 12:20:20 +01001067 LOGP(DRSL, LOGL_NOTICE, "%s unknown Abis RSL DChan msg 0x%02x\n",
1068 ts_name, rslh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001069 return -EINVAL;
1070 }
1071
1072 return rc;
1073}
1074
1075static int rsl_rx_error_rep(struct msgb *msg)
1076{
1077 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
Harald Weltef1a168d2009-07-28 17:58:09 +02001078 struct tlv_parsed tp;
Harald Welte59b04682009-06-10 05:40:52 +08001079
Harald Welte (local)ab788cf2009-12-28 23:14:22 +01001080 LOGP(DRSL, LOGL_ERROR, "%s ERROR REPORT ", gsm_trx_name(msg->trx));
Harald Weltef1a168d2009-07-28 17:58:09 +02001081
1082 rsl_tlv_parse(&tp, rslh->data, msgb_l2len(msg)-sizeof(*rslh));
1083
1084 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
Harald Weltede4477a2009-12-24 12:20:20 +01001085 print_rsl_cause(LOGL_ERROR, TLVP_VAL(&tp, RSL_IE_CAUSE),
Harald Weltef1a168d2009-07-28 17:58:09 +02001086 TLVP_LEN(&tp, RSL_IE_CAUSE));
1087
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001088 LOGPC(DRSL, LOGL_ERROR, "\n");
Harald Welte59b04682009-06-10 05:40:52 +08001089
1090 return 0;
1091}
1092
1093static int abis_rsl_rx_trx(struct msgb *msg)
1094{
1095 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
1096 int rc = 0;
1097
1098 switch (rslh->msg_type) {
1099 case RSL_MT_ERROR_REPORT:
1100 rc = rsl_rx_error_rep(msg);
1101 break;
1102 case RSL_MT_RF_RES_IND:
1103 /* interference on idle channels of TRX */
Harald Welte (local)ab788cf2009-12-28 23:14:22 +01001104 //DEBUGP(DRSL, "%s RF Resource Indication\n", gsm_trx_name(msg->trx));
Harald Welte59b04682009-06-10 05:40:52 +08001105 break;
1106 case RSL_MT_OVERLOAD:
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +02001107 /* indicate CCCH / ACCH / processor overload */
Harald Welte (local)ab788cf2009-12-28 23:14:22 +01001108 LOGP(DRSL, LOGL_ERROR, "%s CCCH/ACCH/CPU Overload\n",
1109 gsm_trx_name(msg->trx));
Harald Welte59b04682009-06-10 05:40:52 +08001110 break;
1111 default:
Harald Welte (local)ab788cf2009-12-28 23:14:22 +01001112 LOGP(DRSL, LOGL_NOTICE, "%s Unknown Abis RSL TRX message "
1113 "type 0x%02x\n", gsm_trx_name(msg->trx), rslh->msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001114 return -EINVAL;
1115 }
1116 return rc;
1117}
1118
Harald Welte427dbc42009-08-10 00:26:10 +02001119/* If T3101 expires, we never received a response to IMMEDIATE ASSIGN */
1120static void t3101_expired(void *data)
1121{
1122 struct gsm_lchan *lchan = data;
1123
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +08001124 rsl_rf_chan_release(lchan, 1);
Harald Welte427dbc42009-08-10 00:26:10 +02001125}
1126
Holger Hans Peter Freyther4a00c062010-05-31 21:33:15 +08001127/* If T3111 expires, we will send the RF Channel Request */
1128static void t3111_expired(void *data)
1129{
1130 struct gsm_lchan *lchan = data;
1131
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +08001132 rsl_rf_chan_release(lchan, 0);
Holger Hans Peter Freyther4a00c062010-05-31 21:33:15 +08001133}
1134
laforge50312e82010-06-21 12:08:52 +02001135#define GSM48_LEN2PLEN(a) (((a) << 2) | 1)
1136
Harald Weltea00fdd72010-12-23 14:39:29 +01001137/* Format an IMM ASS REJ according to 04.08 Chapter 9.1.20 */
1138static int rsl_send_imm_ass_rej(struct gsm_bts *bts,
1139 unsigned int num_req_refs,
1140 struct gsm48_req_ref *rqd_refs,
1141 uint8_t wait_ind)
1142{
1143 uint8_t buf[GSM_MACBLOCK_LEN];
1144 struct gsm48_imm_ass_rej *iar = (struct gsm48_imm_ass_rej *)buf;
1145
1146 /* create IMMEDIATE ASSIGN REJECT 04.08 message */
1147 memset(iar, 0, sizeof(*iar));
1148 iar->proto_discr = GSM48_PDISC_RR;
1149 iar->msg_type = GSM48_MT_RR_IMM_ASS;
1150 iar->page_mode = GSM48_PM_SAME;
1151
1152 memcpy(&iar->req_ref1, &rqd_refs[0], sizeof(iar->req_ref1));
1153 iar->wait_ind1 = wait_ind;
1154
1155 if (num_req_refs >= 2)
1156 memcpy(&iar->req_ref2, &rqd_refs[1], sizeof(iar->req_ref2));
1157 else
1158 memcpy(&iar->req_ref2, &rqd_refs[0], sizeof(iar->req_ref2));
1159 iar->wait_ind2 = wait_ind;
1160
1161 if (num_req_refs >= 3)
1162 memcpy(&iar->req_ref3, &rqd_refs[2], sizeof(iar->req_ref3));
1163 else
1164 memcpy(&iar->req_ref3, &rqd_refs[0], sizeof(iar->req_ref3));
1165 iar->wait_ind3 = wait_ind;
1166
1167 if (num_req_refs >= 4)
1168 memcpy(&iar->req_ref4, &rqd_refs[3], sizeof(iar->req_ref4));
1169 else
1170 memcpy(&iar->req_ref4, &rqd_refs[0], sizeof(iar->req_ref4));
1171 iar->wait_ind4 = wait_ind;
1172
1173 return rsl_imm_assign_cmd(bts, sizeof(iar), (uint8_t *) iar);
1174}
1175
Harald Welte59b04682009-06-10 05:40:52 +08001176/* MS has requested a channel on the RACH */
1177static int rsl_rx_chan_rqd(struct msgb *msg)
1178{
1179 struct gsm_bts *bts = msg->trx->bts;
1180 struct abis_rsl_dchan_hdr *rqd_hdr = msgb_l2(msg);
1181 struct gsm48_req_ref *rqd_ref;
Harald Welte59b04682009-06-10 05:40:52 +08001182 enum gsm_chan_t lctype;
1183 enum gsm_chreq_reason_t chreq_reason;
1184 struct gsm_lchan *lchan;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001185 uint8_t rqd_ta;
Holger Hans Peter Freytherdb392032010-09-06 08:58:42 +08001186 int is_lu;
Harald Welte59b04682009-06-10 05:40:52 +08001187
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001188 uint16_t arfcn;
1189 uint8_t ts_number, subch;
Harald Welte59b04682009-06-10 05:40:52 +08001190
1191 /* parse request reference to be used in immediate assign */
1192 if (rqd_hdr->data[0] != RSL_IE_REQ_REFERENCE)
1193 return -EINVAL;
1194
1195 rqd_ref = (struct gsm48_req_ref *) &rqd_hdr->data[1];
1196
1197 /* parse access delay and use as TA */
1198 if (rqd_hdr->data[sizeof(struct gsm48_req_ref)+1] != RSL_IE_ACCESS_DELAY)
1199 return -EINVAL;
1200 rqd_ta = rqd_hdr->data[sizeof(struct gsm48_req_ref)+2];
1201
1202 /* determine channel type (SDCCH/TCH_F/TCH_H) based on
1203 * request reference RA */
Holger Hans Peter Freytherf0f37f12010-09-06 09:36:02 +08001204 lctype = get_ctype_by_chreq(bts->network, rqd_ref->ra);
1205 chreq_reason = get_reason_by_chreq(rqd_ref->ra, bts->network->neci);
Harald Welte59b04682009-06-10 05:40:52 +08001206
Pablo Neira Ayuso1c450742011-05-06 12:13:10 +02001207 osmo_counter_inc(bts->network->stats.chreq.total);
Harald Welte3edc5a92009-12-22 00:41:05 +01001208
Holger Hans Peter Freytherdb392032010-09-06 08:58:42 +08001209 /*
1210 * We want LOCATION UPDATES to succeed and will assign a TCH
1211 * if we have no SDCCH available.
1212 */
1213 is_lu = !!(chreq_reason == GSM_CHREQ_REASON_LOCATION_UPD);
1214
Harald Welte59b04682009-06-10 05:40:52 +08001215 /* check availability / allocate channel */
Holger Hans Peter Freytherdb392032010-09-06 08:58:42 +08001216 lchan = lchan_alloc(bts, lctype, is_lu);
Harald Welte59b04682009-06-10 05:40:52 +08001217 if (!lchan) {
Harald Welte (local)e0bb5fa2009-12-27 13:48:09 +01001218 LOGP(DRSL, LOGL_NOTICE, "BTS %d CHAN RQD: no resources for %s 0x%x\n",
Harald Welte (local)02204d02009-12-27 18:05:25 +01001219 msg->lchan->ts->trx->bts->nr, gsm_lchant_name(lctype), rqd_ref->ra);
Pablo Neira Ayuso1c450742011-05-06 12:13:10 +02001220 osmo_counter_inc(bts->network->stats.chreq.no_channel);
Harald Weltea00fdd72010-12-23 14:39:29 +01001221 /* FIXME gather multiple CHAN RQD and reject up to 4 at the same time */
1222 if (bts->network->T3122)
1223 rsl_send_imm_ass_rej(bts, 1, rqd_ref, bts->network->T3122 & 0xff);
Harald Welte59b04682009-06-10 05:40:52 +08001224 return -ENOMEM;
1225 }
1226
Harald Weltec88a4432009-12-29 10:44:17 +01001227 if (lchan->state != LCHAN_S_NONE)
1228 LOGP(DRSL, LOGL_NOTICE, "%s lchan_alloc() returned channel "
Harald Welteab2534c2009-12-29 10:52:38 +01001229 "in state %s\n", gsm_lchan_name(lchan),
1230 gsm_lchans_name(lchan->state));
Holger Hans Peter Freyther68914a02010-04-10 00:12:31 +02001231 rsl_lchan_set_state(lchan, LCHAN_S_ACT_REQ);
Harald Welte (local)c3be50c2009-12-27 18:12:29 +01001232
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001233 /* save the RACH data as we need it after the CHAN ACT ACK */
1234 lchan->rqd_ref = talloc_zero(bts, struct gsm48_req_ref);
1235 if (!lchan->rqd_ref) {
1236 LOGP(DRSL, LOGL_ERROR, "Failed to allocate gsm48_req_ref.\n");
1237 lchan_free(lchan);
1238 return -ENOMEM;
1239 }
1240
1241 memcpy(lchan->rqd_ref, rqd_ref, sizeof(*rqd_ref));
1242 lchan->rqd_ta = rqd_ta;
1243
Harald Welte59b04682009-06-10 05:40:52 +08001244 ts_number = lchan->ts->nr;
1245 arfcn = lchan->ts->trx->arfcn;
1246 subch = lchan->nr;
1247
Harald Welted2dd9de2009-08-30 15:37:11 +09001248 lchan->encr.alg_id = RSL_ENC_ALG_A5(0); /* no encryption */
Harald Welte (local)cbd46102009-08-13 10:14:26 +02001249 lchan->ms_power = ms_pwr_ctl_lvl(bts->band, bts->ms_max_power);
Harald Welte9a229e12009-08-10 00:45:40 +02001250 lchan->bs_power = 0; /* 0dB reduction, output power = Pn */
Harald Welte39274f42009-07-29 15:41:29 +02001251 lchan->rsl_cmode = RSL_CMOD_SPD_SIGN;
Harald Welte77234e12009-08-28 23:28:28 +09001252 lchan->tch_mode = GSM48_CMODE_SIGN;
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001253
1254 /* FIXME: Start another timer or assume the BTS sends a ACK/NACK? */
Harald Welteb90d7bd2009-12-17 00:31:10 +01001255 rsl_chan_activate_lchan(lchan, 0x00, rqd_ta, 0);
Harald Welte59b04682009-06-10 05:40:52 +08001256
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001257 DEBUGP(DRSL, "%s Activating ARFCN(%u) SS(%u) lctype %s "
1258 "r=%s ra=0x%02x\n", gsm_lchan_name(lchan), arfcn, subch,
1259 gsm_lchant_name(lchan->type), gsm_chreq_name(chreq_reason),
1260 rqd_ref->ra);
1261 return 0;
1262}
1263
1264static int rsl_send_imm_assignment(struct gsm_lchan *lchan)
1265{
1266 struct gsm_bts *bts = lchan->ts->trx->bts;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001267 uint8_t buf[GSM_MACBLOCK_LEN];
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001268 struct gsm48_imm_ass *ia = (struct gsm48_imm_ass *) buf;
1269
Harald Welte59b04682009-06-10 05:40:52 +08001270 /* create IMMEDIATE ASSIGN 04.08 messge */
laforgee06d5982010-06-20 15:18:46 +02001271 memset(ia, 0, sizeof(*ia));
laforge50312e82010-06-21 12:08:52 +02001272 /* we set ia->l2_plen once we know the length of the MA below */
laforgee06d5982010-06-20 15:18:46 +02001273 ia->proto_discr = GSM48_PDISC_RR;
1274 ia->msg_type = GSM48_MT_RR_IMM_ASS;
1275 ia->page_mode = GSM48_PM_SAME;
1276 gsm48_lchan2chan_desc(&ia->chan_desc, lchan);
Harald Weltea42a93f2010-06-14 22:26:10 +02001277
Harald Welte59b04682009-06-10 05:40:52 +08001278 /* use request reference extracted from CHAN_RQD */
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001279 memcpy(&ia->req_ref, lchan->rqd_ref, sizeof(ia->req_ref));
1280 ia->timing_advance = lchan->rqd_ta;
Harald Weltea42a93f2010-06-14 22:26:10 +02001281 if (!lchan->ts->hopping.enabled) {
laforgee06d5982010-06-20 15:18:46 +02001282 ia->mob_alloc_len = 0;
Harald Weltea42a93f2010-06-14 22:26:10 +02001283 } else {
laforgee06d5982010-06-20 15:18:46 +02001284 ia->mob_alloc_len = lchan->ts->hopping.ma_len;
1285 memcpy(ia->mob_alloc, lchan->ts->hopping.ma_data, ia->mob_alloc_len);
Harald Weltea42a93f2010-06-14 22:26:10 +02001286 }
Harald Welte07f32182010-06-28 18:41:27 +02001287 /* we need to subtract 1 byte from sizeof(*ia) since ia includes the l2_plen field */
1288 ia->l2_plen = GSM48_LEN2PLEN((sizeof(*ia)-1) + ia->mob_alloc_len);
Harald Welte59b04682009-06-10 05:40:52 +08001289
Harald Welte427dbc42009-08-10 00:26:10 +02001290 /* Start timer T3101 to wait for GSM48_MT_RR_PAG_RESP */
1291 lchan->T3101.cb = t3101_expired;
1292 lchan->T3101.data = lchan;
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +02001293 osmo_timer_schedule(&lchan->T3101, bts->network->T3101, 0);
Harald Welte59b04682009-06-10 05:40:52 +08001294
1295 /* send IMMEDIATE ASSIGN CMD on RSL to BTS (to send on CCCH to MS) */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001296 return rsl_imm_assign_cmd(bts, sizeof(*ia)+ia->mob_alloc_len, (uint8_t *) ia);
Harald Welte59b04682009-06-10 05:40:52 +08001297}
1298
1299/* MS has requested a channel on the RACH */
1300static int rsl_rx_ccch_load(struct msgb *msg)
1301{
1302 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001303 uint16_t pg_buf_space;
1304 uint16_t rach_slot_count = -1;
1305 uint16_t rach_busy_count = -1;
1306 uint16_t rach_access_count = -1;
Harald Welte59b04682009-06-10 05:40:52 +08001307
1308 switch (rslh->data[0]) {
1309 case RSL_IE_PAGING_LOAD:
1310 pg_buf_space = rslh->data[1] << 8 | rslh->data[2];
Harald Welte008a4922010-04-19 10:24:07 +02001311 if (is_ipaccess_bts(msg->trx->bts) && pg_buf_space == 0xffff) {
1312 /* paging load below configured threshold, use 50 as default */
1313 pg_buf_space = 50;
1314 }
Harald Welte59b04682009-06-10 05:40:52 +08001315 paging_update_buffer_space(msg->trx->bts, pg_buf_space);
1316 break;
1317 case RSL_IE_RACH_LOAD:
1318 if (msg->data_len >= 7) {
1319 rach_slot_count = rslh->data[2] << 8 | rslh->data[3];
1320 rach_busy_count = rslh->data[4] << 8 | rslh->data[5];
1321 rach_access_count = rslh->data[6] << 8 | rslh->data[7];
1322 }
1323 break;
1324 default:
1325 break;
1326 }
1327
1328 return 0;
1329}
1330
1331static int abis_rsl_rx_cchan(struct msgb *msg)
1332{
1333 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
1334 int rc = 0;
1335
1336 msg->lchan = lchan_lookup(msg->trx, rslh->chan_nr);
1337
1338 switch (rslh->c.msg_type) {
1339 case RSL_MT_CHAN_RQD:
1340 /* MS has requested a channel on the RACH */
1341 rc = rsl_rx_chan_rqd(msg);
1342 break;
1343 case RSL_MT_CCCH_LOAD_IND:
1344 /* current load on the CCCH */
1345 rc = rsl_rx_ccch_load(msg);
1346 break;
1347 case RSL_MT_DELETE_IND:
1348 /* CCCH overloaded, IMM_ASSIGN was dropped */
1349 case RSL_MT_CBCH_LOAD_IND:
1350 /* current load on the CBCH */
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001351 LOGP(DRSL, LOGL_NOTICE, "Unimplemented Abis RSL TRX message "
1352 "type 0x%02x\n", rslh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001353 break;
1354 default:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001355 LOGP(DRSL, LOGL_NOTICE, "Unknown Abis RSL TRX message type "
1356 "0x%02x\n", rslh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001357 return -EINVAL;
1358 }
1359
1360 return rc;
1361}
1362
1363static int rsl_rx_rll_err_ind(struct msgb *msg)
1364{
1365 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001366 uint8_t *rlm_cause = rllh->data;
Harald Welte59b04682009-06-10 05:40:52 +08001367
Harald Welte (local)bd76cce2009-12-26 23:55:00 +01001368 LOGP(DRLL, LOGL_ERROR, "%s ERROR INDICATION cause=%s\n",
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001369 gsm_lchan_name(msg->lchan),
Harald Welteb30935e2010-03-25 12:13:02 +08001370 rsl_rlm_cause_name(rlm_cause[1]));
Harald Welteed9a5ab2009-08-09 13:47:35 +02001371
1372 rll_indication(msg->lchan, rllh->link_id, BSC_RLLR_IND_ERR_IND);
Harald Welte (local)bd76cce2009-12-26 23:55:00 +01001373
Holger Hans Peter Freyther27942e92010-04-17 06:48:29 +02001374 if (rlm_cause[1] == RLL_CAUSE_T200_EXPIRED) {
Pablo Neira Ayuso1c450742011-05-06 12:13:10 +02001375 osmo_counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rll_err);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +08001376 return rsl_rf_chan_release(msg->lchan, 1);
Holger Hans Peter Freyther27942e92010-04-17 06:48:29 +02001377 }
Harald Welte692f5852009-07-04 09:40:05 +02001378
Harald Welte59b04682009-06-10 05:40:52 +08001379 return 0;
1380}
1381
Holger Hans Peter Freyther65f08522010-04-08 22:39:34 +02001382static void rsl_handle_release(struct gsm_lchan *lchan)
1383{
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001384 int sapi;
Holger Hans Peter Freyther4a00c062010-05-31 21:33:15 +08001385 struct gsm_bts *bts;
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001386
1387 /* maybe we have only brought down one RLL */
Holger Hans Peter Freytherd26cbc82010-04-08 22:47:44 +02001388 if (lchan->state != LCHAN_S_REL_REQ)
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001389 return;
1390
1391 for (sapi = 0; sapi < ARRAY_SIZE(lchan->sapis); ++sapi) {
1392 if (lchan->sapis[sapi] == LCHAN_SAPI_UNUSED)
1393 continue;
Harald Welte497aa982010-12-24 12:51:07 +01001394 LOGP(DRSL, LOGL_DEBUG, "%s waiting for SAPI=%d to be released.\n",
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001395 gsm_lchan_name(lchan), sapi);
1396 return;
1397 }
1398
Holger Hans Peter Freytherd26cbc82010-04-08 22:47:44 +02001399
1400
Holger Hans Peter Freyther4a00c062010-05-31 21:33:15 +08001401 /* wait a bit to send the RF Channel Release */
1402 lchan->T3111.cb = t3111_expired;
1403 lchan->T3111.data = lchan;
1404 bts = lchan->ts->trx->bts;
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +02001405 osmo_timer_schedule(&lchan->T3111, bts->network->T3111, 0);
Holger Hans Peter Freyther65f08522010-04-08 22:39:34 +02001406}
1407
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +02001408/* ESTABLISH INDICATION, LOCATION AREA UPDATE REQUEST
Harald Welte59b04682009-06-10 05:40:52 +08001409 0x02, 0x06,
1410 0x01, 0x20,
1411 0x02, 0x00,
1412 0x0b, 0x00, 0x0f, 0x05, 0x08, ... */
1413
1414static int abis_rsl_rx_rll(struct msgb *msg)
1415{
1416 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
1417 int rc = 0;
1418 char *ts_name;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001419 uint8_t sapi = rllh->link_id & 7;
Harald Welte59b04682009-06-10 05:40:52 +08001420
1421 msg->lchan = lchan_lookup(msg->trx, rllh->chan_nr);
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001422 ts_name = gsm_lchan_name(msg->lchan);
Harald Weltede4477a2009-12-24 12:20:20 +01001423 DEBUGP(DRLL, "%s SAPI=%u ", ts_name, sapi);
Harald Welte59b04682009-06-10 05:40:52 +08001424
1425 switch (rllh->c.msg_type) {
1426 case RSL_MT_DATA_IND:
1427 DEBUGPC(DRLL, "DATA INDICATION\n");
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +02001428 if (msgb_l2len(msg) >
Harald Welte59b04682009-06-10 05:40:52 +08001429 sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) &&
1430 rllh->data[0] == RSL_IE_L3_INFO) {
1431 msg->l3h = &rllh->data[3];
Harald Welte (local)64994ce2009-08-14 11:41:12 +02001432 return gsm0408_rcvmsg(msg, rllh->link_id);
Harald Welte59b04682009-06-10 05:40:52 +08001433 }
1434 break;
1435 case RSL_MT_EST_IND:
1436 DEBUGPC(DRLL, "ESTABLISH INDICATION\n");
Harald Welte427dbc42009-08-10 00:26:10 +02001437 /* lchan is established, stop T3101 */
Holger Hans Peter Freytherd8318052009-10-28 14:23:39 +01001438 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_MS;
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +02001439 osmo_timer_del(&msg->lchan->T3101);
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +02001440 if (msgb_l2len(msg) >
Harald Welte59b04682009-06-10 05:40:52 +08001441 sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) &&
1442 rllh->data[0] == RSL_IE_L3_INFO) {
1443 msg->l3h = &rllh->data[3];
Harald Welte (local)64994ce2009-08-14 11:41:12 +02001444 return gsm0408_rcvmsg(msg, rllh->link_id);
Harald Welte59b04682009-06-10 05:40:52 +08001445 }
1446 break;
Harald Welteed9a5ab2009-08-09 13:47:35 +02001447 case RSL_MT_EST_CONF:
Harald Welte61402172009-08-09 14:13:58 +02001448 DEBUGPC(DRLL, "ESTABLISH CONFIRM\n");
Holger Hans Peter Freytherd8318052009-10-28 14:23:39 +01001449 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_NET;
Harald Welteed9a5ab2009-08-09 13:47:35 +02001450 rll_indication(msg->lchan, rllh->link_id,
1451 BSC_RLLR_IND_EST_CONF);
1452 break;
Harald Welte59b04682009-06-10 05:40:52 +08001453 case RSL_MT_REL_IND:
Harald Welte0f2e3c12009-08-08 13:15:07 +02001454 /* BTS informs us of having received DISC from MS */
Harald Welteb6601442009-08-04 02:50:21 +02001455 DEBUGPC(DRLL, "RELEASE INDICATION\n");
Holger Hans Peter Freytherd8318052009-10-28 14:23:39 +01001456 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_UNUSED;
Harald Welteed9a5ab2009-08-09 13:47:35 +02001457 rll_indication(msg->lchan, rllh->link_id,
1458 BSC_RLLR_IND_REL_IND);
Holger Hans Peter Freyther65f08522010-04-08 22:39:34 +02001459 rsl_handle_release(msg->lchan);
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001460 rsl_lchan_rll_release(msg->lchan, rllh->link_id);
Harald Welte59b04682009-06-10 05:40:52 +08001461 break;
1462 case RSL_MT_REL_CONF:
Harald Welte0f2e3c12009-08-08 13:15:07 +02001463 /* BTS informs us of having received UA from MS,
1464 * in response to DISC that we've sent earlier */
Harald Welteb6601442009-08-04 02:50:21 +02001465 DEBUGPC(DRLL, "RELEASE CONFIRMATION\n");
Holger Hans Peter Freytherd8318052009-10-28 14:23:39 +01001466 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_UNUSED;
Holger Hans Peter Freyther65f08522010-04-08 22:39:34 +02001467 rsl_handle_release(msg->lchan);
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001468 rsl_lchan_rll_release(msg->lchan, rllh->link_id);
Harald Welte59b04682009-06-10 05:40:52 +08001469 break;
1470 case RSL_MT_ERROR_IND:
Harald Welte59b04682009-06-10 05:40:52 +08001471 rc = rsl_rx_rll_err_ind(msg);
1472 break;
1473 case RSL_MT_UNIT_DATA_IND:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001474 LOGP(DRLL, LOGL_NOTICE, "unimplemented Abis RLL message "
1475 "type 0x%02x\n", rllh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001476 break;
1477 default:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001478 LOGP(DRLL, LOGL_NOTICE, "unknown Abis RLL message "
1479 "type 0x%02x\n", rllh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001480 }
Harald Welte59b04682009-06-10 05:40:52 +08001481 return rc;
1482}
1483
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001484static uint8_t ipa_smod_s_for_lchan(struct gsm_lchan *lchan)
Harald Welte98d79f92009-07-28 18:11:56 +02001485{
Harald Welteb284b472009-12-02 01:58:23 +05301486 switch (lchan->tch_mode) {
Harald Welte98d79f92009-07-28 18:11:56 +02001487 case GSM48_CMODE_SPEECH_V1:
Harald Welteb284b472009-12-02 01:58:23 +05301488 switch (lchan->type) {
1489 case GSM_LCHAN_TCH_F:
1490 return 0x00;
1491 case GSM_LCHAN_TCH_H:
1492 return 0x03;
1493 default:
1494 break;
1495 }
Harald Welte98d79f92009-07-28 18:11:56 +02001496 case GSM48_CMODE_SPEECH_EFR:
Harald Welteb284b472009-12-02 01:58:23 +05301497 switch (lchan->type) {
1498 case GSM_LCHAN_TCH_F:
1499 return 0x01;
1500 /* there's no half-rate EFR */
1501 default:
1502 break;
1503 }
Harald Welte98d79f92009-07-28 18:11:56 +02001504 case GSM48_CMODE_SPEECH_AMR:
Harald Welteb284b472009-12-02 01:58:23 +05301505 switch (lchan->type) {
1506 case GSM_LCHAN_TCH_F:
1507 return 0x02;
1508 case GSM_LCHAN_TCH_H:
1509 return 0x05;
1510 default:
1511 break;
1512 }
1513 default:
1514 break;
Harald Welte98d79f92009-07-28 18:11:56 +02001515 }
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001516 LOGP(DRSL, LOGL_ERROR, "Cannot determine ip.access speech mode for "
Harald Welteb284b472009-12-02 01:58:23 +05301517 "tch_mode == 0x%02x\n", lchan->tch_mode);
Harald Welte98d79f92009-07-28 18:11:56 +02001518 return 0;
Harald Welte98d79f92009-07-28 18:11:56 +02001519}
1520
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001521static uint8_t ipa_rtp_pt_for_lchan(struct gsm_lchan *lchan)
Sylvain Munaut1338a552009-12-20 22:06:40 +01001522{
Holger Hans Peter Freyther6651b692010-11-14 21:09:08 +01001523 struct gsm_network *net = lchan->ts->trx->bts->network;
1524
1525 /* allow to hardcode the rtp payload */
1526 if (net->hardcoded_rtp_payload != 0)
1527 return net->hardcoded_rtp_payload;
1528
Sylvain Munaut1338a552009-12-20 22:06:40 +01001529 switch (lchan->tch_mode) {
1530 case GSM48_CMODE_SPEECH_V1:
1531 switch (lchan->type) {
1532 case GSM_LCHAN_TCH_F:
1533 return RTP_PT_GSM_FULL;
1534 case GSM_LCHAN_TCH_H:
1535 return RTP_PT_GSM_HALF;
1536 default:
1537 break;
1538 }
1539 case GSM48_CMODE_SPEECH_EFR:
1540 switch (lchan->type) {
1541 case GSM_LCHAN_TCH_F:
1542 return RTP_PT_GSM_EFR;
1543 /* there's no half-rate EFR */
1544 default:
1545 break;
1546 }
1547 case GSM48_CMODE_SPEECH_AMR:
1548 switch (lchan->type) {
1549 case GSM_LCHAN_TCH_F:
1550 return RTP_PT_AMR_FULL;
1551 case GSM_LCHAN_TCH_H:
1552 return RTP_PT_AMR_HALF;
1553 default:
1554 break;
1555 }
1556 default:
1557 break;
1558 }
1559 LOGP(DRSL, LOGL_ERROR, "Cannot determine ip.access rtp payload type for "
1560 "tch_mode == 0x%02x\n & lchan_type == %d",
1561 lchan->tch_mode, lchan->type);
1562 return 0;
1563}
1564
Harald Welte59b04682009-06-10 05:40:52 +08001565/* ip.access specific RSL extensions */
Harald Weltebffa4992009-12-19 16:42:06 +01001566static void ipac_parse_rtp(struct gsm_lchan *lchan, struct tlv_parsed *tv)
1567{
1568 struct in_addr ip;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001569 uint16_t port, conn_id;
Harald Weltebffa4992009-12-19 16:42:06 +01001570
1571 if (TLVP_PRESENT(tv, RSL_IE_IPAC_LOCAL_IP)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001572 ip.s_addr = *((uint32_t *) TLVP_VAL(tv, RSL_IE_IPAC_LOCAL_IP));
Harald Weltebffa4992009-12-19 16:42:06 +01001573 DEBUGPC(DRSL, "LOCAL_IP=%s ", inet_ntoa(ip));
1574 lchan->abis_ip.bound_ip = ntohl(ip.s_addr);
1575 }
1576
1577 if (TLVP_PRESENT(tv, RSL_IE_IPAC_LOCAL_PORT)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001578 port = *((uint16_t *) TLVP_VAL(tv, RSL_IE_IPAC_LOCAL_PORT));
Harald Weltebffa4992009-12-19 16:42:06 +01001579 port = ntohs(port);
1580 DEBUGPC(DRSL, "LOCAL_PORT=%u ", port);
1581 lchan->abis_ip.bound_port = port;
1582 }
1583
1584 if (TLVP_PRESENT(tv, RSL_IE_IPAC_CONN_ID)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001585 conn_id = *((uint16_t *) TLVP_VAL(tv, RSL_IE_IPAC_CONN_ID));
Harald Weltebffa4992009-12-19 16:42:06 +01001586 conn_id = ntohs(conn_id);
1587 DEBUGPC(DRSL, "CON_ID=%u ", conn_id);
1588 lchan->abis_ip.conn_id = conn_id;
1589 }
1590
1591 if (TLVP_PRESENT(tv, RSL_IE_IPAC_RTP_PAYLOAD2)) {
1592 lchan->abis_ip.rtp_payload2 =
1593 *TLVP_VAL(tv, RSL_IE_IPAC_RTP_PAYLOAD2);
1594 DEBUGPC(DRSL, "RTP_PAYLOAD2=0x%02x ",
1595 lchan->abis_ip.rtp_payload2);
1596 }
1597
1598 if (TLVP_PRESENT(tv, RSL_IE_IPAC_SPEECH_MODE)) {
1599 lchan->abis_ip.speech_mode =
1600 *TLVP_VAL(tv, RSL_IE_IPAC_SPEECH_MODE);
1601 DEBUGPC(DRSL, "speech_mode=0x%02x ",
1602 lchan->abis_ip.speech_mode);
1603 }
1604
1605 if (TLVP_PRESENT(tv, RSL_IE_IPAC_REMOTE_IP)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001606 ip.s_addr = *((uint32_t *) TLVP_VAL(tv, RSL_IE_IPAC_REMOTE_IP));
Harald Weltebffa4992009-12-19 16:42:06 +01001607 DEBUGPC(DRSL, "REMOTE_IP=%s ", inet_ntoa(ip));
1608 lchan->abis_ip.connect_ip = ntohl(ip.s_addr);
1609 }
1610
1611 if (TLVP_PRESENT(tv, RSL_IE_IPAC_REMOTE_PORT)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001612 port = *((uint16_t *) TLVP_VAL(tv, RSL_IE_IPAC_REMOTE_PORT));
Harald Weltebffa4992009-12-19 16:42:06 +01001613 port = ntohs(port);
1614 DEBUGPC(DRSL, "REMOTE_PORT=%u ", port);
1615 lchan->abis_ip.connect_port = port;
1616 }
1617}
1618
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001619int rsl_ipacc_crcx(struct gsm_lchan *lchan)
Harald Welte59b04682009-06-10 05:40:52 +08001620{
1621 struct msgb *msg = rsl_msgb_alloc();
1622 struct abis_rsl_dchan_hdr *dh;
1623
1624 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001625 init_dchan_hdr(dh, RSL_MT_IPAC_CRCX);
Harald Welte59b04682009-06-10 05:40:52 +08001626 dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
Harald Weltee6d51f92011-06-25 10:02:33 +02001627 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001628
Harald Welte98d79f92009-07-28 18:11:56 +02001629 /* 0x1- == receive-only, 0x-1 == EFR codec */
Harald Weltebffa4992009-12-19 16:42:06 +01001630 lchan->abis_ip.speech_mode = 0x10 | ipa_smod_s_for_lchan(lchan);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001631 lchan->abis_ip.rtp_payload = ipa_rtp_pt_for_lchan(lchan);
Harald Weltebffa4992009-12-19 16:42:06 +01001632 msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, lchan->abis_ip.speech_mode);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001633 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD, lchan->abis_ip.rtp_payload);
Harald Welte98d79f92009-07-28 18:11:56 +02001634
Sylvain Munaut1338a552009-12-20 22:06:40 +01001635 DEBUGP(DRSL, "%s IPAC_BIND speech_mode=0x%02x RTP_PAYLOAD=%d\n",
1636 gsm_lchan_name(lchan), lchan->abis_ip.speech_mode,
1637 lchan->abis_ip.rtp_payload);
Harald Welte98d79f92009-07-28 18:11:56 +02001638
Harald Welte59b04682009-06-10 05:40:52 +08001639 msg->trx = lchan->ts->trx;
1640
1641 return abis_rsl_sendmsg(msg);
1642}
1643
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001644int rsl_ipacc_mdcx(struct gsm_lchan *lchan, uint32_t ip, uint16_t port,
1645 uint8_t rtp_payload2)
Harald Welte59b04682009-06-10 05:40:52 +08001646{
1647 struct msgb *msg = rsl_msgb_alloc();
1648 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001649 uint32_t *att_ip;
Harald Welte98d79f92009-07-28 18:11:56 +02001650 struct in_addr ia;
Harald Welte59b04682009-06-10 05:40:52 +08001651
1652 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001653 init_dchan_hdr(dh, RSL_MT_IPAC_MDCX);
Harald Welte59b04682009-06-10 05:40:52 +08001654 dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
Harald Weltee6d51f92011-06-25 10:02:33 +02001655 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001656
Harald Weltebffa4992009-12-19 16:42:06 +01001657 /* we need to store these now as MDCX_ACK does not return them :( */
1658 lchan->abis_ip.rtp_payload2 = rtp_payload2;
1659 lchan->abis_ip.connect_port = port;
1660 lchan->abis_ip.connect_ip = ip;
1661
Harald Weltefb4a9e92009-07-29 12:12:18 +02001662 /* 0x0- == both directions, 0x-1 == EFR codec */
Harald Weltebffa4992009-12-19 16:42:06 +01001663 lchan->abis_ip.speech_mode = 0x00 | ipa_smod_s_for_lchan(lchan);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001664 lchan->abis_ip.rtp_payload = ipa_rtp_pt_for_lchan(lchan);
Harald Weltefb4a9e92009-07-29 12:12:18 +02001665
Harald Welte98d79f92009-07-28 18:11:56 +02001666 ia.s_addr = htonl(ip);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001667 DEBUGP(DRSL, "%s IPAC_MDCX IP=%s PORT=%d RTP_PAYLOAD=%d RTP_PAYLOAD2=%d "
1668 "CONN_ID=%d speech_mode=0x%02x\n", gsm_lchan_name(lchan),
1669 inet_ntoa(ia), port, lchan->abis_ip.rtp_payload, rtp_payload2,
1670 lchan->abis_ip.conn_id, lchan->abis_ip.speech_mode);
Harald Welte98d79f92009-07-28 18:11:56 +02001671
Harald Weltebffa4992009-12-19 16:42:06 +01001672 msgb_tv16_put(msg, RSL_IE_IPAC_CONN_ID, lchan->abis_ip.conn_id);
1673 msgb_v_put(msg, RSL_IE_IPAC_REMOTE_IP);
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001674 att_ip = (uint32_t *) msgb_put(msg, sizeof(ip));
Harald Weltebffa4992009-12-19 16:42:06 +01001675 *att_ip = ia.s_addr;
1676 msgb_tv16_put(msg, RSL_IE_IPAC_REMOTE_PORT, port);
1677 msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, lchan->abis_ip.speech_mode);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001678 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD, lchan->abis_ip.rtp_payload);
Harald Welte98d79f92009-07-28 18:11:56 +02001679 if (rtp_payload2)
1680 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD2, rtp_payload2);
1681
Harald Welte59b04682009-06-10 05:40:52 +08001682 msg->trx = lchan->ts->trx;
1683
1684 return abis_rsl_sendmsg(msg);
1685}
1686
Harald Welte9947d9f2009-12-20 16:51:09 +01001687/* tell BTS to connect RTP stream to our local RTP socket */
1688int rsl_ipacc_mdcx_to_rtpsock(struct gsm_lchan *lchan)
1689{
1690 struct rtp_socket *rs = lchan->abis_ip.rtp_socket;
1691 int rc;
1692
1693 rc = rsl_ipacc_mdcx(lchan, ntohl(rs->rtp.sin_local.sin_addr.s_addr),
1694 ntohs(rs->rtp.sin_local.sin_port),
1695 /* FIXME: use RTP payload of bound socket, not BTS*/
1696 lchan->abis_ip.rtp_payload2);
1697
1698 return rc;
1699}
1700
Harald Welte6f40df02010-12-23 12:59:52 +01001701int rsl_ipacc_pdch_activate(struct gsm_bts_trx_ts *ts, int act)
Harald Welteaed946e2009-10-24 10:29:22 +02001702{
1703 struct msgb *msg = rsl_msgb_alloc();
1704 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001705 uint8_t msg_type;
Harald Welte2b361522010-03-28 14:42:09 +08001706
1707 if (act)
1708 msg_type = RSL_MT_IPAC_PDCH_ACT;
1709 else
1710 msg_type = RSL_MT_IPAC_PDCH_DEACT;
Harald Welteaed946e2009-10-24 10:29:22 +02001711
1712 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Harald Welte2b361522010-03-28 14:42:09 +08001713 init_dchan_hdr(dh, msg_type);
Harald Welteaed946e2009-10-24 10:29:22 +02001714 dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
Harald Weltee6d51f92011-06-25 10:02:33 +02001715 dh->chan_nr = gsm_ts2chan_nr(ts, 0);
Harald Welteaed946e2009-10-24 10:29:22 +02001716
Harald Welte6f40df02010-12-23 12:59:52 +01001717 DEBUGP(DRSL, "%s IPAC_PDCH_%sACT\n", gsm_ts_name(ts),
Harald Welte2b361522010-03-28 14:42:09 +08001718 act ? "" : "DE");
Harald Welteaed946e2009-10-24 10:29:22 +02001719
Harald Welte6f40df02010-12-23 12:59:52 +01001720 msg->trx = ts->trx;
Harald Welteaed946e2009-10-24 10:29:22 +02001721
1722 return abis_rsl_sendmsg(msg);
1723}
1724
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001725static int abis_rsl_rx_ipacc_crcx_ack(struct msgb *msg)
Harald Welte59b04682009-06-10 05:40:52 +08001726{
1727 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1728 struct tlv_parsed tv;
Harald Welte87504212009-12-02 01:56:49 +05301729 struct gsm_lchan *lchan = msg->lchan;
Harald Welte59b04682009-06-10 05:40:52 +08001730
1731 /* the BTS has acknowledged a local bind, it now tells us the IP
1732 * address and port number to which it has bound the given logical
1733 * channel */
1734
1735 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
1736 if (!TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_PORT) ||
1737 !TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_IP) ||
Harald Welteb9498952009-07-12 09:45:05 +02001738 !TLVP_PRESENT(&tv, RSL_IE_IPAC_CONN_ID)) {
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001739 LOGP(DRSL, LOGL_NOTICE, "mandatory IE missing");
Harald Welte59b04682009-06-10 05:40:52 +08001740 return -EINVAL;
1741 }
Harald Welte50517742009-12-20 15:42:44 +01001742
Harald Weltebffa4992009-12-19 16:42:06 +01001743 ipac_parse_rtp(lchan, &tv);
Harald Welte50517742009-12-20 15:42:44 +01001744
Pablo Neira Ayusoef717c62011-05-06 12:12:31 +02001745 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_CRCX_ACK, msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001746
1747 return 0;
1748}
1749
Harald Weltebffa4992009-12-19 16:42:06 +01001750static int abis_rsl_rx_ipacc_mdcx_ack(struct msgb *msg)
1751{
1752 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1753 struct tlv_parsed tv;
1754 struct gsm_lchan *lchan = msg->lchan;
1755
1756 /* the BTS has acknowledged a remote connect request and
1757 * it now tells us the IP address and port number to which it has
1758 * connected the given logical channel */
1759
1760 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
1761 ipac_parse_rtp(lchan, &tv);
Pablo Neira Ayusoef717c62011-05-06 12:12:31 +02001762 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_MDCX_ACK, msg->lchan);
Harald Weltebffa4992009-12-19 16:42:06 +01001763
1764 return 0;
1765}
1766
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001767static int abis_rsl_rx_ipacc_dlcx_ind(struct msgb *msg)
Harald Welte59b04682009-06-10 05:40:52 +08001768{
1769 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1770 struct tlv_parsed tv;
1771
1772 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
Harald Welte59b04682009-06-10 05:40:52 +08001773
Harald Weltef1a168d2009-07-28 17:58:09 +02001774 if (TLVP_PRESENT(&tv, RSL_IE_CAUSE))
Harald Weltede4477a2009-12-24 12:20:20 +01001775 print_rsl_cause(LOGL_DEBUG, TLVP_VAL(&tv, RSL_IE_CAUSE),
Harald Weltef1a168d2009-07-28 17:58:09 +02001776 TLVP_LEN(&tv, RSL_IE_CAUSE));
Harald Welte59b04682009-06-10 05:40:52 +08001777
Pablo Neira Ayusoef717c62011-05-06 12:12:31 +02001778 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_DLCX_IND, msg->lchan);
Harald Welteba4e58d2009-07-28 18:02:05 +02001779
Harald Welte59b04682009-06-10 05:40:52 +08001780 return 0;
1781}
1782
1783static int abis_rsl_rx_ipacc(struct msgb *msg)
1784{
1785 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
Harald Weltede4477a2009-12-24 12:20:20 +01001786 char *ts_name;
Harald Welte59b04682009-06-10 05:40:52 +08001787 int rc = 0;
1788
1789 msg->lchan = lchan_lookup(msg->trx, rllh->chan_nr);
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001790 ts_name = gsm_lchan_name(msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001791
1792 switch (rllh->c.msg_type) {
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001793 case RSL_MT_IPAC_CRCX_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001794 DEBUGP(DRSL, "%s IPAC_CRCX_ACK ", ts_name);
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001795 rc = abis_rsl_rx_ipacc_crcx_ack(msg);
Harald Welte59b04682009-06-10 05:40:52 +08001796 break;
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001797 case RSL_MT_IPAC_CRCX_NACK:
Harald Welte59b04682009-06-10 05:40:52 +08001798 /* somehow the BTS was unable to bind the lchan to its local
1799 * port?!? */
Harald Weltede4477a2009-12-24 12:20:20 +01001800 LOGP(DRSL, LOGL_ERROR, "%s IPAC_CRCX_NACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001801 break;
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001802 case RSL_MT_IPAC_MDCX_ACK:
Harald Welte59b04682009-06-10 05:40:52 +08001803 /* the BTS tells us that a connect operation was successful */
Harald Weltede4477a2009-12-24 12:20:20 +01001804 DEBUGP(DRSL, "%s IPAC_MDCX_ACK ", ts_name);
Harald Weltebffa4992009-12-19 16:42:06 +01001805 rc = abis_rsl_rx_ipacc_mdcx_ack(msg);
Harald Welte59b04682009-06-10 05:40:52 +08001806 break;
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001807 case RSL_MT_IPAC_MDCX_NACK:
Harald Welte59b04682009-06-10 05:40:52 +08001808 /* somehow the BTS was unable to connect the lchan to a remote
1809 * port */
Harald Weltede4477a2009-12-24 12:20:20 +01001810 LOGP(DRSL, LOGL_ERROR, "%s IPAC_MDCX_NACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001811 break;
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001812 case RSL_MT_IPAC_DLCX_IND:
Harald Weltede4477a2009-12-24 12:20:20 +01001813 DEBUGP(DRSL, "%s IPAC_DLCX_IND ", ts_name);
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001814 rc = abis_rsl_rx_ipacc_dlcx_ind(msg);
Harald Welte59b04682009-06-10 05:40:52 +08001815 break;
1816 default:
Harald Weltede4477a2009-12-24 12:20:20 +01001817 LOGP(DRSL, LOGL_NOTICE, "Unknown ip.access msg_type 0x%02x\n",
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001818 rllh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001819 break;
1820 }
1821 DEBUGPC(DRSL, "\n");
1822
1823 return rc;
1824}
1825
1826
1827/* Entry-point where L2 RSL from BTS enters */
1828int abis_rsl_rcvmsg(struct msgb *msg)
1829{
Holger Hans Peter Freytherc7d94092009-11-20 15:14:01 +01001830 struct abis_rsl_common_hdr *rslh;
Harald Welte59b04682009-06-10 05:40:52 +08001831 int rc = 0;
1832
Holger Hans Peter Freytherc7d94092009-11-20 15:14:01 +01001833 if (!msg) {
1834 DEBUGP(DRSL, "Empty RSL msg?..\n");
1835 return -1;
1836 }
1837
1838 if (msgb_l2len(msg) < sizeof(*rslh)) {
1839 DEBUGP(DRSL, "Truncated RSL message with l2len: %u\n", msgb_l2len(msg));
1840 return -1;
1841 }
1842
1843 rslh = msgb_l2(msg);
1844
Harald Welte59b04682009-06-10 05:40:52 +08001845 switch (rslh->msg_discr & 0xfe) {
1846 case ABIS_RSL_MDISC_RLL:
1847 rc = abis_rsl_rx_rll(msg);
1848 break;
1849 case ABIS_RSL_MDISC_DED_CHAN:
1850 rc = abis_rsl_rx_dchan(msg);
1851 break;
1852 case ABIS_RSL_MDISC_COM_CHAN:
1853 rc = abis_rsl_rx_cchan(msg);
1854 break;
1855 case ABIS_RSL_MDISC_TRX:
1856 rc = abis_rsl_rx_trx(msg);
1857 break;
1858 case ABIS_RSL_MDISC_LOC:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001859 LOGP(DRSL, LOGL_NOTICE, "unimplemented RSL msg disc 0x%02x\n",
Harald Welte59b04682009-06-10 05:40:52 +08001860 rslh->msg_discr);
1861 break;
1862 case ABIS_RSL_MDISC_IPACCESS:
1863 rc = abis_rsl_rx_ipacc(msg);
1864 break;
1865 default:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001866 LOGP(DRSL, LOGL_NOTICE, "unknown RSL message discriminator "
1867 "0x%02x\n", rslh->msg_discr);
Harald Welte59b04682009-06-10 05:40:52 +08001868 return -EINVAL;
1869 }
1870 msgb_free(msg);
1871 return rc;
1872}
1873
Holger Hans Peter Freytherb67f4082010-07-21 15:54:32 +08001874int rsl_sms_cb_command(struct gsm_bts *bts, uint8_t chan_number,
1875 uint8_t cb_command, const uint8_t *data, int len)
1876{
1877 struct abis_rsl_dchan_hdr *dh;
1878 struct msgb *cb_cmd;
1879
1880 cb_cmd = rsl_msgb_alloc();
1881 if (!cb_cmd)
1882 return -1;
1883
1884 dh = (struct abis_rsl_dchan_hdr *) msgb_put(cb_cmd, sizeof*dh);
1885 init_dchan_hdr(dh, RSL_MT_SMS_BC_CMD);
1886 dh->chan_nr = RSL_CHAN_SDCCH4_ACCH; /* TODO: check the chan config */
1887
1888 msgb_tv_put(cb_cmd, RSL_IE_CB_CMD_TYPE, cb_command);
1889 msgb_tlv_put(cb_cmd, RSL_IE_SMSCB_MSG, len, data);
1890
1891 cb_cmd->trx = bts->c0;
1892
1893 return abis_rsl_sendmsg(cb_cmd);
1894}