blob: 95d5c1ea7dcd54a2fbe8ee6bff9789ba697b5a12 [file] [log] [blame]
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +02001/* GSM Radio Signalling Link messages on the A-bis interface
Harald Welte52b1f982008-12-23 20:25:15 +00002 * 3GPP TS 08.58 version 8.6.0 Release 1999 / ETSI TS 100 596 V8.6.0 */
3
Harald Welte3c9c5f92010-03-04 10:33:10 +01004/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
Harald Welte8470bf22008-12-25 23:28:35 +00005 *
Harald Welte52b1f982008-12-23 20:25:15 +00006 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
Harald Welte9af6ddf2011-01-01 15:25:50 +01009 * it under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
Harald Welte52b1f982008-12-23 20:25:15 +000011 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Harald Welte9af6ddf2011-01-01 15:25:50 +010016 * GNU Affero General Public License for more details.
Harald Welte52b1f982008-12-23 20:25:15 +000017 *
Harald Welte9af6ddf2011-01-01 15:25:50 +010018 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Harald Welte52b1f982008-12-23 20:25:15 +000020 *
21 */
22
23#include <stdio.h>
Harald Welte8470bf22008-12-25 23:28:35 +000024#include <stdlib.h>
Harald Welte52b1f982008-12-23 20:25:15 +000025#include <errno.h>
Harald Welte75099262009-02-16 21:12:08 +000026#include <netinet/in.h>
Harald Welte167df882009-02-17 14:35:45 +000027#include <arpa/inet.h>
Harald Welte52b1f982008-12-23 20:25:15 +000028
Harald Welte8470bf22008-12-25 23:28:35 +000029#include <openbsc/gsm_data.h>
30#include <openbsc/gsm_04_08.h>
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010031#include <osmocom/gsm/gsm_utils.h>
Harald Welte8470bf22008-12-25 23:28:35 +000032#include <openbsc/abis_rsl.h>
33#include <openbsc/chan_alloc.h>
Harald Welteedcc5272009-08-09 13:47:35 +020034#include <openbsc/bsc_rll.h>
Harald Welte8470bf22008-12-25 23:28:35 +000035#include <openbsc/debug.h>
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010036#include <osmocom/gsm/tlv.h>
Holger Freyther392209c2009-02-10 00:06:19 +000037#include <openbsc/paging.h>
Harald Welte167df882009-02-17 14:35:45 +000038#include <openbsc/signal.h>
Harald Welte3c7dc6e2009-11-29 19:07:28 +010039#include <openbsc/meas_rep.h>
Harald Welte17f5bf62009-12-20 15:42:44 +010040#include <openbsc/rtp_proxy.h>
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +020041#include <osmocom/abis/e1_input.h>
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010042#include <osmocom/gsm/rsl.h>
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010043#include <osmocom/core/talloc.h>
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +080044
Harald Welte8470bf22008-12-25 23:28:35 +000045#define RSL_ALLOC_SIZE 1024
46#define RSL_ALLOC_HEADROOM 128
Harald Welte52b1f982008-12-23 20:25:15 +000047
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +080048static int rsl_send_imm_assignment(struct gsm_lchan *lchan);
49
Holger Hans Peter Freyther08eebd52010-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 Ayusobbc5b992011-05-06 12:12:31 +020056 osmo_signal_dispatch(SS_LCHAN, sig_no, &sig);
Holger Hans Peter Freyther08eebd52010-12-27 13:28:20 +010057}
58
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +020059static uint8_t mdisc_by_msgtype(uint8_t msg_type)
Harald Welte52b1f982008-12-23 20:25:15 +000060{
61 /* mask off the transparent bit ? */
62 msg_type &= 0xfe;
63
Harald Welte8470bf22008-12-25 23:28:35 +000064 if ((msg_type & 0xf0) == 0x00)
Harald Welte52b1f982008-12-23 20:25:15 +000065 return ABIS_RSL_MDISC_RLL;
Harald Welte8470bf22008-12-25 23:28:35 +000066 if ((msg_type & 0xf0) == 0x10) {
Harald Welte52b1f982008-12-23 20:25:15 +000067 if (msg_type >= 0x19 && msg_type <= 0x22)
68 return ABIS_RSL_MDISC_TRX;
69 else
70 return ABIS_RSL_MDISC_COM_CHAN;
71 }
Harald Welte2d5b6382008-12-27 19:46:06 +000072 if ((msg_type & 0xe0) == 0x20)
Harald Welte52b1f982008-12-23 20:25:15 +000073 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 Freytherc42ad8b2011-04-18 17:04:00 +020079 uint8_t msg_type)
Harald Welte52b1f982008-12-23 20:25:15 +000080{
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 Welte8470bf22008-12-25 23:28:35 +000086/* determine logical channel based on TRX and channel number IE */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +020087struct gsm_lchan *lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr)
Harald Welte8470bf22008-12-25 23:28:35 +000088{
89 struct gsm_lchan *lchan;
Holger Hans Peter Freytherc42ad8b2011-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 Welte8470bf22008-12-25 23:28:35 +000093 struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr];
94
95 if (cbits == 0x01) {
96 lch_idx = 0; /* TCH/F */
Harald Weltea1499d02009-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 Welteb1d4c8e2009-12-17 23:10:46 +0100100 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte8470bf22008-12-25 23:28:35 +0000101 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 Welteb1d4c8e2009-12-17 23:10:46 +0100105 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte8470bf22008-12-25 23:28:35 +0000106 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 Welteb1d4c8e2009-12-17 23:10:46 +0100110 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte8470bf22008-12-25 23:28:35 +0000111 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 Welteb1d4c8e2009-12-17 23:10:46 +0100115 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte8470bf22008-12-25 23:28:35 +0000116 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 Welteb1d4c8e2009-12-17 23:10:46 +0100121 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte8470bf22008-12-25 23:28:35 +0000122 chan_nr, ts->pchan);
123 /* FIXME: we should not return first sdcch4 !!! */
124 } else {
Harald Welteb1d4c8e2009-12-17 23:10:46 +0100125 LOGP(DRSL, LOGL_ERROR, "unknown chan_nr=0x%02x\n", chan_nr);
Harald Welte8470bf22008-12-25 23:28:35 +0000126 return NULL;
127 }
128
129 lchan = &ts->lchan[lch_idx];
Harald Weltedc5062b2010-03-26 21:28:59 +0800130 log_set_context(BSC_CTX_LCHAN, lchan);
Holger Hans Peter Freyther2412a072010-06-28 15:47:12 +0800131 if (lchan->conn)
132 log_set_context(BSC_CTX_SUBSCR, lchan->conn->subscr);
Harald Welte8470bf22008-12-25 23:28:35 +0000133
134 return lchan;
135}
136
Harald Welte52b1f982008-12-23 20:25:15 +0000137/* As per TS 03.03 Section 2.2, the IMSI has 'not more than 15 digits' */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200138uint64_t str_to_imsi(const char *imsi_str)
Harald Welte52b1f982008-12-23 20:25:15 +0000139{
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200140 uint64_t ret;
Harald Welte52b1f982008-12-23 20:25:15 +0000141
142 ret = strtoull(imsi_str, NULL, 10);
143
144 return ret;
145}
146
Harald Welte8470bf22008-12-25 23:28:35 +0000147static struct msgb *rsl_msgb_alloc(void)
148{
Harald Welte966636f2009-06-26 19:39:35 +0200149 return msgb_alloc_headroom(RSL_ALLOC_SIZE, RSL_ALLOC_HEADROOM,
150 "RSL");
Harald Welte8470bf22008-12-25 23:28:35 +0000151}
152
Harald Welte362322e2009-02-15 14:36:38 +0000153#define MACBLOCK_SIZE 23
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200154static void pad_macblock(uint8_t *out, const uint8_t *in, int len)
Harald Welte362322e2009-02-15 14:36:38 +0000155{
156 memcpy(out, in, len);
157
158 if (len < MACBLOCK_SIZE)
159 memset(out+len, 0x2b, MACBLOCK_SIZE-len);
160}
161
Harald Welte08d91a52009-08-30 15:37:11 +0900162/* Chapter 9.3.7: Encryption Information */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200163static int build_encr_info(uint8_t *out, struct gsm_lchan *lchan)
Harald Welte08d91a52009-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 Freytherc42ad8b2011-04-18 17:04:00 +0200171static void print_rsl_cause(int lvl, const uint8_t *cause_v, uint8_t cause_len)
Harald Welte8830e072009-07-28 17:58:09 +0200172{
Harald Welte7f93cea2009-02-23 00:02:59 +0000173 int i;
174
Harald Welte5b8ed432009-12-24 12:20:20 +0100175 LOGPC(DRSL, lvl, "CAUSE=0x%02x(%s) ",
Harald Welte8830e072009-07-28 17:58:09 +0200176 cause_v[0], rsl_err_name(cause_v[0]));
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +0200177 for (i = 1; i < cause_len-1; i++)
Harald Welte5b8ed432009-12-24 12:20:20 +0100178 LOGPC(DRSL, lvl, "%02x ", cause_v[i]);
Harald Welte7f93cea2009-02-23 00:02:59 +0000179}
180
Harald Weltee8bd9e82011-08-10 23:26:33 +0200181static void lchan_act_tmr_cb(void *data)
182{
183 struct gsm_lchan *lchan = data;
184
Holger Hans Peter Freyther1411c062012-12-06 19:00:35 +0100185 LOGP(DRSL, LOGL_ERROR, "%s Timeout during activation!\n",
Harald Weltee8bd9e82011-08-10 23:26:33 +0200186 gsm_lchan_name(lchan));
187
Daniel Willmann513da172011-08-11 04:44:12 +0200188 rsl_lchan_set_state(lchan, LCHAN_S_NONE);
189 lchan_free(lchan);
Harald Weltee8bd9e82011-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 Freyther1411c062012-12-06 19:00:35 +0100196 LOGP(DRSL, LOGL_ERROR, "%s Timeout during deactivation!\n",
Harald Weltee8bd9e82011-08-10 23:26:33 +0200197 gsm_lchan_name(lchan));
198
Holger Hans Peter Freytherbbf21392012-01-14 21:56:37 +0100199 if (lchan->state != LCHAN_S_REL_ERR)
200 rsl_lchan_set_state(lchan, LCHAN_S_NONE);
Daniel Willmann513da172011-08-11 04:44:12 +0200201 lchan_free(lchan);
Harald Weltee8bd9e82011-08-10 23:26:33 +0200202}
203
204
Harald Welte52b1f982008-12-23 20:25:15 +0000205/* Send a BCCH_INFO message as per Chapter 8.5.1 */
Holger Hans Peter Freytherc42ad8b2011-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 Welte52b1f982008-12-23 20:25:15 +0000208{
209 struct abis_rsl_dchan_hdr *dh;
Harald Welte8470bf22008-12-25 23:28:35 +0000210 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000211
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 Ayuso7abecfc2011-08-17 22:43:54 +0200219 msg->dst = trx->rsl_link;
Harald Welte8470bf22008-12-25 23:28:35 +0000220
221 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000222}
223
Holger Hans Peter Freytherc42ad8b2011-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 Welte52b1f982008-12-23 20:25:15 +0000226{
227 struct abis_rsl_common_hdr *ch;
Harald Welte8470bf22008-12-25 23:28:35 +0000228 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000229
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);
Harald Welte702d8702008-12-26 20:25:35 +0000235 msgb_tl16v_put(msg, RSL_IE_L3_INFO, len, data);
Harald Welte52b1f982008-12-23 20:25:15 +0000236
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200237 msg->dst = trx->rsl_link;
Harald Welte8470bf22008-12-25 23:28:35 +0000238
239 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000240}
241
Holger Hans Peter Freytherc42ad8b2011-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 Welte7a69cf02011-01-13 23:16:03 +0100244{
245 struct abis_rsl_dchan_hdr *dh;
246 struct msgb *msg = rsl_msgb_alloc();
Harald Weltef6093a42011-06-25 10:02:33 +0200247 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte7a69cf02011-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 Ayuso7abecfc2011-08-17 22:43:54 +0200256 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte7a69cf02011-01-13 23:16:03 +0100257
258 return abis_rsl_sendmsg(msg);
259}
260
Harald Weltefcd24452009-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 Welteeab33352009-06-27 03:09:08 +0200264 struct msgb *msg;
Harald Weltef6093a42011-06-25 10:02:33 +0200265 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Weltefcd24452009-06-20 18:15:19 +0200266
267 db = abs(db);
268 if (db > 30)
269 return -EINVAL;
270
Harald Welteeab33352009-06-27 03:09:08 +0200271 msg = rsl_msgb_alloc();
272
Harald Weltefcd24452009-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 Ayuso7abecfc2011-08-17 22:43:54 +0200283 msg->dst = lchan->ts->trx->rsl_link;
Harald Weltefcd24452009-06-20 18:15:19 +0200284
285 return abis_rsl_sendmsg(msg);
286}
287
Harald Weltefcd24452009-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 Welteeab33352009-06-27 03:09:08 +0200291 struct msgb *msg;
Harald Weltef6093a42011-06-25 10:02:33 +0200292 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Weltefcd24452009-06-20 18:15:19 +0200293 int ctl_lvl;
294
Harald Welte66b6a8d2009-08-09 14:45:18 +0200295 ctl_lvl = ms_pwr_ctl_lvl(lchan->ts->trx->bts->band, dbm);
Harald Weltefcd24452009-06-20 18:15:19 +0200296 if (ctl_lvl < 0)
297 return ctl_lvl;
298
Harald Welteeab33352009-06-27 03:09:08 +0200299 msg = rsl_msgb_alloc();
300
Harald Weltefcd24452009-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 Ayuso7abecfc2011-08-17 22:43:54 +0200312 msg->dst = lchan->ts->trx->rsl_link;
Harald Weltefcd24452009-06-20 18:15:19 +0200313
314 return abis_rsl_sendmsg(msg);
315}
316
Harald Welte9943c5b2009-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 Freyther5a3a61d2010-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 Welte9943c5b2009-07-29 15:41:29 +0200327
328 /* set TCH Speech/Data */
329 cm->spd_ind = lchan->rsl_cmode;
330
Harald Welte1a79d362009-11-27 08:55:16 +0100331 if (lchan->rsl_cmode == RSL_CMOD_SPD_SIGN &&
332 lchan->tch_mode != GSM48_CMODE_SIGN)
Harald Welteb1d4c8e2009-12-17 23:10:46 +0100333 LOGP(DRSL, LOGL_ERROR, "unsupported: rsl_mode == signalling, "
Harald Welte1a79d362009-11-27 08:55:16 +0100334 "but tch_mode != signalling\n");
335
Harald Welte9943c5b2009-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 Welte9943c5b2009-07-29 15:41:29 +0200366 case GSM48_CMODE_DATA_12k0:
Harald Welte9943c5b2009-07-29 15:41:29 +0200367 case GSM48_CMODE_DATA_6k0:
Harald Weltee4227982012-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 Welte9943c5b2009-07-29 15:41:29 +0200413 default:
414 return -EINVAL;
415 }
416
417 return 0;
418}
419
Harald Welte52b1f982008-12-23 20:25:15 +0000420/* Chapter 8.4.1 */
Harald Welteddab3c72009-02-28 13:19:15 +0000421#if 0
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200422int rsl_chan_activate(struct gsm_bts_trx *trx, uint8_t chan_nr,
423 uint8_t act_type,
Harald Welte52b1f982008-12-23 20:25:15 +0000424 struct rsl_ie_chan_mode *chan_mode,
425 struct rsl_ie_chan_ident *chan_ident,
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200426 uint8_t bs_power, uint8_t ms_power,
427 uint8_t ta)
Harald Welte52b1f982008-12-23 20:25:15 +0000428{
429 struct abis_rsl_dchan_hdr *dh;
Harald Welte8470bf22008-12-25 23:28:35 +0000430 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000431
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 Freytherc42ad8b2011-04-18 17:04:00 +0200439 (uint8_t *) chan_mode);
Harald Welte52b1f982008-12-23 20:25:15 +0000440 msgb_tlv_put(msg, RSL_IE_CHAN_IDENT, 4,
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200441 (uint8_t *) chan_ident);
Harald Welte702d8702008-12-26 20:25:35 +0000442#if 0
Harald Welte52b1f982008-12-23 20:25:15 +0000443 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, 1,
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200444 (uint8_t *) &encr_info);
Harald Welte702d8702008-12-26 20:25:35 +0000445#endif
Harald Welted4c9bf32009-02-15 16:56:18 +0000446 msgb_tv_put(msg, RSL_IE_BS_POWER, bs_power);
Harald Welte52b1f982008-12-23 20:25:15 +0000447 msgb_tv_put(msg, RSL_IE_MS_POWER, ms_power);
448 msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta);
449
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200450 msg->dst = trx->rsl_link;
Harald Weltee79769b2009-02-07 00:48:17 +0000451
Harald Welte8470bf22008-12-25 23:28:35 +0000452 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000453}
Harald Welteddab3c72009-02-28 13:19:15 +0000454#endif
Harald Welte52b1f982008-12-23 20:25:15 +0000455
Holger Hans Peter Freytherc42ad8b2011-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 Welte4b634542008-12-27 01:55:51 +0000458{
459 struct abis_rsl_dchan_hdr *dh;
Harald Welteeab33352009-06-27 03:09:08 +0200460 struct msgb *msg;
Harald Welte9943c5b2009-07-29 15:41:29 +0200461 int rc;
Harald Welte93d50e62010-06-29 17:53:45 +0200462 uint8_t *len;
Harald Welte4b634542008-12-27 01:55:51 +0000463
Harald Weltef6093a42011-06-25 10:02:33 +0200464 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte4b634542008-12-27 01:55:51 +0000465 struct rsl_ie_chan_mode cm;
laforge694a5cf2010-06-20 21:38:19 +0200466 struct gsm48_chan_desc cd;
Harald Welte4b634542008-12-27 01:55:51 +0000467
Harald Welte9943c5b2009-07-29 15:41:29 +0200468 rc = channel_mode_from_lchan(&cm, lchan);
469 if (rc < 0)
470 return rc;
Harald Welte4b634542008-12-27 01:55:51 +0000471
Holger Hans Peter Freythere38bd6c2010-06-30 11:56:43 +0800472 memset(&cd, 0, sizeof(cd));
laforge694a5cf2010-06-20 21:38:19 +0200473 gsm48_lchan2chan_desc(&cd, lchan);
Harald Welte4b634542008-12-27 01:55:51 +0000474
Harald Welteeab33352009-06-27 03:09:08 +0200475 msg = rsl_msgb_alloc();
Harald Welte4b634542008-12-27 01:55:51 +0000476 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 Welte4b634542008-12-27 01:55:51 +0000481 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200482 (uint8_t *) &cm);
Holger Hans Peter Freythere38bd6c2010-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 */
laforge694a5cf2010-06-20 21:38:19 +0200491 msgb_v_put(msg, RSL_IE_CHAN_IDENT);
Harald Welte93d50e62010-06-29 17:53:45 +0200492 len = msgb_put(msg, 1);
Dieter Spaareabb6e32011-07-27 23:40:33 +0200493 msgb_tv_fixed_put(msg, GSM48_IE_CHANDESC_2, sizeof(cd), (const uint8_t *) &cd);
Holger Hans Peter Freyther0379c6d2010-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 Freythere38bd6c2010-06-30 11:56:43 +0800500
501 /* update the calculated size */
502 msg->l3h = len + 1;
503 *len = msgb_l3len(msg);
504
Harald Welte08d91a52009-08-30 15:37:11 +0900505 if (lchan->encr.alg_id > RSL_ENC_ALG_A5(0)) {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200506 uint8_t encr_info[MAX_A5_KEY_LEN+2];
Harald Welte08d91a52009-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 Welte8d77b952009-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 Welted4c9bf32009-02-15 16:56:18 +0000521 msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power);
522 msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power);
Harald Welte4b634542008-12-27 01:55:51 +0000523 msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta);
524
Holger Hans Peter Freyther93b6c652010-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 Freytherc42ad8b2011-04-18 17:04:00 +0200527 (uint8_t *) &lchan->mr_conf);
Holger Hans Peter Freyther93b6c652010-01-28 04:45:05 +0100528
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200529 msg->dst = lchan->ts->trx->rsl_link;
Harald Weltee79769b2009-02-07 00:48:17 +0000530
Harald Welte4b634542008-12-27 01:55:51 +0000531 return abis_rsl_sendmsg(msg);
532}
533
Harald Welte470abb72009-07-29 11:38:15 +0200534/* Chapter 8.4.9: Modify channel mode on BTS side */
Harald Welteda783762009-02-18 03:29:53 +0000535int rsl_chan_mode_modify_req(struct gsm_lchan *lchan)
536{
537 struct abis_rsl_dchan_hdr *dh;
Harald Welteeab33352009-06-27 03:09:08 +0200538 struct msgb *msg;
Harald Welte9943c5b2009-07-29 15:41:29 +0200539 int rc;
Harald Welteda783762009-02-18 03:29:53 +0000540
Harald Weltef6093a42011-06-25 10:02:33 +0200541 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welteda783762009-02-18 03:29:53 +0000542 struct rsl_ie_chan_mode cm;
543
Harald Welte9943c5b2009-07-29 15:41:29 +0200544 rc = channel_mode_from_lchan(&cm, lchan);
545 if (rc < 0)
546 return rc;
Harald Welteda783762009-02-18 03:29:53 +0000547
Harald Welteeab33352009-06-27 03:09:08 +0200548 msg = rsl_msgb_alloc();
Harald Welteda783762009-02-18 03:29:53 +0000549 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 Freytherc42ad8b2011-04-18 17:04:00 +0200554 (uint8_t *) &cm);
Harald Welte08d91a52009-08-30 15:37:11 +0900555
556 if (lchan->encr.alg_id > RSL_ENC_ALG_A5(0)) {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200557 uint8_t encr_info[MAX_A5_KEY_LEN+2];
Harald Welte08d91a52009-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 Freytherea528022009-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 Freytherc42ad8b2011-04-18 17:04:00 +0200565 (uint8_t *) &lchan->mr_conf);
Holger Hans Peter Freytherea528022009-11-18 22:57:02 +0100566 }
567
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200568 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte08d91a52009-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 Weltef6093a42011-06-25 10:02:33 +0200578 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200579 uint8_t encr_info[MAX_A5_KEY_LEN+2];
580 uint8_t l3_len = msg->len;
Harald Welte08d91a52009-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 Welteda783762009-02-18 03:29:53 +0000599
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200600 msg->dst = lchan->ts->trx->rsl_link;
Harald Welteda783762009-02-18 03:29:53 +0000601
602 return abis_rsl_sendmsg(msg);
603}
604
Harald Welte115d1032009-08-10 11:43:22 +0200605/* Chapter 8.4.5 / 4.6: Deactivate the SACCH after 04.08 RR CHAN RELEASE */
Harald Welteae0f2362009-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 Weltef6093a42011-06-25 10:02:33 +0200613 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welteae0f2362009-07-19 18:36:49 +0200614
615 msg->lchan = lchan;
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200616 msg->dst = lchan->ts->trx->rsl_link;
Harald Welteae0f2362009-07-19 18:36:49 +0200617
Harald Welte (local)19ef62a2009-12-27 18:16:36 +0100618 DEBUGP(DRSL, "%s DEACTivate SACCH CMD\n", gsm_lchan_name(lchan));
Harald Welteae0f2362009-07-19 18:36:49 +0200619
620 return abis_rsl_sendmsg(msg);
621}
622
Holger Hans Peter Freyther4b4dd102010-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 Freyther44752d92010-06-08 11:53:33 +0800634 rsl_lchan_set_state(lchan, LCHAN_S_NONE);
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +0800635}
636
Harald Weltefd355a32011-03-04 13:41:31 +0100637static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan);
638
Harald Welte115d1032009-08-10 11:43:22 +0200639/* Chapter 8.4.14 / 4.7: Tell BTS to release the radio channel */
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +0800640static int rsl_rf_chan_release(struct gsm_lchan *lchan, int error)
Harald Welte52b1f982008-12-23 20:25:15 +0000641{
642 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +0800643 struct msgb *msg;
Harald Weltefd355a32011-03-04 13:41:31 +0100644 int rc;
Harald Welte52b1f982008-12-23 20:25:15 +0000645
Holger Hans Peter Freyther4b4dd102010-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 Welte52b1f982008-12-23 20:25:15 +0000653 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
654 init_dchan_hdr(dh, RSL_MT_RF_CHAN_REL);
Harald Weltef6093a42011-06-25 10:02:33 +0200655 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte52b1f982008-12-23 20:25:15 +0000656
Harald Welte8470bf22008-12-25 23:28:35 +0000657 msg->lchan = lchan;
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200658 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte8470bf22008-12-25 23:28:35 +0000659
Holger Hans Peter Freyther4b4dd102010-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 Ayuso7abecfc2011-08-17 22:43:54 +0200668 struct e1inp_sign_link *sign_link = msg->dst;
669
Holger Hans Peter Freyther44752d92010-06-08 11:53:33 +0800670 rsl_lchan_set_state(lchan, LCHAN_S_REL_ERR);
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +0800671 lchan->error_timer.data = lchan;
672 lchan->error_timer.cb = error_timeout_cb;
Pablo Neira Ayusobf540cb2011-05-06 12:11:06 +0200673 osmo_timer_schedule(&lchan->error_timer,
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200674 sign_link->trx->bts->network->T3111 + 2, 0);
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +0800675 }
Harald Welte2d5b6382008-12-27 19:46:06 +0000676
Harald Weltee8bd9e82011-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 Weltefd355a32011-03-04 13:41:31 +0100682 rc = abis_rsl_sendmsg(msg);
683
Harald Welte115d1032009-08-10 11:43:22 +0200684 /* BTS will respond by RF CHAN REL ACK */
Harald Welte26d79072011-01-14 23:18:59 +0100685#ifdef HSL_SR_1_0
Harald Weltefd355a32011-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 Welte26d79072011-01-14 23:18:59 +0100689#endif
Harald Weltefd355a32011-03-04 13:41:31 +0100690
691 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +0000692}
693
Harald Welte64bb7542011-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 Weltee8bd9e82011-08-10 23:26:33 +0200699 osmo_timer_del(&lchan->act_timer);
700
Harald Welte64bb7542011-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 Ayusobf540cb2011-05-06 12:11:06 +0200705 osmo_timer_del(&lchan->T3111);
Harald Welte64bb7542011-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 Freytherc42ad8b2011-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 Welte52b1f982008-12-23 20:25:15 +0000716{
717 struct abis_rsl_dchan_hdr *dh;
Harald Welte8470bf22008-12-25 23:28:35 +0000718 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000719
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);
Harald Welte255539c2008-12-28 02:26:27 +0000725 msgb_tlv_put(msg, RSL_IE_MS_IDENTITY, len-2, ms_ident+2);
Harald Welte52b1f982008-12-23 20:25:15 +0000726 msgb_tv_put(msg, RSL_IE_CHAN_NEEDED, chan_needed);
727
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200728 msg->dst = bts->c0->rsl_link;
Harald Welte8470bf22008-12-25 23:28:35 +0000729
730 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000731}
732
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200733int imsi_str2bcd(uint8_t *bcd_out, const char *str_in)
Harald Welte52b1f982008-12-23 20:25:15 +0000734{
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
Harald Welte702d8702008-12-26 20:25:35 +0000750/* Chapter 8.5.6 */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200751int rsl_imm_assign_cmd(struct gsm_bts *bts, uint8_t len, uint8_t *val)
Harald Welte52b1f982008-12-23 20:25:15 +0000752{
Harald Welte8470bf22008-12-25 23:28:35 +0000753 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000754 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200755 uint8_t buf[MACBLOCK_SIZE];
Harald Welte52b1f982008-12-23 20:25:15 +0000756
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
Harald Welte362322e2009-02-15 14:36:38 +0000761 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 }
Harald Welte52b1f982008-12-23 20:25:15 +0000771
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200772 msg->dst = bts->c0->rsl_link;
Harald Welte8470bf22008-12-25 23:28:35 +0000773
774 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000775}
776
Harald Welte67fa91b2009-08-10 09:51:40 +0200777/* Send Siemens specific MS RF Power Capability Indication */
Harald Welte31c48932009-08-10 10:07:33 +0200778int rsl_siemens_mrpci(struct gsm_lchan *lchan, struct rsl_mrpci *mrpci)
Harald Welte67fa91b2009-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 Welte3c456d02009-08-10 11:26:14 +0200785 dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
Harald Weltef6093a42011-06-25 10:02:33 +0200786 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200787 msgb_tv_put(msg, RSL_IE_SIEMENS_MRPCI, *(uint8_t *)mrpci);
Harald Welte67fa91b2009-08-10 09:51:40 +0200788
Harald Welte5b8ed432009-12-24 12:20:20 +0100789 DEBUGP(DRSL, "%s TX Siemens MRPCI 0x%02x\n",
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200790 gsm_lchan_name(lchan), *(uint8_t *)mrpci);
Harald Welte3c456d02009-08-10 11:26:14 +0200791
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200792 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte3c456d02009-08-10 11:26:14 +0200793
Harald Welte67fa91b2009-08-10 09:51:40 +0200794 return abis_rsl_sendmsg(msg);
795}
796
797
Harald Welte8470bf22008-12-25 23:28:35 +0000798/* Send "DATA REQUEST" message with given L3 Info payload */
Harald Welte52b1f982008-12-23 20:25:15 +0000799/* Chapter 8.3.1 */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200800int rsl_data_request(struct msgb *msg, uint8_t link_id)
Harald Welte52b1f982008-12-23 20:25:15 +0000801{
Harald Welte8470bf22008-12-25 23:28:35 +0000802 if (msg->lchan == NULL) {
Harald Welteb1d4c8e2009-12-17 23:10:46 +0100803 LOGP(DRSL, LOGL_ERROR, "cannot send DATA REQUEST to unknown lchan\n");
Harald Welte8470bf22008-12-25 23:28:35 +0000804 return -EINVAL;
805 }
Harald Welte52b1f982008-12-23 20:25:15 +0000806
Harald Weltef6093a42011-06-25 10:02:33 +0200807 rsl_rll_push_l3(msg, RSL_MT_DATA_REQ, gsm_lchan2chan_nr(msg->lchan),
Harald Welte3c9c5f92010-03-04 10:33:10 +0100808 link_id, 1);
Harald Welte52b1f982008-12-23 20:25:15 +0000809
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200810 msg->dst = msg->lchan->ts->trx->rsl_link;
Harald Welte8470bf22008-12-25 23:28:35 +0000811
812 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000813}
814
Harald Welteedcc5272009-08-09 13:47:35 +0200815/* Send "ESTABLISH REQUEST" message with given L3 Info payload */
816/* Chapter 8.3.1 */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200817int rsl_establish_request(struct gsm_lchan *lchan, uint8_t link_id)
Harald Welteedcc5272009-08-09 13:47:35 +0200818{
Harald Welte3c9c5f92010-03-04 10:33:10 +0100819 struct msgb *msg;
Harald Welteedcc5272009-08-09 13:47:35 +0200820
Harald Weltef6093a42011-06-25 10:02:33 +0200821 msg = rsl_rll_simple(RSL_MT_EST_REQ, gsm_lchan2chan_nr(lchan),
Harald Welte3c9c5f92010-03-04 10:33:10 +0100822 link_id, 0);
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200823 msg->dst = lchan->ts->trx->rsl_link;
Harald Welteedcc5272009-08-09 13:47:35 +0200824
Harald Weltefda74ee2012-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 Welteedcc5272009-08-09 13:47:35 +0200828 return abis_rsl_sendmsg(msg);
829}
830
Harald Welted2dc1de2009-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 Freyther5ca825e2012-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 Welted2dc1de2009-08-08 13:15:07 +0200838{
Harald Welted2dc1de2009-08-08 13:15:07 +0200839
Harald Welte3c9c5f92010-03-04 10:33:10 +0100840 struct msgb *msg;
841
Harald Weltef6093a42011-06-25 10:02:33 +0200842 msg = rsl_rll_simple(RSL_MT_REL_REQ, gsm_lchan2chan_nr(lchan),
Harald Welte3c9c5f92010-03-04 10:33:10 +0100843 link_id, 0);
Holger Hans Peter Freyther4f5848d2010-06-08 11:57:45 +0800844 /* 0 is normal release, 1 is local end */
Holger Hans Peter Freyther5ca825e2012-12-06 12:01:38 +0100845 msgb_tv_put(msg, RSL_IE_RELEASE_MODE, release_mode);
Harald Welted2dc1de2009-08-08 13:15:07 +0200846
Harald Welte8e93b792009-12-29 10:44:17 +0100847 /* FIXME: start some timer in case we don't receive a REL ACK ? */
848
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200849 msg->dst = lchan->ts->trx->rsl_link;
Harald Welted2dc1de2009-08-08 13:15:07 +0200850
Harald Weltefda74ee2012-04-26 19:42:19 +0200851 DEBUGP(DRLL, "%s RSL RLL RELEASE REQ (link_id=0x%02x, reason=%u)\n",
Holger Hans Peter Freyther5ca825e2012-12-06 12:01:38 +0100852 gsm_lchan_name(lchan), link_id, release_mode);
Harald Weltefda74ee2012-04-26 19:42:19 +0200853
Harald Welted2dc1de2009-08-08 13:15:07 +0200854 return abis_rsl_sendmsg(msg);
855}
856
Holger Hans Peter Freyther74419492010-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 Welte702d8702008-12-26 20:25:35 +0000863/* 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 */
Harald Welte4b634542008-12-27 01:55:51 +0000870 if (rslh->ie_chan != RSL_IE_CHAN_NR)
871 return -EINVAL;
Harald Welted011e8b2009-11-29 22:45:52 +0100872
Harald Weltee8bd9e82011-08-10 23:26:33 +0200873 osmo_timer_del(&msg->lchan->act_timer);
874
Harald Welte8e93b792009-12-29 10:44:17 +0100875 if (msg->lchan->state != LCHAN_S_ACT_REQ)
Harald Welte1887f9d2009-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 Freyther74419492010-04-10 00:12:31 +0200879 rsl_lchan_set_state(msg->lchan, LCHAN_S_ACTIVE);
Harald Welteb8bfc562009-12-21 13:27:11 +0100880
Holger Hans Peter Freyther5ba05f42010-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 Freyther08eebd52010-12-27 13:28:20 +0100888 send_lchan_signal(S_LCHAN_ACTIVATE_ACK, msg->lchan, NULL);
Harald Welted011e8b2009-11-29 22:45:52 +0100889
Harald Welte4b634542008-12-27 01:55:51 +0000890 return 0;
891}
Harald Welte702d8702008-12-26 20:25:35 +0000892
Harald Welte4b634542008-12-27 01:55:51 +0000893/* Chapter 8.4.3: Channel Activate NACK */
894static int rsl_rx_chan_act_nack(struct msgb *msg)
895{
Harald Welte6dab0552009-05-01 17:21:37 +0000896 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
897 struct tlv_parsed tp;
Harald Welte4b634542008-12-27 01:55:51 +0000898
Harald Weltee8bd9e82011-08-10 23:26:33 +0200899 osmo_timer_del(&msg->lchan->act_timer);
900
Daniel Willmann6fc6a122011-08-11 04:54:23 +0200901 LOGP(DRSL, LOGL_ERROR, "%s CHANNEL ACTIVATE NACK ",
Harald Welte (local)19ef62a2009-12-27 18:16:36 +0100902 gsm_lchan_name(msg->lchan));
Harald Welte (local)91b603d2009-12-27 11:48:11 +0100903
Harald Welte6dab0552009-05-01 17:21:37 +0000904 /* BTS has rejected channel activation ?!? */
905 if (dh->ie_chan != RSL_IE_CHAN_NR)
Harald Welte4b634542008-12-27 01:55:51 +0000906 return -EINVAL;
Harald Welte6dab0552009-05-01 17:21:37 +0000907
908 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
Harald Welte (local)3e460312009-12-27 18:12:29 +0100909 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE)) {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200910 const uint8_t *cause = TLVP_VAL(&tp, RSL_IE_CAUSE);
Harald Welte (local)3e460312009-12-27 18:12:29 +0100911 print_rsl_cause(LOGL_ERROR, cause,
Harald Welte8830e072009-07-28 17:58:09 +0200912 TLVP_LEN(&tp, RSL_IE_CAUSE));
Harald Welte (local)3e460312009-12-27 18:12:29 +0100913 if (*cause != RSL_ERR_RCH_ALR_ACTV_ALLOC)
Holger Hans Peter Freyther74419492010-04-10 00:12:31 +0200914 rsl_lchan_set_state(msg->lchan, LCHAN_S_NONE);
Daniel Willmann7ddc3182011-08-11 04:47:11 +0200915 else
916 rsl_rf_chan_release(msg->lchan, 1);
917
Harald Welte (local)3e460312009-12-27 18:12:29 +0100918 } else
Holger Hans Peter Freyther74419492010-04-10 00:12:31 +0200919 rsl_lchan_set_state(msg->lchan, LCHAN_S_NONE);
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +0200920
Harald Welte (local)91b603d2009-12-27 11:48:11 +0100921 LOGPC(DRSL, LOGL_ERROR, "\n");
922
Holger Hans Peter Freyther08eebd52010-12-27 13:28:20 +0100923 send_lchan_signal(S_LCHAN_ACTIVATE_NACK, msg->lchan, NULL);
Harald Welted011e8b2009-11-29 22:45:52 +0100924
Harald Welte3073a9f2009-08-09 19:50:08 +0200925 lchan_free(msg->lchan);
Harald Welte4b634542008-12-27 01:55:51 +0000926 return 0;
Harald Welte702d8702008-12-26 20:25:35 +0000927}
928
Harald Welte7f93cea2009-02-23 00:02:59 +0000929/* 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 Welteb1d4c8e2009-12-17 23:10:46 +0100935 /* FIXME: print which channel */
Harald Welte (local)fc057502009-12-26 22:33:09 +0100936 LOGP(DRSL, LOGL_NOTICE, "%s CONNECTION FAIL: RELEASING ",
Harald Welte (local)19ef62a2009-12-27 18:16:36 +0100937 gsm_lchan_name(msg->lchan));
Harald Welte7f93cea2009-02-23 00:02:59 +0000938
939 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
940
Harald Welte8830e072009-07-28 17:58:09 +0200941 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
Harald Welte5b8ed432009-12-24 12:20:20 +0100942 print_rsl_cause(LOGL_NOTICE, TLVP_VAL(&tp, RSL_IE_CAUSE),
Harald Welte8830e072009-07-28 17:58:09 +0200943 TLVP_LEN(&tp, RSL_IE_CAUSE));
944
Harald Welte (local)fc057502009-12-26 22:33:09 +0100945 LOGPC(DRSL, LOGL_NOTICE, "\n");
Harald Welte7f93cea2009-02-23 00:02:59 +0000946 /* FIXME: only free it after channel release ACK */
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +0200947 osmo_counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rf_fail);
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +0800948 return rsl_rf_chan_release(msg->lchan, 1);
Harald Welte7f93cea2009-02-23 00:02:59 +0000949}
950
Harald Welte3c7dc6e2009-11-29 19:07:28 +0100951static void print_meas_rep_uni(struct gsm_meas_rep_unidir *mru,
952 const char *prefix)
953{
Harald Welte6739dfb2009-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 Welte3c7dc6e2009-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 Welte0c1bd612012-07-02 17:12:08 +0200961static void print_meas_rep(struct gsm_lchan *lchan, struct gsm_meas_rep *mr)
Harald Welte3c7dc6e2009-11-29 19:07:28 +0100962{
Harald Welte6739dfb2009-12-16 16:52:07 +0100963 int i;
Harald Welte0c1bd612012-07-02 17:12:08 +0200964 char *name = "";
Harald Welte6739dfb2009-12-16 16:52:07 +0100965
Harald Welte0c1bd612012-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 Welte3c7dc6e2009-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 Welte6739dfb2009-12-16 16:52:07 +0100980 DEBUGPC(DMEAS, "L1_MS_PWR=%3ddBm ", mr->ms_l1.pwr);
Harald Welte3c7dc6e2009-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 Welte479015b2009-12-19 18:33:05 +0100996 if (mr->num_cell == 7)
997 return;
Harald Welte6739dfb2009-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 Welte303e5e02009-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 Welte6739dfb2009-12-16 16:52:07 +01001002 }
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001003}
1004
Harald Welte440fed02009-05-01 18:43:47 +00001005static 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 Welted12b0fd2009-12-15 21:36:05 +01001009 struct gsm_meas_rep *mr = lchan_next_meas_rep(msg->lchan);
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001010 uint8_t len;
1011 const uint8_t *val;
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001012 int rc;
Harald Welte440fed02009-05-01 18:43:47 +00001013
Harald Welteb8bfc562009-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 Welte8e93b792009-12-29 10:44:17 +01001016 if (msg->lchan->state != LCHAN_S_ACTIVE) {
Holger Hans Peter Freytherc44db4a2010-07-29 14:50:57 +08001017 LOGP(DRSL, LOGL_DEBUG, "%s: MEAS RES for inactive channel\n",
Harald Welte8e93b792009-12-29 10:44:17 +01001018 gsm_lchan_name(msg->lchan));
Harald Welteb8bfc562009-12-21 13:27:11 +01001019 return 0;
Harald Welte8e93b792009-12-29 10:44:17 +01001020 }
Harald Welteb8bfc562009-12-21 13:27:11 +01001021
Harald Welted12b0fd2009-12-15 21:36:05 +01001022 memset(mr, 0, sizeof(*mr));
Harald Welte33e65972009-12-16 23:29:34 +01001023 mr->lchan = msg->lchan;
Harald Weltedbb1d882009-11-30 19:16:47 +01001024
Harald Welte440fed02009-05-01 18:43:47 +00001025 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
1026
Harald Welte3c7dc6e2009-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 Welted12b0fd2009-12-15 21:36:05 +01001033 mr->nr = *TLVP_VAL(&tp, RSL_IE_MEAS_RES_NR);
Harald Welte3c7dc6e2009-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 Welted12b0fd2009-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 Welte440fed02009-05-01 18:43:47 +00001044 }
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001045
Harald Welted12b0fd2009-12-15 21:36:05 +01001046 mr->bs_power = *TLVP_VAL(&tp, RSL_IE_BS_POWER);
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001047
1048 /* Optional Parts */
Harald Welte440fed02009-05-01 18:43:47 +00001049 if (TLVP_PRESENT(&tp, RSL_IE_MS_TIMING_OFFSET))
Harald Welted12b0fd2009-12-15 21:36:05 +01001050 mr->ms_timing_offset =
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001051 *TLVP_VAL(&tp, RSL_IE_MS_TIMING_OFFSET);
1052
Harald Weltefe9af262009-06-20 18:44:35 +02001053 if (TLVP_PRESENT(&tp, RSL_IE_L1_INFO)) {
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001054 struct e1inp_sign_link *sign_link = msg->dst;
1055
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001056 val = TLVP_VAL(&tp, RSL_IE_L1_INFO);
Harald Welted12b0fd2009-12-15 21:36:05 +01001057 mr->flags |= MEAS_REP_F_MS_L1;
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001058 mr->ms_l1.pwr = ms_pwr_dbm(sign_link->trx->bts->band, val[0] >> 3);
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001059 if (val[0] & 0x04)
Harald Welted12b0fd2009-12-15 21:36:05 +01001060 mr->flags |= MEAS_REP_F_FPC;
1061 mr->ms_l1.ta = val[1];
Andreas Eversberg3365cd12011-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 Eversberg2957de92011-12-16 17:45:37 +01001065 mr->ms_l1.ta >>= 2;
Harald Weltefe9af262009-06-20 18:44:35 +02001066 }
Harald Weltef7c43522009-06-09 20:24:21 +00001067 if (TLVP_PRESENT(&tp, RSL_IE_L3_INFO)) {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001068 msg->l3h = (uint8_t *) TLVP_VAL(&tp, RSL_IE_L3_INFO);
Harald Welted12b0fd2009-12-15 21:36:05 +01001069 rc = gsm48_parse_meas_rep(mr, msg);
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001070 if (rc < 0)
1071 return rc;
1072 }
1073
Harald Welte0c1bd612012-07-02 17:12:08 +02001074 print_meas_rep(msg->lchan, mr);
Harald Welte60d68f12009-06-05 20:07:43 +00001075
Holger Hans Peter Freyther08eebd52010-12-27 13:28:20 +01001076 send_lchan_signal(S_LCHAN_MEAS_REP, msg->lchan, mr);
Harald Weltedbb1d882009-11-30 19:16:47 +01001077
Harald Welte75d34a82009-05-23 06:11:13 +00001078 return 0;
Harald Welte440fed02009-05-01 18:43:47 +00001079}
1080
Harald Welted011e8b2009-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)19ef62a2009-12-27 18:16:36 +01001087 DEBUGP(DRSL, "%s HANDOVER DETECT ", gsm_lchan_name(msg->lchan));
Harald Welted011e8b2009-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 Freyther08eebd52010-12-27 13:28:20 +01001097 send_lchan_signal(S_LCHAN_HANDOVER_DETECT, msg->lchan, NULL);
Harald Welted011e8b2009-11-29 22:45:52 +01001098
1099 return 0;
1100}
1101
Harald Welte52b1f982008-12-23 20:25:15 +00001102static int abis_rsl_rx_dchan(struct msgb *msg)
1103{
Harald Welte8470bf22008-12-25 23:28:35 +00001104 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
1105 int rc = 0;
Harald Weltef325eb42009-02-19 17:07:39 +00001106 char *ts_name;
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001107 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte52b1f982008-12-23 20:25:15 +00001108
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001109 msg->lchan = lchan_lookup(sign_link->trx, rslh->chan_nr);
Harald Welte (local)19ef62a2009-12-27 18:16:36 +01001110 ts_name = gsm_lchan_name(msg->lchan);
Harald Weltef325eb42009-02-19 17:07:39 +00001111
Harald Welte8470bf22008-12-25 23:28:35 +00001112 switch (rslh->c.msg_type) {
Harald Welte52b1f982008-12-23 20:25:15 +00001113 case RSL_MT_CHAN_ACTIV_ACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001114 DEBUGP(DRSL, "%s CHANNEL ACTIVATE ACK\n", ts_name);
Harald Welte4b634542008-12-27 01:55:51 +00001115 rc = rsl_rx_chan_act_ack(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001116 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001117 case RSL_MT_CHAN_ACTIV_NACK:
Harald Welte4b634542008-12-27 01:55:51 +00001118 rc = rsl_rx_chan_act_nack(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001119 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001120 case RSL_MT_CONN_FAIL:
Harald Welte7f93cea2009-02-23 00:02:59 +00001121 rc = rsl_rx_conn_fail(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001122 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001123 case RSL_MT_MEAS_RES:
Harald Welte440fed02009-05-01 18:43:47 +00001124 rc = rsl_rx_meas_res(msg);
Harald Welte2d5b6382008-12-27 19:46:06 +00001125 break;
Harald Welted011e8b2009-11-29 22:45:52 +01001126 case RSL_MT_HANDO_DET:
1127 rc = rsl_rx_hando_det(msg);
1128 break;
Harald Welte2d5b6382008-12-27 19:46:06 +00001129 case RSL_MT_RF_CHAN_REL_ACK:
Harald Welte64bb7542011-01-14 14:16:16 +01001130 rc = rsl_rx_rf_chan_rel_ack(msg->lchan);
Harald Welte8470bf22008-12-25 23:28:35 +00001131 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001132 case RSL_MT_MODE_MODIFY_ACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001133 DEBUGP(DRSL, "%s CHANNEL MODE MODIFY ACK\n", ts_name);
Harald Welteda783762009-02-18 03:29:53 +00001134 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001135 case RSL_MT_MODE_MODIFY_NACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001136 LOGP(DRSL, LOGL_ERROR, "%s CHANNEL MODE MODIFY NACK\n", ts_name);
Harald Welteda783762009-02-18 03:29:53 +00001137 break;
Harald Welte9c880c92009-10-24 10:29:22 +02001138 case RSL_MT_IPAC_PDCH_ACT_ACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001139 DEBUGPC(DRSL, "%s IPAC PDCH ACT ACK\n", ts_name);
Harald Welte4563eab2010-03-28 14:42:09 +08001140 msg->lchan->ts->flags |= TS_F_PDCH_MODE;
Harald Welte9c880c92009-10-24 10:29:22 +02001141 break;
1142 case RSL_MT_IPAC_PDCH_ACT_NACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001143 LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH ACT NACK\n", ts_name);
Harald Welte9c880c92009-10-24 10:29:22 +02001144 break;
1145 case RSL_MT_IPAC_PDCH_DEACT_ACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001146 DEBUGP(DRSL, "%s IPAC PDCH DEACT ACK\n", ts_name);
Harald Welte4563eab2010-03-28 14:42:09 +08001147 msg->lchan->ts->flags &= ~TS_F_PDCH_MODE;
Harald Welte9c880c92009-10-24 10:29:22 +02001148 break;
1149 case RSL_MT_IPAC_PDCH_DEACT_NACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001150 LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH DEACT NACK\n", ts_name);
Harald Welte9c880c92009-10-24 10:29:22 +02001151 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001152 case RSL_MT_PHY_CONTEXT_CONF:
1153 case RSL_MT_PREPROC_MEAS_RES:
Harald Welte52b1f982008-12-23 20:25:15 +00001154 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 Welte5b8ed432009-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 Welte52b1f982008-12-23 20:25:15 +00001162 break;
1163 default:
Harald Welte5b8ed432009-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 Welte52b1f982008-12-23 20:25:15 +00001166 return -EINVAL;
1167 }
Harald Weltef325eb42009-02-19 17:07:39 +00001168
Harald Welte8470bf22008-12-25 23:28:35 +00001169 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001170}
1171
Harald Welte702d8702008-12-26 20:25:35 +00001172static int rsl_rx_error_rep(struct msgb *msg)
1173{
1174 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
Harald Welte8830e072009-07-28 17:58:09 +02001175 struct tlv_parsed tp;
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001176 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte702d8702008-12-26 20:25:35 +00001177
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001178 LOGP(DRSL, LOGL_ERROR, "%s ERROR REPORT ", gsm_trx_name(sign_link->trx));
Harald Welte8830e072009-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 Welte5b8ed432009-12-24 12:20:20 +01001183 print_rsl_cause(LOGL_ERROR, TLVP_VAL(&tp, RSL_IE_CAUSE),
Harald Welte8830e072009-07-28 17:58:09 +02001184 TLVP_LEN(&tp, RSL_IE_CAUSE));
1185
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001186 LOGPC(DRSL, LOGL_ERROR, "\n");
Harald Welte702d8702008-12-26 20:25:35 +00001187
1188 return 0;
1189}
1190
Harald Welte52b1f982008-12-23 20:25:15 +00001191static int abis_rsl_rx_trx(struct msgb *msg)
1192{
Harald Welte702d8702008-12-26 20:25:35 +00001193 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001194 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte8470bf22008-12-25 23:28:35 +00001195 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001196
1197 switch (rslh->msg_type) {
Harald Welte702d8702008-12-26 20:25:35 +00001198 case RSL_MT_ERROR_REPORT:
1199 rc = rsl_rx_error_rep(msg);
1200 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001201 case RSL_MT_RF_RES_IND:
1202 /* interference on idle channels of TRX */
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001203 //DEBUGP(DRSL, "%s RF Resource Indication\n", gsm_trx_name(sign_link->trx));
Harald Welte8f5e2392009-02-03 12:57:37 +00001204 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001205 case RSL_MT_OVERLOAD:
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +02001206 /* indicate CCCH / ACCH / processor overload */
Harald Welte (local)d48f4eb2009-12-28 23:14:22 +01001207 LOGP(DRSL, LOGL_ERROR, "%s CCCH/ACCH/CPU Overload\n",
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001208 gsm_trx_name(sign_link->trx));
Harald Welte52b1f982008-12-23 20:25:15 +00001209 break;
Dieter Spaar16646022011-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 Welte52b1f982008-12-23 20:25:15 +00001216 default:
Harald Welte (local)d48f4eb2009-12-28 23:14:22 +01001217 LOGP(DRSL, LOGL_NOTICE, "%s Unknown Abis RSL TRX message "
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001218 "type 0x%02x\n", gsm_trx_name(sign_link->trx), rslh->msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001219 return -EINVAL;
1220 }
Harald Welte8470bf22008-12-25 23:28:35 +00001221 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001222}
1223
Harald Welteb7e81162009-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 Freyther4b4dd102010-05-31 21:38:24 +08001229 rsl_rf_chan_release(lchan, 1);
Harald Welteb7e81162009-08-10 00:26:10 +02001230}
1231
Holger Hans Peter Freytherf30c0dc2010-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 Freyther4b4dd102010-05-31 21:38:24 +08001237 rsl_rf_chan_release(lchan, 0);
Holger Hans Peter Freytherf30c0dc2010-05-31 21:33:15 +08001238}
1239
laforgecfa4a012010-06-21 12:08:52 +02001240#define GSM48_LEN2PLEN(a) (((a) << 2) | 1)
1241
Harald Welte2862dca2010-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 Welte8470bf22008-12-25 23:28:35 +00001281/* MS has requested a channel on the RACH */
Harald Welte52b1f982008-12-23 20:25:15 +00001282static int rsl_rx_chan_rqd(struct msgb *msg)
1283{
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001284 struct e1inp_sign_link *sign_link = msg->dst;
1285 struct gsm_bts *bts = sign_link->trx->bts;
Harald Welte8470bf22008-12-25 23:28:35 +00001286 struct abis_rsl_dchan_hdr *rqd_hdr = msgb_l2(msg);
1287 struct gsm48_req_ref *rqd_ref;
Harald Welte8470bf22008-12-25 23:28:35 +00001288 enum gsm_chan_t lctype;
Harald Welte2cbe0922008-12-29 04:09:31 +00001289 enum gsm_chreq_reason_t chreq_reason;
Harald Welte8470bf22008-12-25 23:28:35 +00001290 struct gsm_lchan *lchan;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001291 uint8_t rqd_ta;
Holger Hans Peter Freyther457c2a82010-09-06 08:58:42 +08001292 int is_lu;
Harald Welte8470bf22008-12-25 23:28:35 +00001293
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001294 uint16_t arfcn;
Holger Hans Peter Freytherc6d0a172012-02-03 20:10:13 +01001295 uint8_t subch;
Harald Welte52b1f982008-12-23 20:25:15 +00001296
Harald Welte8470bf22008-12-25 23:28:35 +00001297 /* 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 Freyther78891072010-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 Welte2cbe0922008-12-29 04:09:31 +00001312
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +02001313 osmo_counter_inc(bts->network->stats.chreq.total);
Harald Welte24ff6ee2009-12-22 00:41:05 +01001314
Holger Hans Peter Freyther457c2a82010-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 Welte8470bf22008-12-25 23:28:35 +00001321 /* check availability / allocate channel */
Holger Hans Peter Freyther457c2a82010-09-06 08:58:42 +08001322 lchan = lchan_alloc(bts, lctype, is_lu);
Harald Welte8470bf22008-12-25 23:28:35 +00001323 if (!lchan) {
Harald Welte (local)2f5df852009-12-27 13:48:09 +01001324 LOGP(DRSL, LOGL_NOTICE, "BTS %d CHAN RQD: no resources for %s 0x%x\n",
Harald Welte (local)ccd88452009-12-27 18:05:25 +01001325 msg->lchan->ts->trx->bts->nr, gsm_lchant_name(lctype), rqd_ref->ra);
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +02001326 osmo_counter_inc(bts->network->stats.chreq.no_channel);
Harald Welte2862dca2010-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 Welte8470bf22008-12-25 23:28:35 +00001330 return -ENOMEM;
1331 }
1332
Harald Welte8e93b792009-12-29 10:44:17 +01001333 if (lchan->state != LCHAN_S_NONE)
1334 LOGP(DRSL, LOGL_NOTICE, "%s lchan_alloc() returned channel "
Harald Welte1887f9d2009-12-29 10:52:38 +01001335 "in state %s\n", gsm_lchan_name(lchan),
1336 gsm_lchans_name(lchan->state));
Harald Welte (local)3e460312009-12-27 18:12:29 +01001337
Holger Hans Peter Freyther5ba05f42010-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 Freytherc0a66742011-12-29 23:33:04 +01001346 rsl_lchan_set_state(lchan, LCHAN_S_ACT_REQ);
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +08001347 memcpy(lchan->rqd_ref, rqd_ref, sizeof(*rqd_ref));
1348 lchan->rqd_ta = rqd_ta;
1349
Harald Welte8470bf22008-12-25 23:28:35 +00001350 arfcn = lchan->ts->trx->arfcn;
1351 subch = lchan->nr;
Harald Welte52b1f982008-12-23 20:25:15 +00001352
Harald Welte08d91a52009-08-30 15:37:11 +09001353 lchan->encr.alg_id = RSL_ENC_ALG_A5(0); /* no encryption */
Harald Welte (local)0e451d02009-08-13 10:14:26 +02001354 lchan->ms_power = ms_pwr_ctl_lvl(bts->band, bts->ms_max_power);
Harald Welte0b2124b2009-08-10 00:45:40 +02001355 lchan->bs_power = 0; /* 0dB reduction, output power = Pn */
Harald Welte9943c5b2009-07-29 15:41:29 +02001356 lchan->rsl_cmode = RSL_CMOD_SPD_SIGN;
Harald Welte196d0522009-08-28 23:28:28 +09001357 lchan->tch_mode = GSM48_CMODE_SIGN;
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +08001358
Harald Weltee8bd9e82011-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 Eversberg2957de92011-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 Welte8d77b952009-12-17 00:31:10 +01001372 rsl_chan_activate_lchan(lchan, 0x00, rqd_ta, 0);
Harald Welte52b1f982008-12-23 20:25:15 +00001373
Holger Hans Peter Freyther5ba05f42010-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 Freytherc42ad8b2011-04-18 17:04:00 +02001380 uint8_t buf[GSM_MACBLOCK_LEN];
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +08001381 struct gsm48_imm_ass *ia = (struct gsm48_imm_ass *) buf;
1382
Harald Welte52b1f982008-12-23 20:25:15 +00001383 /* create IMMEDIATE ASSIGN 04.08 messge */
laforge09108bf2010-06-20 15:18:46 +02001384 memset(ia, 0, sizeof(*ia));
laforgecfa4a012010-06-21 12:08:52 +02001385 /* we set ia->l2_plen once we know the length of the MA below */
laforge09108bf2010-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 Weltea39b0f22010-06-14 22:26:10 +02001390
Harald Welte8470bf22008-12-25 23:28:35 +00001391 /* use request reference extracted from CHAN_RQD */
Holger Hans Peter Freyther5ba05f42010-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 Weltea39b0f22010-06-14 22:26:10 +02001394 if (!lchan->ts->hopping.enabled) {
laforge09108bf2010-06-20 15:18:46 +02001395 ia->mob_alloc_len = 0;
Harald Weltea39b0f22010-06-14 22:26:10 +02001396 } else {
laforge09108bf2010-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 Weltea39b0f22010-06-14 22:26:10 +02001399 }
Harald Weltea1d39a22010-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 Welte52b1f982008-12-23 20:25:15 +00001402
Harald Welteb7e81162009-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 Ayusobf540cb2011-05-06 12:11:06 +02001406 osmo_timer_schedule(&lchan->T3101, bts->network->T3101, 0);
Holger Freyther3186bf22008-12-29 06:23:49 +00001407
Harald Welte52b1f982008-12-23 20:25:15 +00001408 /* send IMMEDIATE ASSIGN CMD on RSL to BTS (to send on CCCH to MS) */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001409 return rsl_imm_assign_cmd(bts, sizeof(*ia)+ia->mob_alloc_len, (uint8_t *) ia);
Harald Welte52b1f982008-12-23 20:25:15 +00001410}
1411
Holger Hans Peter Freyther54fa2c72012-02-03 20:26:25 +01001412/* current load on the CCCH */
Harald Welteea280442009-02-02 22:29:56 +00001413static int rsl_rx_ccch_load(struct msgb *msg)
1414{
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001415 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welteea280442009-02-02 22:29:56 +00001416 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
Holger Hans Peter Freyther54fa2c72012-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 Welteea280442009-02-02 22:29:56 +00001423
1424 switch (rslh->data[0]) {
1425 case RSL_IE_PAGING_LOAD:
Holger Hans Peter Freyther54fa2c72012-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 Welte38e9c822010-04-19 10:24:07 +02001428 /* paging load below configured threshold, use 50 as default */
Holger Hans Peter Freyther54fa2c72012-02-03 20:26:25 +01001429 sd.pg_buf_space = 50;
Harald Welte38e9c822010-04-19 10:24:07 +02001430 }
Holger Hans Peter Freyther54fa2c72012-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 Welteea280442009-02-02 22:29:56 +00001433 break;
1434 case RSL_IE_RACH_LOAD:
Holger Freyther8c563cf2009-02-03 20:08:51 +00001435 if (msg->data_len >= 7) {
Holger Hans Peter Freyther54fa2c72012-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);
Holger Freyther8c563cf2009-02-03 20:08:51 +00001440 }
Harald Welteea280442009-02-02 22:29:56 +00001441 break;
1442 default:
1443 break;
1444 }
1445
1446 return 0;
1447}
1448
Harald Welte52b1f982008-12-23 20:25:15 +00001449static int abis_rsl_rx_cchan(struct msgb *msg)
1450{
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001451 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welteea280442009-02-02 22:29:56 +00001452 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001453 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001454
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001455 msg->lchan = lchan_lookup(sign_link->trx, rslh->chan_nr);
Harald Welte8470bf22008-12-25 23:28:35 +00001456
1457 switch (rslh->c.msg_type) {
Harald Welte52b1f982008-12-23 20:25:15 +00001458 case RSL_MT_CHAN_RQD:
1459 /* MS has requested a channel on the RACH */
1460 rc = rsl_rx_chan_rqd(msg);
1461 break;
Harald Welteea280442009-02-02 22:29:56 +00001462 case RSL_MT_CCCH_LOAD_IND:
1463 /* current load on the CCCH */
1464 rc = rsl_rx_ccch_load(msg);
1465 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001466 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 Welteb1d4c8e2009-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 Welte52b1f982008-12-23 20:25:15 +00001472 break;
1473 default:
Harald Welteb1d4c8e2009-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 Welte52b1f982008-12-23 20:25:15 +00001476 return -EINVAL;
1477 }
Harald Welte8470bf22008-12-25 23:28:35 +00001478
1479 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001480}
1481
Harald Welte4b634542008-12-27 01:55:51 +00001482static int rsl_rx_rll_err_ind(struct msgb *msg)
1483{
1484 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001485 uint8_t *rlm_cause = rllh->data;
Harald Welte4b634542008-12-27 01:55:51 +00001486
Harald Welte (local)9538efc2009-12-26 23:55:00 +01001487 LOGP(DRLL, LOGL_ERROR, "%s ERROR INDICATION cause=%s\n",
Harald Welte (local)19ef62a2009-12-27 18:16:36 +01001488 gsm_lchan_name(msg->lchan),
Harald Weltee95daf12010-03-25 12:13:02 +08001489 rsl_rlm_cause_name(rlm_cause[1]));
Harald Welteedcc5272009-08-09 13:47:35 +02001490
1491 rll_indication(msg->lchan, rllh->link_id, BSC_RLLR_IND_ERR_IND);
Harald Welte (local)9538efc2009-12-26 23:55:00 +01001492
Holger Hans Peter Freyther3ba36d52010-04-17 06:48:29 +02001493 if (rlm_cause[1] == RLL_CAUSE_T200_EXPIRED) {
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +02001494 osmo_counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rll_err);
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +08001495 return rsl_rf_chan_release(msg->lchan, 1);
Holger Hans Peter Freyther3ba36d52010-04-17 06:48:29 +02001496 }
Harald Welte81543bc2009-07-04 09:40:05 +02001497
Harald Welte4b634542008-12-27 01:55:51 +00001498 return 0;
1499}
Harald Weltef325eb42009-02-19 17:07:39 +00001500
Holger Hans Peter Freytherdbc5fae2010-04-08 22:39:34 +02001501static void rsl_handle_release(struct gsm_lchan *lchan)
1502{
Holger Hans Peter Freyther4b85a322010-07-29 17:09:36 +08001503 int sapi;
Holger Hans Peter Freytherf30c0dc2010-05-31 21:33:15 +08001504 struct gsm_bts *bts;
Holger Hans Peter Freyther4b85a322010-07-29 17:09:36 +08001505
1506 /* maybe we have only brought down one RLL */
Holger Hans Peter Freytherd7fd3062010-04-08 22:47:44 +02001507 if (lchan->state != LCHAN_S_REL_REQ)
Holger Hans Peter Freyther4b85a322010-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 Welte3a3c2772010-12-24 12:51:07 +01001513 LOGP(DRSL, LOGL_DEBUG, "%s waiting for SAPI=%d to be released.\n",
Holger Hans Peter Freyther4b85a322010-07-29 17:09:36 +08001514 gsm_lchan_name(lchan), sapi);
1515 return;
1516 }
1517
Holger Hans Peter Freytherd7fd3062010-04-08 22:47:44 +02001518
1519
Holger Hans Peter Freytherf30c0dc2010-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 Ayusobf540cb2011-05-06 12:11:06 +02001524 osmo_timer_schedule(&lchan->T3111, bts->network->T3111, 0);
Holger Hans Peter Freytherdbc5fae2010-04-08 22:39:34 +02001525}
1526
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +02001527/* ESTABLISH INDICATION, LOCATION AREA UPDATE REQUEST
Harald Welte52b1f982008-12-23 20:25:15 +00001528 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 Ayuso7abecfc2011-08-17 22:43:54 +02001535 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte52b1f982008-12-23 20:25:15 +00001536 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
Harald Weltef325eb42009-02-19 17:07:39 +00001537 int rc = 0;
1538 char *ts_name;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001539 uint8_t sapi = rllh->link_id & 7;
Harald Welte8470bf22008-12-25 23:28:35 +00001540
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001541 msg->lchan = lchan_lookup(sign_link->trx, rllh->chan_nr);
Harald Welte (local)19ef62a2009-12-27 18:16:36 +01001542 ts_name = gsm_lchan_name(msg->lchan);
Harald Welte5b8ed432009-12-24 12:20:20 +01001543 DEBUGP(DRLL, "%s SAPI=%u ", ts_name, sapi);
Harald Welte52b1f982008-12-23 20:25:15 +00001544
1545 switch (rllh->c.msg_type) {
1546 case RSL_MT_DATA_IND:
Harald Weltef325eb42009-02-19 17:07:39 +00001547 DEBUGPC(DRLL, "DATA INDICATION\n");
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +02001548 if (msgb_l2len(msg) >
Harald Welte4a543e82009-02-28 13:17:55 +00001549 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)daef6062009-08-14 11:41:12 +02001552 return gsm0408_rcvmsg(msg, rllh->link_id);
Harald Welte4a543e82009-02-28 13:17:55 +00001553 }
Harald Welte52b1f982008-12-23 20:25:15 +00001554 break;
1555 case RSL_MT_EST_IND:
Harald Weltef325eb42009-02-19 17:07:39 +00001556 DEBUGPC(DRLL, "ESTABLISH INDICATION\n");
Harald Welteb7e81162009-08-10 00:26:10 +02001557 /* lchan is established, stop T3101 */
Holger Hans Peter Freyther5ba6f482009-10-28 14:23:39 +01001558 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_MS;
Pablo Neira Ayusobf540cb2011-05-06 12:11:06 +02001559 osmo_timer_del(&msg->lchan->T3101);
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +02001560 if (msgb_l2len(msg) >
Harald Welte4a543e82009-02-28 13:17:55 +00001561 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)daef6062009-08-14 11:41:12 +02001564 return gsm0408_rcvmsg(msg, rllh->link_id);
Harald Welte4a543e82009-02-28 13:17:55 +00001565 }
Harald Welte52b1f982008-12-23 20:25:15 +00001566 break;
Harald Welteedcc5272009-08-09 13:47:35 +02001567 case RSL_MT_EST_CONF:
Harald Welte1c409272009-08-09 14:13:58 +02001568 DEBUGPC(DRLL, "ESTABLISH CONFIRM\n");
Holger Hans Peter Freyther5ba6f482009-10-28 14:23:39 +01001569 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_NET;
Harald Welteedcc5272009-08-09 13:47:35 +02001570 rll_indication(msg->lchan, rllh->link_id,
1571 BSC_RLLR_IND_EST_CONF);
1572 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001573 case RSL_MT_REL_IND:
Harald Welted2dc1de2009-08-08 13:15:07 +02001574 /* BTS informs us of having received DISC from MS */
Harald Welte602f2b82009-08-04 02:50:21 +02001575 DEBUGPC(DRLL, "RELEASE INDICATION\n");
Holger Hans Peter Freyther5ba6f482009-10-28 14:23:39 +01001576 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_UNUSED;
Harald Welteedcc5272009-08-09 13:47:35 +02001577 rll_indication(msg->lchan, rllh->link_id,
1578 BSC_RLLR_IND_REL_IND);
Holger Hans Peter Freytherdbc5fae2010-04-08 22:39:34 +02001579 rsl_handle_release(msg->lchan);
Holger Hans Peter Freyther4b85a322010-07-29 17:09:36 +08001580 rsl_lchan_rll_release(msg->lchan, rllh->link_id);
Harald Welte2d5b6382008-12-27 19:46:06 +00001581 break;
1582 case RSL_MT_REL_CONF:
Harald Welted2dc1de2009-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 Welte602f2b82009-08-04 02:50:21 +02001585 DEBUGPC(DRLL, "RELEASE CONFIRMATION\n");
Holger Hans Peter Freyther5ba6f482009-10-28 14:23:39 +01001586 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_UNUSED;
Holger Hans Peter Freytherdbc5fae2010-04-08 22:39:34 +02001587 rsl_handle_release(msg->lchan);
Holger Hans Peter Freyther4b85a322010-07-29 17:09:36 +08001588 rsl_lchan_rll_release(msg->lchan, rllh->link_id);
Harald Welte4b634542008-12-27 01:55:51 +00001589 break;
1590 case RSL_MT_ERROR_IND:
1591 rc = rsl_rx_rll_err_ind(msg);
1592 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001593 case RSL_MT_UNIT_DATA_IND:
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001594 LOGP(DRLL, LOGL_NOTICE, "unimplemented Abis RLL message "
1595 "type 0x%02x\n", rllh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001596 break;
1597 default:
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001598 LOGP(DRLL, LOGL_NOTICE, "unknown Abis RLL message "
1599 "type 0x%02x\n", rllh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001600 }
Harald Welte8470bf22008-12-25 23:28:35 +00001601 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001602}
1603
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001604static uint8_t ipa_smod_s_for_lchan(struct gsm_lchan *lchan)
Harald Weltef4e79f22009-07-28 18:11:56 +02001605{
Harald Welte0603c9d2009-12-02 01:58:23 +05301606 switch (lchan->tch_mode) {
Harald Weltef4e79f22009-07-28 18:11:56 +02001607 case GSM48_CMODE_SPEECH_V1:
Harald Welte0603c9d2009-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 Weltef4e79f22009-07-28 18:11:56 +02001616 case GSM48_CMODE_SPEECH_EFR:
Harald Welte0603c9d2009-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 Weltef4e79f22009-07-28 18:11:56 +02001624 case GSM48_CMODE_SPEECH_AMR:
Harald Welte0603c9d2009-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 Weltef4e79f22009-07-28 18:11:56 +02001635 }
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001636 LOGP(DRSL, LOGL_ERROR, "Cannot determine ip.access speech mode for "
Harald Welte0603c9d2009-12-02 01:58:23 +05301637 "tch_mode == 0x%02x\n", lchan->tch_mode);
Harald Weltef4e79f22009-07-28 18:11:56 +02001638 return 0;
Harald Weltef4e79f22009-07-28 18:11:56 +02001639}
1640
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001641static uint8_t ipa_rtp_pt_for_lchan(struct gsm_lchan *lchan)
Sylvain Munautb54dda42009-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 Munautb54dda42009-12-20 22:06:40 +01001664 case GSM_LCHAN_TCH_H:
Holger Hans Peter Freythered999b22011-07-21 10:24:46 +02001665 return RTP_PT_AMR;
Sylvain Munautb54dda42009-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 Welte75099262009-02-16 21:12:08 +00001678/* ip.access specific RSL extensions */
Harald Welte5e3d91b2009-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 Freytherc42ad8b2011-04-18 17:04:00 +02001682 uint16_t port, conn_id;
Harald Welte5e3d91b2009-12-19 16:42:06 +01001683
1684 if (TLVP_PRESENT(tv, RSL_IE_IPAC_LOCAL_IP)) {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001685 ip.s_addr = *((uint32_t *) TLVP_VAL(tv, RSL_IE_IPAC_LOCAL_IP));
Harald Welte5e3d91b2009-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 Freytherc42ad8b2011-04-18 17:04:00 +02001691 port = *((uint16_t *) TLVP_VAL(tv, RSL_IE_IPAC_LOCAL_PORT));
Harald Welte5e3d91b2009-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 Freytherc42ad8b2011-04-18 17:04:00 +02001698 conn_id = *((uint16_t *) TLVP_VAL(tv, RSL_IE_IPAC_CONN_ID));
Harald Welte5e3d91b2009-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 Freytherc42ad8b2011-04-18 17:04:00 +02001719 ip.s_addr = *((uint32_t *) TLVP_VAL(tv, RSL_IE_IPAC_REMOTE_IP));
Harald Welte5e3d91b2009-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 Freytherc42ad8b2011-04-18 17:04:00 +02001725 port = *((uint16_t *) TLVP_VAL(tv, RSL_IE_IPAC_REMOTE_PORT));
Harald Welte5e3d91b2009-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 Freyther231163d2009-11-18 21:06:12 +01001732int rsl_ipacc_crcx(struct gsm_lchan *lchan)
Harald Welte75099262009-02-16 21:12:08 +00001733{
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 Freyther231163d2009-11-18 21:06:12 +01001738 init_dchan_hdr(dh, RSL_MT_IPAC_CRCX);
Harald Welte75099262009-02-16 21:12:08 +00001739 dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
Harald Weltef6093a42011-06-25 10:02:33 +02001740 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte75099262009-02-16 21:12:08 +00001741
Harald Weltef4e79f22009-07-28 18:11:56 +02001742 /* 0x1- == receive-only, 0x-1 == EFR codec */
Harald Welte5e3d91b2009-12-19 16:42:06 +01001743 lchan->abis_ip.speech_mode = 0x10 | ipa_smod_s_for_lchan(lchan);
Sylvain Munautb54dda42009-12-20 22:06:40 +01001744 lchan->abis_ip.rtp_payload = ipa_rtp_pt_for_lchan(lchan);
Harald Welte5e3d91b2009-12-19 16:42:06 +01001745 msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, lchan->abis_ip.speech_mode);
Sylvain Munautb54dda42009-12-20 22:06:40 +01001746 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD, lchan->abis_ip.rtp_payload);
Harald Weltef4e79f22009-07-28 18:11:56 +02001747
Sylvain Munautb54dda42009-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 Weltef4e79f22009-07-28 18:11:56 +02001751
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001752 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte75099262009-02-16 21:12:08 +00001753
1754 return abis_rsl_sendmsg(msg);
1755}
1756
Holger Hans Peter Freytherc42ad8b2011-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 Welte75099262009-02-16 21:12:08 +00001759{
1760 struct msgb *msg = rsl_msgb_alloc();
1761 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001762 uint32_t *att_ip;
Harald Weltef4e79f22009-07-28 18:11:56 +02001763 struct in_addr ia;
Harald Welte75099262009-02-16 21:12:08 +00001764
1765 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001766 init_dchan_hdr(dh, RSL_MT_IPAC_MDCX);
Harald Welte75099262009-02-16 21:12:08 +00001767 dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
Harald Weltef6093a42011-06-25 10:02:33 +02001768 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte75099262009-02-16 21:12:08 +00001769
Harald Welte5e3d91b2009-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 Welte58ca5b72009-07-29 12:12:18 +02001775 /* 0x0- == both directions, 0x-1 == EFR codec */
Harald Welte5e3d91b2009-12-19 16:42:06 +01001776 lchan->abis_ip.speech_mode = 0x00 | ipa_smod_s_for_lchan(lchan);
Sylvain Munautb54dda42009-12-20 22:06:40 +01001777 lchan->abis_ip.rtp_payload = ipa_rtp_pt_for_lchan(lchan);
Harald Welte58ca5b72009-07-29 12:12:18 +02001778
Harald Weltef4e79f22009-07-28 18:11:56 +02001779 ia.s_addr = htonl(ip);
Sylvain Munautb54dda42009-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 Weltef4e79f22009-07-28 18:11:56 +02001784
Harald Welte5e3d91b2009-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 Freytherc42ad8b2011-04-18 17:04:00 +02001787 att_ip = (uint32_t *) msgb_put(msg, sizeof(ip));
Harald Welte5e3d91b2009-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 Munautb54dda42009-12-20 22:06:40 +01001791 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD, lchan->abis_ip.rtp_payload);
Harald Weltef4e79f22009-07-28 18:11:56 +02001792 if (rtp_payload2)
1793 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD2, rtp_payload2);
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001794
1795 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte75099262009-02-16 21:12:08 +00001796
1797 return abis_rsl_sendmsg(msg);
1798}
1799
Harald Weltea72273e2009-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 Welte53cd7ac2010-12-23 12:59:52 +01001814int rsl_ipacc_pdch_activate(struct gsm_bts_trx_ts *ts, int act)
Harald Welte9c880c92009-10-24 10:29:22 +02001815{
1816 struct msgb *msg = rsl_msgb_alloc();
1817 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001818 uint8_t msg_type;
Harald Welte4563eab2010-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 Welte9c880c92009-10-24 10:29:22 +02001824
1825 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Harald Welte4563eab2010-03-28 14:42:09 +08001826 init_dchan_hdr(dh, msg_type);
Harald Welte9c880c92009-10-24 10:29:22 +02001827 dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
Harald Weltef6093a42011-06-25 10:02:33 +02001828 dh->chan_nr = gsm_ts2chan_nr(ts, 0);
Harald Welte9c880c92009-10-24 10:29:22 +02001829
Harald Welte53cd7ac2010-12-23 12:59:52 +01001830 DEBUGP(DRSL, "%s IPAC_PDCH_%sACT\n", gsm_ts_name(ts),
Harald Welte4563eab2010-03-28 14:42:09 +08001831 act ? "" : "DE");
Harald Welte9c880c92009-10-24 10:29:22 +02001832
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001833 msg->dst = ts->trx->rsl_link;
Harald Welte9c880c92009-10-24 10:29:22 +02001834
1835 return abis_rsl_sendmsg(msg);
1836}
1837
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001838static int abis_rsl_rx_ipacc_crcx_ack(struct msgb *msg)
Harald Welte75099262009-02-16 21:12:08 +00001839{
1840 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1841 struct tlv_parsed tv;
Harald Welte2c828992009-12-02 01:56:49 +05301842 struct gsm_lchan *lchan = msg->lchan;
Harald Welte75099262009-02-16 21:12:08 +00001843
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 Welte86c162d2009-07-12 09:45:05 +02001851 !TLVP_PRESENT(&tv, RSL_IE_IPAC_CONN_ID)) {
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001852 LOGP(DRSL, LOGL_NOTICE, "mandatory IE missing");
Harald Welte75099262009-02-16 21:12:08 +00001853 return -EINVAL;
1854 }
Harald Welte17f5bf62009-12-20 15:42:44 +01001855
Harald Welte5e3d91b2009-12-19 16:42:06 +01001856 ipac_parse_rtp(lchan, &tv);
Harald Welte17f5bf62009-12-20 15:42:44 +01001857
Pablo Neira Ayusobbc5b992011-05-06 12:12:31 +02001858 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_CRCX_ACK, msg->lchan);
Harald Welte167df882009-02-17 14:35:45 +00001859
Harald Welte75099262009-02-16 21:12:08 +00001860 return 0;
1861}
1862
Harald Welte5e3d91b2009-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 Ayusobbc5b992011-05-06 12:12:31 +02001875 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_MDCX_ACK, msg->lchan);
Harald Welte5e3d91b2009-12-19 16:42:06 +01001876
1877 return 0;
1878}
1879
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001880static int abis_rsl_rx_ipacc_dlcx_ind(struct msgb *msg)
Harald Welte75099262009-02-16 21:12:08 +00001881{
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 Welte75099262009-02-16 21:12:08 +00001886
Harald Welte8830e072009-07-28 17:58:09 +02001887 if (TLVP_PRESENT(&tv, RSL_IE_CAUSE))
Harald Welte5b8ed432009-12-24 12:20:20 +01001888 print_rsl_cause(LOGL_DEBUG, TLVP_VAL(&tv, RSL_IE_CAUSE),
Harald Welte8830e072009-07-28 17:58:09 +02001889 TLVP_LEN(&tv, RSL_IE_CAUSE));
Harald Welte75099262009-02-16 21:12:08 +00001890
Pablo Neira Ayusobbc5b992011-05-06 12:12:31 +02001891 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_DLCX_IND, msg->lchan);
Harald Welte888b1142009-07-28 18:02:05 +02001892
Harald Welte75099262009-02-16 21:12:08 +00001893 return 0;
1894}
1895
1896static int abis_rsl_rx_ipacc(struct msgb *msg)
1897{
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001898 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte75099262009-02-16 21:12:08 +00001899 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
Harald Welte5b8ed432009-12-24 12:20:20 +01001900 char *ts_name;
Harald Welte75099262009-02-16 21:12:08 +00001901 int rc = 0;
1902
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001903 msg->lchan = lchan_lookup(sign_link->trx, rllh->chan_nr);
Harald Welte (local)19ef62a2009-12-27 18:16:36 +01001904 ts_name = gsm_lchan_name(msg->lchan);
Harald Welte75099262009-02-16 21:12:08 +00001905
1906 switch (rllh->c.msg_type) {
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001907 case RSL_MT_IPAC_CRCX_ACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001908 DEBUGP(DRSL, "%s IPAC_CRCX_ACK ", ts_name);
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001909 rc = abis_rsl_rx_ipacc_crcx_ack(msg);
Harald Welte75099262009-02-16 21:12:08 +00001910 break;
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001911 case RSL_MT_IPAC_CRCX_NACK:
Harald Welte75099262009-02-16 21:12:08 +00001912 /* somehow the BTS was unable to bind the lchan to its local
1913 * port?!? */
Harald Welte5b8ed432009-12-24 12:20:20 +01001914 LOGP(DRSL, LOGL_ERROR, "%s IPAC_CRCX_NACK\n", ts_name);
Harald Welte75099262009-02-16 21:12:08 +00001915 break;
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001916 case RSL_MT_IPAC_MDCX_ACK:
Harald Welte75099262009-02-16 21:12:08 +00001917 /* the BTS tells us that a connect operation was successful */
Harald Welte5b8ed432009-12-24 12:20:20 +01001918 DEBUGP(DRSL, "%s IPAC_MDCX_ACK ", ts_name);
Harald Welte5e3d91b2009-12-19 16:42:06 +01001919 rc = abis_rsl_rx_ipacc_mdcx_ack(msg);
Harald Welte75099262009-02-16 21:12:08 +00001920 break;
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001921 case RSL_MT_IPAC_MDCX_NACK:
Harald Welte75099262009-02-16 21:12:08 +00001922 /* somehow the BTS was unable to connect the lchan to a remote
1923 * port */
Harald Welte5b8ed432009-12-24 12:20:20 +01001924 LOGP(DRSL, LOGL_ERROR, "%s IPAC_MDCX_NACK\n", ts_name);
Harald Welte75099262009-02-16 21:12:08 +00001925 break;
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001926 case RSL_MT_IPAC_DLCX_IND:
Harald Welte5b8ed432009-12-24 12:20:20 +01001927 DEBUGP(DRSL, "%s IPAC_DLCX_IND ", ts_name);
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001928 rc = abis_rsl_rx_ipacc_dlcx_ind(msg);
Harald Welte75099262009-02-16 21:12:08 +00001929 break;
1930 default:
Harald Welte5b8ed432009-12-24 12:20:20 +01001931 LOGP(DRSL, LOGL_NOTICE, "Unknown ip.access msg_type 0x%02x\n",
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001932 rllh->c.msg_type);
Harald Welte75099262009-02-16 21:12:08 +00001933 break;
1934 }
Harald Welte6dab0552009-05-01 17:21:37 +00001935 DEBUGPC(DRSL, "\n");
Harald Welte75099262009-02-16 21:12:08 +00001936
1937 return rc;
1938}
1939
1940
Harald Welte52b1f982008-12-23 20:25:15 +00001941/* Entry-point where L2 RSL from BTS enters */
Harald Welte8470bf22008-12-25 23:28:35 +00001942int abis_rsl_rcvmsg(struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +00001943{
Holger Hans Peter Freyther19bab732009-11-20 15:14:01 +01001944 struct abis_rsl_common_hdr *rslh;
Harald Welte8f5e2392009-02-03 12:57:37 +00001945 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001946
Holger Hans Peter Freyther19bab732009-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 Weltef25b55e2012-05-31 20:22:34 +02001954 msgb_free(msg);
Holger Hans Peter Freyther19bab732009-11-20 15:14:01 +01001955 return -1;
1956 }
1957
1958 rslh = msgb_l2(msg);
1959
Harald Welte52b1f982008-12-23 20:25:15 +00001960 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:
Harald Welte52b1f982008-12-23 20:25:15 +00001968 rc = abis_rsl_rx_cchan(msg);
1969 break;
Harald Welte8470bf22008-12-25 23:28:35 +00001970 case ABIS_RSL_MDISC_TRX:
1971 rc = abis_rsl_rx_trx(msg);
1972 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001973 case ABIS_RSL_MDISC_LOC:
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001974 LOGP(DRSL, LOGL_NOTICE, "unimplemented RSL msg disc 0x%02x\n",
Harald Welte8f5e2392009-02-03 12:57:37 +00001975 rslh->msg_discr);
1976 break;
Harald Welte75099262009-02-16 21:12:08 +00001977 case ABIS_RSL_MDISC_IPACCESS:
1978 rc = abis_rsl_rx_ipacc(msg);
1979 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001980 default:
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001981 LOGP(DRSL, LOGL_NOTICE, "unknown RSL message discriminator "
1982 "0x%02x\n", rslh->msg_discr);
Harald Weltef25b55e2012-05-31 20:22:34 +02001983 rc = -EINVAL;
Harald Welte52b1f982008-12-23 20:25:15 +00001984 }
Harald Welte4f4a3902008-12-26 00:04:49 +00001985 msgb_free(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001986 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001987}
Holger Freyther3b72a892009-02-04 00:31:39 +00001988
Holger Hans Peter Freyther8cb4a0f2010-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 Spaar16646022011-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 Ayuso7abecfc2011-08-17 22:43:54 +02002020 msg->dst = trx->rsl_link;
Dieter Spaar16646022011-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 Ayuso7abecfc2011-08-17 22:43:54 +02002036 msg->dst = trx->rsl_link;
Dieter Spaar16646022011-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 Ayuso7abecfc2011-08-17 22:43:54 +02002053 msg->dst = trx->rsl_link;
Dieter Spaar16646022011-07-28 00:01:50 +02002054
2055 return abis_rsl_sendmsg(msg);
2056}