blob: 6f50cee16c0a0e61cd7d8b09b3cbcb3dd6eab722 [file] [log] [blame]
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +02001/* GSM Radio Signalling Link messages on the A-bis interface
Harald Welte59b04682009-06-10 05:40:52 +08002 * 3GPP TS 08.58 version 8.6.0 Release 1999 / ETSI TS 100 596 V8.6.0 */
3
Harald Weltea22d36b2010-03-04 10:33:10 +01004/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
Harald Welte59b04682009-06-10 05:40:52 +08005 *
6 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
Harald Welte0e3e88e2011-01-01 15:25:50 +01009 * it under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
Harald Welte59b04682009-06-10 05:40:52 +080011 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Harald Welte0e3e88e2011-01-01 15:25:50 +010016 * GNU Affero General Public License for more details.
Harald Welte59b04682009-06-10 05:40:52 +080017 *
Harald Welte0e3e88e2011-01-01 15:25:50 +010018 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Harald Welte59b04682009-06-10 05:40:52 +080020 *
21 */
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <errno.h>
Harald Welte59b04682009-06-10 05:40:52 +080026#include <netinet/in.h>
27#include <arpa/inet.h>
28
29#include <openbsc/gsm_data.h>
30#include <openbsc/gsm_04_08.h>
Pablo Neira Ayusodd5fff42011-03-22 16:47:59 +010031#include <osmocom/gsm/gsm_utils.h>
Harald Welte59b04682009-06-10 05:40:52 +080032#include <openbsc/abis_rsl.h>
33#include <openbsc/chan_alloc.h>
Harald Welteed9a5ab2009-08-09 13:47:35 +020034#include <openbsc/bsc_rll.h>
Harald Welte59b04682009-06-10 05:40:52 +080035#include <openbsc/debug.h>
Pablo Neira Ayusodd5fff42011-03-22 16:47:59 +010036#include <osmocom/gsm/tlv.h>
Harald Welte59b04682009-06-10 05:40:52 +080037#include <openbsc/paging.h>
38#include <openbsc/signal.h>
Harald Weltec20bd1d2009-11-29 19:07:28 +010039#include <openbsc/meas_rep.h>
Harald Welte50517742009-12-20 15:42:44 +010040#include <openbsc/rtp_proxy.h>
Pablo Neira Ayuso42e41df2011-08-17 22:44:07 +020041#include <osmocom/abis/e1_input.h>
Pablo Neira Ayusodd5fff42011-03-22 16:47:59 +010042#include <osmocom/gsm/rsl.h>
Pablo Neira Ayusodd5fff42011-03-22 16:47:59 +010043#include <osmocom/core/talloc.h>
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +080044
Harald Welte59b04682009-06-10 05:40:52 +080045#define RSL_ALLOC_SIZE 1024
46#define RSL_ALLOC_HEADROOM 128
47
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +080048static int rsl_send_imm_assignment(struct gsm_lchan *lchan);
49
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +010050static void send_lchan_signal(int sig_no, struct gsm_lchan *lchan,
51 struct gsm_meas_rep *resp)
52{
53 struct lchan_signal_data sig;
54 sig.lchan = lchan;
55 sig.mr = resp;
Pablo Neira Ayusoef717c62011-05-06 12:12:31 +020056 osmo_signal_dispatch(SS_LCHAN, sig_no, &sig);
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +010057}
58
Holger Hans Peter Freytherc22f2992012-12-06 19:09:58 +010059static void do_lchan_free(struct gsm_lchan *lchan)
60{
61 /* we have an error timer pending to release that */
62 if (lchan->state != LCHAN_S_REL_ERR)
63 rsl_lchan_set_state(lchan, LCHAN_S_NONE);
64 lchan_free(lchan);
65}
66
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +020067static uint8_t mdisc_by_msgtype(uint8_t msg_type)
Harald Welte59b04682009-06-10 05:40:52 +080068{
69 /* mask off the transparent bit ? */
70 msg_type &= 0xfe;
71
72 if ((msg_type & 0xf0) == 0x00)
73 return ABIS_RSL_MDISC_RLL;
74 if ((msg_type & 0xf0) == 0x10) {
75 if (msg_type >= 0x19 && msg_type <= 0x22)
76 return ABIS_RSL_MDISC_TRX;
77 else
78 return ABIS_RSL_MDISC_COM_CHAN;
79 }
80 if ((msg_type & 0xe0) == 0x20)
81 return ABIS_RSL_MDISC_DED_CHAN;
82
83 return ABIS_RSL_MDISC_LOC;
84}
85
86static inline void init_dchan_hdr(struct abis_rsl_dchan_hdr *dh,
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +020087 uint8_t msg_type)
Harald Welte59b04682009-06-10 05:40:52 +080088{
89 dh->c.msg_discr = mdisc_by_msgtype(msg_type);
90 dh->c.msg_type = msg_type;
91 dh->ie_chan = RSL_IE_CHAN_NR;
92}
93
Harald Welte59b04682009-06-10 05:40:52 +080094/* determine logical channel based on TRX and channel number IE */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +020095struct gsm_lchan *lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr)
Harald Welte59b04682009-06-10 05:40:52 +080096{
97 struct gsm_lchan *lchan;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +020098 uint8_t ts_nr = chan_nr & 0x07;
99 uint8_t cbits = chan_nr >> 3;
100 uint8_t lch_idx;
Harald Welte59b04682009-06-10 05:40:52 +0800101 struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr];
102
103 if (cbits == 0x01) {
104 lch_idx = 0; /* TCH/F */
Harald Welte37884ed2009-10-24 10:25:50 +0200105 if (ts->pchan != GSM_PCHAN_TCH_F &&
106 ts->pchan != GSM_PCHAN_PDCH &&
107 ts->pchan != GSM_PCHAN_TCH_F_PDCH)
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100108 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte59b04682009-06-10 05:40:52 +0800109 chan_nr, ts->pchan);
110 } else if ((cbits & 0x1e) == 0x02) {
111 lch_idx = cbits & 0x1; /* TCH/H */
112 if (ts->pchan != GSM_PCHAN_TCH_H)
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100113 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte59b04682009-06-10 05:40:52 +0800114 chan_nr, ts->pchan);
115 } else if ((cbits & 0x1c) == 0x04) {
116 lch_idx = cbits & 0x3; /* SDCCH/4 */
117 if (ts->pchan != GSM_PCHAN_CCCH_SDCCH4)
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100118 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte59b04682009-06-10 05:40:52 +0800119 chan_nr, ts->pchan);
120 } else if ((cbits & 0x18) == 0x08) {
121 lch_idx = cbits & 0x7; /* SDCCH/8 */
122 if (ts->pchan != GSM_PCHAN_SDCCH8_SACCH8C)
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100123 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte59b04682009-06-10 05:40:52 +0800124 chan_nr, ts->pchan);
125 } else if (cbits == 0x10 || cbits == 0x11 || cbits == 0x12) {
126 lch_idx = 0;
127 if (ts->pchan != GSM_PCHAN_CCCH &&
128 ts->pchan != GSM_PCHAN_CCCH_SDCCH4)
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100129 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte59b04682009-06-10 05:40:52 +0800130 chan_nr, ts->pchan);
131 /* FIXME: we should not return first sdcch4 !!! */
132 } else {
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100133 LOGP(DRSL, LOGL_ERROR, "unknown chan_nr=0x%02x\n", chan_nr);
Harald Welte59b04682009-06-10 05:40:52 +0800134 return NULL;
135 }
136
137 lchan = &ts->lchan[lch_idx];
Harald Welte51d2a592010-03-26 21:28:59 +0800138 log_set_context(BSC_CTX_LCHAN, lchan);
Holger Hans Peter Freyther1a95fa82010-06-28 15:47:12 +0800139 if (lchan->conn)
140 log_set_context(BSC_CTX_SUBSCR, lchan->conn->subscr);
Harald Welte59b04682009-06-10 05:40:52 +0800141
142 return lchan;
143}
144
Harald Welte59b04682009-06-10 05:40:52 +0800145/* As per TS 03.03 Section 2.2, the IMSI has 'not more than 15 digits' */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200146uint64_t str_to_imsi(const char *imsi_str)
Harald Welte59b04682009-06-10 05:40:52 +0800147{
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200148 uint64_t ret;
Harald Welte59b04682009-06-10 05:40:52 +0800149
150 ret = strtoull(imsi_str, NULL, 10);
151
152 return ret;
153}
154
Harald Welte59b04682009-06-10 05:40:52 +0800155static struct msgb *rsl_msgb_alloc(void)
156{
Harald Welte9cfc9352009-06-26 19:39:35 +0200157 return msgb_alloc_headroom(RSL_ALLOC_SIZE, RSL_ALLOC_HEADROOM,
158 "RSL");
Harald Welte59b04682009-06-10 05:40:52 +0800159}
160
161#define MACBLOCK_SIZE 23
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200162static void pad_macblock(uint8_t *out, const uint8_t *in, int len)
Harald Welte59b04682009-06-10 05:40:52 +0800163{
164 memcpy(out, in, len);
165
166 if (len < MACBLOCK_SIZE)
167 memset(out+len, 0x2b, MACBLOCK_SIZE-len);
168}
169
Harald Welted2dd9de2009-08-30 15:37:11 +0900170/* Chapter 9.3.7: Encryption Information */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200171static int build_encr_info(uint8_t *out, struct gsm_lchan *lchan)
Harald Welted2dd9de2009-08-30 15:37:11 +0900172{
173 *out++ = lchan->encr.alg_id & 0xff;
174 if (lchan->encr.key_len)
175 memcpy(out, lchan->encr.key, lchan->encr.key_len);
176 return lchan->encr.key_len + 1;
177}
178
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200179static void print_rsl_cause(int lvl, const uint8_t *cause_v, uint8_t cause_len)
Harald Weltef1a168d2009-07-28 17:58:09 +0200180{
Harald Welte59b04682009-06-10 05:40:52 +0800181 int i;
182
Harald Weltede4477a2009-12-24 12:20:20 +0100183 LOGPC(DRSL, lvl, "CAUSE=0x%02x(%s) ",
Harald Weltef1a168d2009-07-28 17:58:09 +0200184 cause_v[0], rsl_err_name(cause_v[0]));
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +0200185 for (i = 1; i < cause_len-1; i++)
Harald Weltede4477a2009-12-24 12:20:20 +0100186 LOGPC(DRSL, lvl, "%02x ", cause_v[i]);
Harald Welte59b04682009-06-10 05:40:52 +0800187}
188
Harald Welte32951ea2011-08-10 23:26:33 +0200189static void lchan_act_tmr_cb(void *data)
190{
191 struct gsm_lchan *lchan = data;
192
Holger Hans Peter Freytherb050e3e2012-12-06 19:00:35 +0100193 LOGP(DRSL, LOGL_ERROR, "%s Timeout during activation!\n",
Harald Welte32951ea2011-08-10 23:26:33 +0200194 gsm_lchan_name(lchan));
195
Daniel Willmann2731e732011-08-11 04:44:12 +0200196 rsl_lchan_set_state(lchan, LCHAN_S_NONE);
197 lchan_free(lchan);
Harald Welte32951ea2011-08-10 23:26:33 +0200198}
199
200static void lchan_deact_tmr_cb(void *data)
201{
202 struct gsm_lchan *lchan = data;
203
Holger Hans Peter Freytherb050e3e2012-12-06 19:00:35 +0100204 LOGP(DRSL, LOGL_ERROR, "%s Timeout during deactivation!\n",
Harald Welte32951ea2011-08-10 23:26:33 +0200205 gsm_lchan_name(lchan));
206
Holger Hans Peter Freytherc22f2992012-12-06 19:09:58 +0100207 do_lchan_free(lchan);
Harald Welte32951ea2011-08-10 23:26:33 +0200208}
209
210
Harald Welte59b04682009-06-10 05:40:52 +0800211/* Send a BCCH_INFO message as per Chapter 8.5.1 */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200212int rsl_bcch_info(struct gsm_bts_trx *trx, uint8_t type,
213 const uint8_t *data, int len)
Harald Welte59b04682009-06-10 05:40:52 +0800214{
215 struct abis_rsl_dchan_hdr *dh;
216 struct msgb *msg = rsl_msgb_alloc();
217
218 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof*dh);
219 init_dchan_hdr(dh, RSL_MT_BCCH_INFO);
220 dh->chan_nr = RSL_CHAN_BCCH;
221
222 msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
223 msgb_tlv_put(msg, RSL_IE_FULL_BCCH_INFO, len, data);
224
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200225 msg->dst = trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800226
227 return abis_rsl_sendmsg(msg);
228}
229
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200230int rsl_sacch_filling(struct gsm_bts_trx *trx, uint8_t type,
231 const uint8_t *data, int len)
Harald Welte59b04682009-06-10 05:40:52 +0800232{
233 struct abis_rsl_common_hdr *ch;
234 struct msgb *msg = rsl_msgb_alloc();
235
236 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
237 ch->msg_discr = ABIS_RSL_MDISC_TRX;
238 ch->msg_type = RSL_MT_SACCH_FILL;
239
240 msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
241 msgb_tl16v_put(msg, RSL_IE_L3_INFO, len, data);
242
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200243 msg->dst = trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800244
245 return abis_rsl_sendmsg(msg);
246}
247
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200248int rsl_sacch_info_modify(struct gsm_lchan *lchan, uint8_t type,
249 const uint8_t *data, int len)
Harald Welte10b7d8f2011-01-13 23:16:03 +0100250{
251 struct abis_rsl_dchan_hdr *dh;
252 struct msgb *msg = rsl_msgb_alloc();
Harald Weltee6d51f92011-06-25 10:02:33 +0200253 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte10b7d8f2011-01-13 23:16:03 +0100254
255 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
256 init_dchan_hdr(dh, RSL_MT_SACCH_INFO_MODIFY);
257 dh->chan_nr = chan_nr;
258
259 msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
260 msgb_tl16v_put(msg, RSL_IE_L3_INFO, len, data);
261
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200262 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte10b7d8f2011-01-13 23:16:03 +0100263
264 return abis_rsl_sendmsg(msg);
265}
266
Harald Welte91afe4c2009-06-20 18:15:19 +0200267int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db)
268{
269 struct abis_rsl_dchan_hdr *dh;
Harald Welteed831842009-06-27 03:09:08 +0200270 struct msgb *msg;
Harald Weltee6d51f92011-06-25 10:02:33 +0200271 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte91afe4c2009-06-20 18:15:19 +0200272
273 db = abs(db);
274 if (db > 30)
275 return -EINVAL;
276
Harald Welteed831842009-06-27 03:09:08 +0200277 msg = rsl_msgb_alloc();
278
Harald Welte91afe4c2009-06-20 18:15:19 +0200279 lchan->bs_power = db/2;
280 if (fpc)
281 lchan->bs_power |= 0x10;
282
283 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
284 init_dchan_hdr(dh, RSL_MT_BS_POWER_CONTROL);
285 dh->chan_nr = chan_nr;
286
287 msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power);
288
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200289 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte91afe4c2009-06-20 18:15:19 +0200290
291 return abis_rsl_sendmsg(msg);
292}
293
Harald Welte91afe4c2009-06-20 18:15:19 +0200294int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm)
295{
296 struct abis_rsl_dchan_hdr *dh;
Harald Welteed831842009-06-27 03:09:08 +0200297 struct msgb *msg;
Harald Weltee6d51f92011-06-25 10:02:33 +0200298 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte91afe4c2009-06-20 18:15:19 +0200299 int ctl_lvl;
300
Harald Weltec4dcda02009-08-09 14:45:18 +0200301 ctl_lvl = ms_pwr_ctl_lvl(lchan->ts->trx->bts->band, dbm);
Harald Welte91afe4c2009-06-20 18:15:19 +0200302 if (ctl_lvl < 0)
303 return ctl_lvl;
304
Harald Welteed831842009-06-27 03:09:08 +0200305 msg = rsl_msgb_alloc();
306
Harald Welte91afe4c2009-06-20 18:15:19 +0200307 lchan->ms_power = ctl_lvl;
308
309 if (fpc)
310 lchan->ms_power |= 0x20;
311
312 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
313 init_dchan_hdr(dh, RSL_MT_MS_POWER_CONTROL);
314 dh->chan_nr = chan_nr;
315
316 msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power);
317
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200318 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte91afe4c2009-06-20 18:15:19 +0200319
320 return abis_rsl_sendmsg(msg);
321}
322
Harald Welte39274f42009-07-29 15:41:29 +0200323static int channel_mode_from_lchan(struct rsl_ie_chan_mode *cm,
324 struct gsm_lchan *lchan)
325{
326 memset(cm, 0, sizeof(cm));
327
328 /* FIXME: what to do with data calls ? */
Holger Hans Peter Freyther21d63ff2010-09-06 09:25:48 +0800329 if (lchan->ts->trx->bts->network->dtx_enabled)
330 cm->dtx_dtu = 0x03;
331 else
332 cm->dtx_dtu = 0x00;
Harald Welte39274f42009-07-29 15:41:29 +0200333
334 /* set TCH Speech/Data */
335 cm->spd_ind = lchan->rsl_cmode;
336
Harald Welte951e3512009-11-27 08:55:16 +0100337 if (lchan->rsl_cmode == RSL_CMOD_SPD_SIGN &&
338 lchan->tch_mode != GSM48_CMODE_SIGN)
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100339 LOGP(DRSL, LOGL_ERROR, "unsupported: rsl_mode == signalling, "
Harald Welte951e3512009-11-27 08:55:16 +0100340 "but tch_mode != signalling\n");
341
Harald Welte39274f42009-07-29 15:41:29 +0200342 switch (lchan->type) {
343 case GSM_LCHAN_SDCCH:
344 cm->chan_rt = RSL_CMOD_CRT_SDCCH;
345 break;
346 case GSM_LCHAN_TCH_F:
347 cm->chan_rt = RSL_CMOD_CRT_TCH_Bm;
348 break;
349 case GSM_LCHAN_TCH_H:
350 cm->chan_rt = RSL_CMOD_CRT_TCH_Lm;
351 break;
352 case GSM_LCHAN_NONE:
353 case GSM_LCHAN_UNKNOWN:
354 default:
355 return -EINVAL;
356 }
357
358 switch (lchan->tch_mode) {
359 case GSM48_CMODE_SIGN:
360 cm->chan_rate = 0;
361 break;
362 case GSM48_CMODE_SPEECH_V1:
363 cm->chan_rate = RSL_CMOD_SP_GSM1;
364 break;
365 case GSM48_CMODE_SPEECH_EFR:
366 cm->chan_rate = RSL_CMOD_SP_GSM2;
367 break;
368 case GSM48_CMODE_SPEECH_AMR:
369 cm->chan_rate = RSL_CMOD_SP_GSM3;
370 break;
371 case GSM48_CMODE_DATA_14k5:
Harald Welte39274f42009-07-29 15:41:29 +0200372 case GSM48_CMODE_DATA_12k0:
Harald Welte39274f42009-07-29 15:41:29 +0200373 case GSM48_CMODE_DATA_6k0:
Harald Weltee75a47d2012-08-24 15:33:56 +0200374 switch (lchan->csd_mode) {
375 case LCHAN_CSD_M_NT:
376 /* non-transparent CSD with RLP */
377 switch (lchan->tch_mode) {
378 case GSM48_CMODE_DATA_14k5:
379 cm->chan_rate = RSL_CMOD_SP_NT_14k5;
380 break;
381 case GSM48_CMODE_DATA_12k0:
382 cm->chan_rate = RSL_CMOD_SP_NT_12k0;
383 break;
384 case GSM48_CMODE_DATA_6k0:
385 cm->chan_rate = RSL_CMOD_SP_NT_6k0;
386 break;
387 default:
388 return -EINVAL;
389 }
390 break;
391 /* transparent data services below */
392 case LCHAN_CSD_M_T_1200_75:
393 cm->chan_rate = RSL_CMOD_CSD_T_1200_75;
394 break;
395 case LCHAN_CSD_M_T_600:
396 cm->chan_rate = RSL_CMOD_CSD_T_600;
397 break;
398 case LCHAN_CSD_M_T_1200:
399 cm->chan_rate = RSL_CMOD_CSD_T_1200;
400 break;
401 case LCHAN_CSD_M_T_2400:
402 cm->chan_rate = RSL_CMOD_CSD_T_2400;
403 break;
404 case LCHAN_CSD_M_T_9600:
405 cm->chan_rate = RSL_CMOD_CSD_T_9600;
406 break;
407 case LCHAN_CSD_M_T_14400:
408 cm->chan_rate = RSL_CMOD_CSD_T_14400;
409 break;
410 case LCHAN_CSD_M_T_29000:
411 cm->chan_rate = RSL_CMOD_CSD_T_29000;
412 break;
413 case LCHAN_CSD_M_T_32000:
414 cm->chan_rate = RSL_CMOD_CSD_T_32000;
415 break;
416 default:
417 return -EINVAL;
418 }
Harald Welte39274f42009-07-29 15:41:29 +0200419 default:
420 return -EINVAL;
421 }
422
423 return 0;
424}
425
Harald Welte59b04682009-06-10 05:40:52 +0800426/* Chapter 8.4.1 */
427#if 0
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200428int rsl_chan_activate(struct gsm_bts_trx *trx, uint8_t chan_nr,
429 uint8_t act_type,
Harald Welte59b04682009-06-10 05:40:52 +0800430 struct rsl_ie_chan_mode *chan_mode,
431 struct rsl_ie_chan_ident *chan_ident,
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200432 uint8_t bs_power, uint8_t ms_power,
433 uint8_t ta)
Harald Welte59b04682009-06-10 05:40:52 +0800434{
435 struct abis_rsl_dchan_hdr *dh;
436 struct msgb *msg = rsl_msgb_alloc();
437
438 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
439 init_dchan_hdr(dh, RSL_MT_CHAN_ACTIV);
440 dh->chan_nr = chan_nr;
441
442 msgb_tv_put(msg, RSL_IE_ACT_TYPE, act_type);
443 /* For compatibility with Phase 1 */
444 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(*chan_mode),
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200445 (uint8_t *) chan_mode);
Harald Welte59b04682009-06-10 05:40:52 +0800446 msgb_tlv_put(msg, RSL_IE_CHAN_IDENT, 4,
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200447 (uint8_t *) chan_ident);
Harald Welte59b04682009-06-10 05:40:52 +0800448#if 0
449 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, 1,
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200450 (uint8_t *) &encr_info);
Harald Welte59b04682009-06-10 05:40:52 +0800451#endif
452 msgb_tv_put(msg, RSL_IE_BS_POWER, bs_power);
453 msgb_tv_put(msg, RSL_IE_MS_POWER, ms_power);
454 msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta);
455
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200456 msg->dst = trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800457
458 return abis_rsl_sendmsg(msg);
459}
460#endif
461
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200462int rsl_chan_activate_lchan(struct gsm_lchan *lchan, uint8_t act_type,
463 uint8_t ta, uint8_t ho_ref)
Harald Welte59b04682009-06-10 05:40:52 +0800464{
465 struct abis_rsl_dchan_hdr *dh;
Harald Welteed831842009-06-27 03:09:08 +0200466 struct msgb *msg;
Harald Welte39274f42009-07-29 15:41:29 +0200467 int rc;
Harald Weltedea24e92010-06-29 17:53:45 +0200468 uint8_t *len;
Harald Welte59b04682009-06-10 05:40:52 +0800469
Harald Weltee6d51f92011-06-25 10:02:33 +0200470 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte59b04682009-06-10 05:40:52 +0800471 struct rsl_ie_chan_mode cm;
laforgef723cf02010-06-20 21:38:19 +0200472 struct gsm48_chan_desc cd;
Harald Welte59b04682009-06-10 05:40:52 +0800473
Harald Welte39274f42009-07-29 15:41:29 +0200474 rc = channel_mode_from_lchan(&cm, lchan);
475 if (rc < 0)
476 return rc;
Harald Welte59b04682009-06-10 05:40:52 +0800477
Holger Hans Peter Freyther11b01402010-06-30 11:56:43 +0800478 memset(&cd, 0, sizeof(cd));
laforgef723cf02010-06-20 21:38:19 +0200479 gsm48_lchan2chan_desc(&cd, lchan);
Harald Welte59b04682009-06-10 05:40:52 +0800480
Harald Welteed831842009-06-27 03:09:08 +0200481 msg = rsl_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800482 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
483 init_dchan_hdr(dh, RSL_MT_CHAN_ACTIV);
484 dh->chan_nr = chan_nr;
485
486 msgb_tv_put(msg, RSL_IE_ACT_TYPE, act_type);
Harald Welte59b04682009-06-10 05:40:52 +0800487 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200488 (uint8_t *) &cm);
Holger Hans Peter Freyther11b01402010-06-30 11:56:43 +0800489
490 /*
491 * The Channel Identification is needed for Phase1 phones
492 * and it contains the GSM48 Channel Description and the
493 * Mobile Allocation. The GSM 08.58 asks for the Mobile
494 * Allocation to have a length of zero. We are using the
495 * msgb_l3len to calculate the length of both messages.
496 */
laforgef723cf02010-06-20 21:38:19 +0200497 msgb_v_put(msg, RSL_IE_CHAN_IDENT);
Harald Weltedea24e92010-06-29 17:53:45 +0200498 len = msgb_put(msg, 1);
Dieter Spaar18a55f62011-07-27 23:40:33 +0200499 msgb_tv_fixed_put(msg, GSM48_IE_CHANDESC_2, sizeof(cd), (const uint8_t *) &cd);
Holger Hans Peter Freyther4cab4422010-06-30 12:06:20 +0800500
501 if (lchan->ts->hopping.enabled)
502 msgb_tlv_put(msg, GSM48_IE_MA_AFTER, lchan->ts->hopping.ma_len,
503 lchan->ts->hopping.ma_data);
504 else
505 msgb_tlv_put(msg, GSM48_IE_MA_AFTER, 0, NULL);
Holger Hans Peter Freyther11b01402010-06-30 11:56:43 +0800506
507 /* update the calculated size */
508 msg->l3h = len + 1;
509 *len = msgb_l3len(msg);
510
Harald Welted2dd9de2009-08-30 15:37:11 +0900511 if (lchan->encr.alg_id > RSL_ENC_ALG_A5(0)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200512 uint8_t encr_info[MAX_A5_KEY_LEN+2];
Harald Welted2dd9de2009-08-30 15:37:11 +0900513 rc = build_encr_info(encr_info, lchan);
514 if (rc > 0)
515 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, rc, encr_info);
516 }
517
Harald Welteb90d7bd2009-12-17 00:31:10 +0100518 switch (act_type) {
519 case RSL_ACT_INTER_ASYNC:
520 case RSL_ACT_INTER_SYNC:
521 msgb_tv_put(msg, RSL_IE_HANDO_REF, ho_ref);
522 break;
523 default:
524 break;
525 }
526
Harald Welte59b04682009-06-10 05:40:52 +0800527 msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power);
528 msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power);
529 msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta);
530
Holger Hans Peter Freyther6fe8ab92010-01-28 04:45:05 +0100531 if (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR)
532 msgb_tlv_put(msg, RSL_IE_MR_CONFIG, sizeof(lchan->mr_conf),
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200533 (uint8_t *) &lchan->mr_conf);
Holger Hans Peter Freyther6fe8ab92010-01-28 04:45:05 +0100534
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200535 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800536
537 return abis_rsl_sendmsg(msg);
538}
539
Harald Welte8e770492009-07-29 11:38:15 +0200540/* Chapter 8.4.9: Modify channel mode on BTS side */
Harald Welte59b04682009-06-10 05:40:52 +0800541int rsl_chan_mode_modify_req(struct gsm_lchan *lchan)
542{
543 struct abis_rsl_dchan_hdr *dh;
Harald Welteed831842009-06-27 03:09:08 +0200544 struct msgb *msg;
Harald Welte39274f42009-07-29 15:41:29 +0200545 int rc;
Harald Welte59b04682009-06-10 05:40:52 +0800546
Harald Weltee6d51f92011-06-25 10:02:33 +0200547 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte59b04682009-06-10 05:40:52 +0800548 struct rsl_ie_chan_mode cm;
549
Harald Welte39274f42009-07-29 15:41:29 +0200550 rc = channel_mode_from_lchan(&cm, lchan);
551 if (rc < 0)
552 return rc;
Harald Welte59b04682009-06-10 05:40:52 +0800553
Harald Welteed831842009-06-27 03:09:08 +0200554 msg = rsl_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800555 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
556 init_dchan_hdr(dh, RSL_MT_MODE_MODIFY_REQ);
557 dh->chan_nr = chan_nr;
558
559 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200560 (uint8_t *) &cm);
Harald Welted2dd9de2009-08-30 15:37:11 +0900561
562 if (lchan->encr.alg_id > RSL_ENC_ALG_A5(0)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200563 uint8_t encr_info[MAX_A5_KEY_LEN+2];
Harald Welted2dd9de2009-08-30 15:37:11 +0900564 rc = build_encr_info(encr_info, lchan);
565 if (rc > 0)
566 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, rc, encr_info);
567 }
568
Holger Hans Peter Freyther3cce58f2009-11-18 22:57:02 +0100569 if (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR) {
570 msgb_tlv_put(msg, RSL_IE_MR_CONFIG, sizeof(lchan->mr_conf),
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200571 (uint8_t *) &lchan->mr_conf);
Holger Hans Peter Freyther3cce58f2009-11-18 22:57:02 +0100572 }
573
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200574 msg->dst = lchan->ts->trx->rsl_link;
Harald Welted2dd9de2009-08-30 15:37:11 +0900575
576 return abis_rsl_sendmsg(msg);
577}
578
579/* Chapter 8.4.6: Send the encryption command with given L3 info */
580int rsl_encryption_cmd(struct msgb *msg)
581{
582 struct abis_rsl_dchan_hdr *dh;
583 struct gsm_lchan *lchan = msg->lchan;
Harald Weltee6d51f92011-06-25 10:02:33 +0200584 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200585 uint8_t encr_info[MAX_A5_KEY_LEN+2];
586 uint8_t l3_len = msg->len;
Harald Welted2dd9de2009-08-30 15:37:11 +0900587 int rc;
588
589 /* First push the L3 IE tag and length */
590 msgb_tv16_push(msg, RSL_IE_L3_INFO, l3_len);
591
592 /* then the link identifier (SAPI0, main sign link) */
593 msgb_tv_push(msg, RSL_IE_LINK_IDENT, 0);
594
595 /* then encryption information */
596 rc = build_encr_info(encr_info, lchan);
597 if (rc <= 0)
598 return rc;
599 msgb_tlv_push(msg, RSL_IE_ENCR_INFO, rc, encr_info);
600
601 /* and finally the DCHAN header */
602 dh = (struct abis_rsl_dchan_hdr *) msgb_push(msg, sizeof(*dh));
603 init_dchan_hdr(dh, RSL_MT_ENCR_CMD);
604 dh->chan_nr = chan_nr;
Harald Welte59b04682009-06-10 05:40:52 +0800605
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200606 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800607
608 return abis_rsl_sendmsg(msg);
609}
610
Harald Welte85a163c2009-08-10 11:43:22 +0200611/* Chapter 8.4.5 / 4.6: Deactivate the SACCH after 04.08 RR CHAN RELEASE */
Harald Welteafe3c232009-07-19 18:36:49 +0200612int rsl_deact_sacch(struct gsm_lchan *lchan)
613{
614 struct abis_rsl_dchan_hdr *dh;
615 struct msgb *msg = rsl_msgb_alloc();
616
617 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
618 init_dchan_hdr(dh, RSL_MT_DEACTIVATE_SACCH);
Harald Weltee6d51f92011-06-25 10:02:33 +0200619 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welteafe3c232009-07-19 18:36:49 +0200620
621 msg->lchan = lchan;
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200622 msg->dst = lchan->ts->trx->rsl_link;
Harald Welteafe3c232009-07-19 18:36:49 +0200623
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +0100624 DEBUGP(DRSL, "%s DEACTivate SACCH CMD\n", gsm_lchan_name(lchan));
Harald Welteafe3c232009-07-19 18:36:49 +0200625
626 return abis_rsl_sendmsg(msg);
627}
628
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800629static void error_timeout_cb(void *data)
630{
631 struct gsm_lchan *lchan = data;
632 if (lchan->state != LCHAN_S_REL_ERR) {
633 LOGP(DRSL, LOGL_ERROR, "%s error timeout but not in error state: %d\n",
634 gsm_lchan_name(lchan), lchan->state);
635 return;
636 }
637
638 /* go back to the none state */
639 LOGP(DRSL, LOGL_NOTICE, "%s is back in operation.\n", gsm_lchan_name(lchan));
Holger Hans Peter Freyther456fb9d2010-06-08 11:53:33 +0800640 rsl_lchan_set_state(lchan, LCHAN_S_NONE);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800641}
642
Harald Welte08011e22011-03-04 13:41:31 +0100643static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan);
644
Harald Welte85a163c2009-08-10 11:43:22 +0200645/* Chapter 8.4.14 / 4.7: Tell BTS to release the radio channel */
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800646static int rsl_rf_chan_release(struct gsm_lchan *lchan, int error)
Harald Welte59b04682009-06-10 05:40:52 +0800647{
648 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800649 struct msgb *msg;
Harald Welte08011e22011-03-04 13:41:31 +0100650 int rc;
Harald Welte59b04682009-06-10 05:40:52 +0800651
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800652 if (lchan->state == LCHAN_S_REL_ERR) {
653 LOGP(DRSL, LOGL_NOTICE, "%s is in error state not sending release.\n",
654 gsm_lchan_name(lchan));
655 return -1;
656 }
657
658 msg = rsl_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800659 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
660 init_dchan_hdr(dh, RSL_MT_RF_CHAN_REL);
Harald Weltee6d51f92011-06-25 10:02:33 +0200661 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte59b04682009-06-10 05:40:52 +0800662
663 msg->lchan = lchan;
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200664 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800665
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800666 DEBUGP(DRSL, "%s RF Channel Release CMD due error %d\n", gsm_lchan_name(lchan), error);
667
668 if (error) {
669 /*
670 * the nanoBTS sends RLL release indications after the channel release. This can
671 * be a problem when we have reassigned the channel to someone else and then can
672 * not figure out who used this channel.
673 */
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200674 struct e1inp_sign_link *sign_link = msg->dst;
675
Holger Hans Peter Freyther456fb9d2010-06-08 11:53:33 +0800676 rsl_lchan_set_state(lchan, LCHAN_S_REL_ERR);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800677 lchan->error_timer.data = lchan;
678 lchan->error_timer.cb = error_timeout_cb;
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +0200679 osmo_timer_schedule(&lchan->error_timer,
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200680 sign_link->trx->bts->network->T3111 + 2, 0);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800681 }
Harald Welte59b04682009-06-10 05:40:52 +0800682
Harald Welte32951ea2011-08-10 23:26:33 +0200683 /* Start another timer or assume the BTS sends a ACK/NACK? */
684 lchan->act_timer.cb = lchan_deact_tmr_cb;
685 lchan->act_timer.data = lchan;
686 osmo_timer_schedule(&lchan->act_timer, 4, 0);
687
Harald Welte08011e22011-03-04 13:41:31 +0100688 rc = abis_rsl_sendmsg(msg);
689
Harald Welte85a163c2009-08-10 11:43:22 +0200690 /* BTS will respond by RF CHAN REL ACK */
Harald Welte6bddd822011-01-14 23:18:59 +0100691#ifdef HSL_SR_1_0
Harald Welte08011e22011-03-04 13:41:31 +0100692 /* The HSL Femto seems to 'forget' sending a REL ACK for TS1...TS7 */
693 if (lchan->ts->trx->bts->type == GSM_BTS_TYPE_HSL_FEMTO && lchan->ts->nr != 0)
694 rc = rsl_rx_rf_chan_rel_ack(lchan);
Harald Welte6bddd822011-01-14 23:18:59 +0100695#endif
Harald Welte08011e22011-03-04 13:41:31 +0100696
697 return rc;
Harald Welte59b04682009-06-10 05:40:52 +0800698}
699
Harald Welte9773f6c2011-01-14 14:16:16 +0100700static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan)
701{
702
703 DEBUGP(DRSL, "%s RF CHANNEL RELEASE ACK\n", gsm_lchan_name(lchan));
704
Holger Hans Peter Freytherc22f2992012-12-06 19:09:58 +0100705 /* Stop all pending timers */
Harald Welte32951ea2011-08-10 23:26:33 +0200706 osmo_timer_del(&lchan->act_timer);
Holger Hans Peter Freytherc22f2992012-12-06 19:09:58 +0100707 osmo_timer_del(&lchan->T3111);
Harald Welte32951ea2011-08-10 23:26:33 +0200708
Harald Welte9773f6c2011-01-14 14:16:16 +0100709 if (lchan->state != LCHAN_S_REL_REQ && lchan->state != LCHAN_S_REL_ERR)
710 LOGP(DRSL, LOGL_NOTICE, "%s CHAN REL ACK but state %s\n",
711 gsm_lchan_name(lchan),
712 gsm_lchans_name(lchan->state));
Holger Hans Peter Freytherc22f2992012-12-06 19:09:58 +0100713 do_lchan_free(lchan);
Harald Welte9773f6c2011-01-14 14:16:16 +0100714
715 return 0;
716}
717
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200718int rsl_paging_cmd(struct gsm_bts *bts, uint8_t paging_group, uint8_t len,
719 uint8_t *ms_ident, uint8_t chan_needed)
Harald Welte59b04682009-06-10 05:40:52 +0800720{
721 struct abis_rsl_dchan_hdr *dh;
722 struct msgb *msg = rsl_msgb_alloc();
723
724 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
725 init_dchan_hdr(dh, RSL_MT_PAGING_CMD);
726 dh->chan_nr = RSL_CHAN_PCH_AGCH;
727
728 msgb_tv_put(msg, RSL_IE_PAGING_GROUP, paging_group);
729 msgb_tlv_put(msg, RSL_IE_MS_IDENTITY, len-2, ms_ident+2);
730 msgb_tv_put(msg, RSL_IE_CHAN_NEEDED, chan_needed);
731
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200732 msg->dst = bts->c0->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800733
734 return abis_rsl_sendmsg(msg);
735}
736
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200737int imsi_str2bcd(uint8_t *bcd_out, const char *str_in)
Harald Welte59b04682009-06-10 05:40:52 +0800738{
739 int i, len = strlen(str_in);
740
741 for (i = 0; i < len; i++) {
742 int num = str_in[i] - 0x30;
743 if (num < 0 || num > 9)
744 return -1;
745 if (i % 2 == 0)
746 bcd_out[i/2] = num;
747 else
748 bcd_out[i/2] |= (num << 4);
749 }
750
751 return 0;
752}
753
754/* Chapter 8.5.6 */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200755int rsl_imm_assign_cmd(struct gsm_bts *bts, uint8_t len, uint8_t *val)
Harald Welte59b04682009-06-10 05:40:52 +0800756{
757 struct msgb *msg = rsl_msgb_alloc();
758 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200759 uint8_t buf[MACBLOCK_SIZE];
Harald Welte59b04682009-06-10 05:40:52 +0800760
761 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
762 init_dchan_hdr(dh, RSL_MT_IMMEDIATE_ASSIGN_CMD);
763 dh->chan_nr = RSL_CHAN_PCH_AGCH;
764
765 switch (bts->type) {
766 case GSM_BTS_TYPE_BS11:
767 msgb_tlv_put(msg, RSL_IE_IMM_ASS_INFO, len, val);
768 break;
769 default:
770 /* If phase 2, construct a FULL_IMM_ASS_INFO */
771 pad_macblock(buf, val, len);
772 msgb_tlv_put(msg, RSL_IE_FULL_IMM_ASS_INFO, MACBLOCK_SIZE, buf);
773 break;
774 }
775
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200776 msg->dst = bts->c0->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800777
778 return abis_rsl_sendmsg(msg);
779}
780
Harald Welte4684e632009-08-10 09:51:40 +0200781/* Send Siemens specific MS RF Power Capability Indication */
Harald Welte12090752009-08-10 10:07:33 +0200782int rsl_siemens_mrpci(struct gsm_lchan *lchan, struct rsl_mrpci *mrpci)
Harald Welte4684e632009-08-10 09:51:40 +0200783{
784 struct msgb *msg = rsl_msgb_alloc();
785 struct abis_rsl_dchan_hdr *dh;
786
787 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
788 init_dchan_hdr(dh, RSL_MT_SIEMENS_MRPCI);
Harald Welte874a5b42009-08-10 11:26:14 +0200789 dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
Harald Weltee6d51f92011-06-25 10:02:33 +0200790 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200791 msgb_tv_put(msg, RSL_IE_SIEMENS_MRPCI, *(uint8_t *)mrpci);
Harald Welte4684e632009-08-10 09:51:40 +0200792
Harald Weltede4477a2009-12-24 12:20:20 +0100793 DEBUGP(DRSL, "%s TX Siemens MRPCI 0x%02x\n",
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200794 gsm_lchan_name(lchan), *(uint8_t *)mrpci);
Harald Welte874a5b42009-08-10 11:26:14 +0200795
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200796 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte874a5b42009-08-10 11:26:14 +0200797
Harald Welte4684e632009-08-10 09:51:40 +0200798 return abis_rsl_sendmsg(msg);
799}
800
801
Harald Welte59b04682009-06-10 05:40:52 +0800802/* Send "DATA REQUEST" message with given L3 Info payload */
803/* Chapter 8.3.1 */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200804int rsl_data_request(struct msgb *msg, uint8_t link_id)
Harald Welte59b04682009-06-10 05:40:52 +0800805{
Harald Welte59b04682009-06-10 05:40:52 +0800806 if (msg->lchan == NULL) {
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100807 LOGP(DRSL, LOGL_ERROR, "cannot send DATA REQUEST to unknown lchan\n");
Harald Welte59b04682009-06-10 05:40:52 +0800808 return -EINVAL;
809 }
810
Harald Weltee6d51f92011-06-25 10:02:33 +0200811 rsl_rll_push_l3(msg, RSL_MT_DATA_REQ, gsm_lchan2chan_nr(msg->lchan),
Harald Weltea22d36b2010-03-04 10:33:10 +0100812 link_id, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800813
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200814 msg->dst = msg->lchan->ts->trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800815
816 return abis_rsl_sendmsg(msg);
817}
818
Harald Welteed9a5ab2009-08-09 13:47:35 +0200819/* Send "ESTABLISH REQUEST" message with given L3 Info payload */
820/* Chapter 8.3.1 */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200821int rsl_establish_request(struct gsm_lchan *lchan, uint8_t link_id)
Harald Welteed9a5ab2009-08-09 13:47:35 +0200822{
Harald Weltea22d36b2010-03-04 10:33:10 +0100823 struct msgb *msg;
Harald Welteed9a5ab2009-08-09 13:47:35 +0200824
Harald Weltee6d51f92011-06-25 10:02:33 +0200825 msg = rsl_rll_simple(RSL_MT_EST_REQ, gsm_lchan2chan_nr(lchan),
Harald Weltea22d36b2010-03-04 10:33:10 +0100826 link_id, 0);
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200827 msg->dst = lchan->ts->trx->rsl_link;
Harald Welteed9a5ab2009-08-09 13:47:35 +0200828
Harald Welte17091bd2012-04-26 19:42:19 +0200829 DEBUGP(DRLL, "%s RSL RLL ESTABLISH REQ (link_id=0x%02x)\n",
830 gsm_lchan_name(lchan), link_id);
831
Harald Welteed9a5ab2009-08-09 13:47:35 +0200832 return abis_rsl_sendmsg(msg);
833}
834
Harald Welte0f2e3c12009-08-08 13:15:07 +0200835/* Chapter 8.3.7 Request the release of multiframe mode of RLL connection.
836 This is what higher layers should call. The BTS then responds with
837 RELEASE CONFIRM, which we in turn use to trigger RSL CHANNEL RELEASE,
838 which in turn is acknowledged by RSL CHANNEL RELEASE ACK, which calls
839 lchan_free() */
Holger Hans Peter Freyther2806c792012-12-06 12:01:38 +0100840int rsl_release_request(struct gsm_lchan *lchan, uint8_t link_id,
841 enum rsl_rel_mode release_mode)
Harald Welte0f2e3c12009-08-08 13:15:07 +0200842{
Harald Welte0f2e3c12009-08-08 13:15:07 +0200843
Harald Weltea22d36b2010-03-04 10:33:10 +0100844 struct msgb *msg;
845
Harald Weltee6d51f92011-06-25 10:02:33 +0200846 msg = rsl_rll_simple(RSL_MT_REL_REQ, gsm_lchan2chan_nr(lchan),
Harald Weltea22d36b2010-03-04 10:33:10 +0100847 link_id, 0);
Holger Hans Peter Freytherbcea9a72010-06-08 11:57:45 +0800848 /* 0 is normal release, 1 is local end */
Holger Hans Peter Freyther2806c792012-12-06 12:01:38 +0100849 msgb_tv_put(msg, RSL_IE_RELEASE_MODE, release_mode);
Harald Welte0f2e3c12009-08-08 13:15:07 +0200850
Harald Weltec88a4432009-12-29 10:44:17 +0100851 /* FIXME: start some timer in case we don't receive a REL ACK ? */
852
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200853 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte0f2e3c12009-08-08 13:15:07 +0200854
Harald Welte17091bd2012-04-26 19:42:19 +0200855 DEBUGP(DRLL, "%s RSL RLL RELEASE REQ (link_id=0x%02x, reason=%u)\n",
Holger Hans Peter Freyther2806c792012-12-06 12:01:38 +0100856 gsm_lchan_name(lchan), link_id, release_mode);
Harald Welte17091bd2012-04-26 19:42:19 +0200857
Harald Welte0f2e3c12009-08-08 13:15:07 +0200858 return abis_rsl_sendmsg(msg);
859}
860
Holger Hans Peter Freyther68914a02010-04-10 00:12:31 +0200861int rsl_lchan_set_state(struct gsm_lchan *lchan, int state)
862{
863 lchan->state = state;
864 return 0;
865}
866
Harald Welte59b04682009-06-10 05:40:52 +0800867/* Chapter 8.4.2: Channel Activate Acknowledge */
868static int rsl_rx_chan_act_ack(struct msgb *msg)
869{
870 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
871
872 /* BTS has confirmed channel activation, we now need
873 * to assign the activated channel to the MS */
874 if (rslh->ie_chan != RSL_IE_CHAN_NR)
875 return -EINVAL;
Harald Welte6720a432009-11-29 22:45:52 +0100876
Harald Welte32951ea2011-08-10 23:26:33 +0200877 osmo_timer_del(&msg->lchan->act_timer);
878
Harald Weltec88a4432009-12-29 10:44:17 +0100879 if (msg->lchan->state != LCHAN_S_ACT_REQ)
Harald Welteab2534c2009-12-29 10:52:38 +0100880 LOGP(DRSL, LOGL_NOTICE, "%s CHAN ACT ACK, but state %s\n",
881 gsm_lchan_name(msg->lchan),
882 gsm_lchans_name(msg->lchan->state));
Holger Hans Peter Freyther68914a02010-04-10 00:12:31 +0200883 rsl_lchan_set_state(msg->lchan, LCHAN_S_ACTIVE);
Harald Welte4baa9c52009-12-21 13:27:11 +0100884
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +0800885 if (msg->lchan->rqd_ref) {
886 rsl_send_imm_assignment(msg->lchan);
887 talloc_free(msg->lchan->rqd_ref);
888 msg->lchan->rqd_ref = NULL;
889 msg->lchan->rqd_ta = 0;
890 }
891
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +0100892 send_lchan_signal(S_LCHAN_ACTIVATE_ACK, msg->lchan, NULL);
Harald Welte6720a432009-11-29 22:45:52 +0100893
Harald Welte59b04682009-06-10 05:40:52 +0800894 return 0;
895}
896
897/* Chapter 8.4.3: Channel Activate NACK */
898static int rsl_rx_chan_act_nack(struct msgb *msg)
899{
900 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
901 struct tlv_parsed tp;
902
Harald Welte32951ea2011-08-10 23:26:33 +0200903 osmo_timer_del(&msg->lchan->act_timer);
904
Daniel Willmann9e9d44c2011-08-11 04:54:23 +0200905 LOGP(DRSL, LOGL_ERROR, "%s CHANNEL ACTIVATE NACK ",
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +0100906 gsm_lchan_name(msg->lchan));
Harald Welte (local)ed6d7622009-12-27 11:48:11 +0100907
Harald Welte59b04682009-06-10 05:40:52 +0800908 /* BTS has rejected channel activation ?!? */
909 if (dh->ie_chan != RSL_IE_CHAN_NR)
910 return -EINVAL;
911
912 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
Harald Welte (local)c3be50c2009-12-27 18:12:29 +0100913 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200914 const uint8_t *cause = TLVP_VAL(&tp, RSL_IE_CAUSE);
Harald Welte (local)c3be50c2009-12-27 18:12:29 +0100915 print_rsl_cause(LOGL_ERROR, cause,
Harald Weltef1a168d2009-07-28 17:58:09 +0200916 TLVP_LEN(&tp, RSL_IE_CAUSE));
Harald Welte (local)c3be50c2009-12-27 18:12:29 +0100917 if (*cause != RSL_ERR_RCH_ALR_ACTV_ALLOC)
Holger Hans Peter Freyther68914a02010-04-10 00:12:31 +0200918 rsl_lchan_set_state(msg->lchan, LCHAN_S_NONE);
Daniel Willmann245ee032011-08-11 04:47:11 +0200919 else
920 rsl_rf_chan_release(msg->lchan, 1);
921
Harald Welte (local)c3be50c2009-12-27 18:12:29 +0100922 } else
Holger Hans Peter Freyther68914a02010-04-10 00:12:31 +0200923 rsl_lchan_set_state(msg->lchan, LCHAN_S_NONE);
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +0200924
Harald Welte (local)ed6d7622009-12-27 11:48:11 +0100925 LOGPC(DRSL, LOGL_ERROR, "\n");
926
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +0100927 send_lchan_signal(S_LCHAN_ACTIVATE_NACK, msg->lchan, NULL);
Harald Welte6720a432009-11-29 22:45:52 +0100928
Harald Weltecddb9802009-08-09 19:50:08 +0200929 lchan_free(msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +0800930 return 0;
931}
932
933/* Chapter 8.4.4: Connection Failure Indication */
934static int rsl_rx_conn_fail(struct msgb *msg)
935{
936 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
937 struct tlv_parsed tp;
938
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100939 /* FIXME: print which channel */
Harald Welte (local)4bd76642009-12-26 22:33:09 +0100940 LOGP(DRSL, LOGL_NOTICE, "%s CONNECTION FAIL: RELEASING ",
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +0100941 gsm_lchan_name(msg->lchan));
Harald Welte59b04682009-06-10 05:40:52 +0800942
943 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
944
Harald Weltef1a168d2009-07-28 17:58:09 +0200945 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
Harald Weltede4477a2009-12-24 12:20:20 +0100946 print_rsl_cause(LOGL_NOTICE, TLVP_VAL(&tp, RSL_IE_CAUSE),
Harald Weltef1a168d2009-07-28 17:58:09 +0200947 TLVP_LEN(&tp, RSL_IE_CAUSE));
948
Harald Welte (local)4bd76642009-12-26 22:33:09 +0100949 LOGPC(DRSL, LOGL_NOTICE, "\n");
Harald Welte59b04682009-06-10 05:40:52 +0800950 /* FIXME: only free it after channel release ACK */
Pablo Neira Ayuso1c450742011-05-06 12:13:10 +0200951 osmo_counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rf_fail);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800952 return rsl_rf_chan_release(msg->lchan, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800953}
954
Harald Weltec20bd1d2009-11-29 19:07:28 +0100955static void print_meas_rep_uni(struct gsm_meas_rep_unidir *mru,
956 const char *prefix)
957{
Harald Welte0e4fa782009-12-16 16:52:07 +0100958 DEBUGPC(DMEAS, "RXL-FULL-%s=%3ddBm RXL-SUB-%s=%3ddBm ",
959 prefix, rxlev2dbm(mru->full.rx_lev),
960 prefix, rxlev2dbm(mru->sub.rx_lev));
Harald Weltec20bd1d2009-11-29 19:07:28 +0100961 DEBUGPC(DMEAS, "RXQ-FULL-%s=%d RXQ-SUB-%s=%d ",
962 prefix, mru->full.rx_qual, prefix, mru->sub.rx_qual);
963}
964
Harald Welte50290cc2012-07-02 17:12:08 +0200965static void print_meas_rep(struct gsm_lchan *lchan, struct gsm_meas_rep *mr)
Harald Weltec20bd1d2009-11-29 19:07:28 +0100966{
Harald Welte0e4fa782009-12-16 16:52:07 +0100967 int i;
Harald Welte50290cc2012-07-02 17:12:08 +0200968 char *name = "";
Harald Welte0e4fa782009-12-16 16:52:07 +0100969
Harald Welte50290cc2012-07-02 17:12:08 +0200970 if (lchan && lchan->conn && lchan->conn->subscr)
971 name = subscr_name(lchan->conn->subscr);
972
973 DEBUGP(DMEAS, "[%s] MEASUREMENT RESULT NR=%d ", name, mr->nr);
Harald Weltec20bd1d2009-11-29 19:07:28 +0100974
975 if (mr->flags & MEAS_REP_F_DL_DTX)
976 DEBUGPC(DMEAS, "DTXd ");
977
978 print_meas_rep_uni(&mr->ul, "ul");
979 DEBUGPC(DMEAS, "BS_POWER=%d ", mr->bs_power);
980 if (mr->flags & MEAS_REP_F_MS_TO)
981 DEBUGPC(DMEAS, "MS_TO=%d ", mr->ms_timing_offset);
982
983 if (mr->flags & MEAS_REP_F_MS_L1) {
Harald Welte0e4fa782009-12-16 16:52:07 +0100984 DEBUGPC(DMEAS, "L1_MS_PWR=%3ddBm ", mr->ms_l1.pwr);
Harald Weltec20bd1d2009-11-29 19:07:28 +0100985 DEBUGPC(DMEAS, "L1_FPC=%u ",
986 mr->flags & MEAS_REP_F_FPC ? 1 : 0);
987 DEBUGPC(DMEAS, "L1_TA=%u ", mr->ms_l1.ta);
988 }
989
990 if (mr->flags & MEAS_REP_F_UL_DTX)
991 DEBUGPC(DMEAS, "DTXu ");
992 if (mr->flags & MEAS_REP_F_BA1)
993 DEBUGPC(DMEAS, "BA1 ");
994 if (!(mr->flags & MEAS_REP_F_DL_VALID))
995 DEBUGPC(DMEAS, "NOT VALID ");
996 else
997 print_meas_rep_uni(&mr->dl, "dl");
998
999 DEBUGPC(DMEAS, "NUM_NEIGH=%u\n", mr->num_cell);
Harald Welte0b833f82009-12-19 18:33:05 +01001000 if (mr->num_cell == 7)
1001 return;
Harald Welte0e4fa782009-12-16 16:52:07 +01001002 for (i = 0; i < mr->num_cell; i++) {
1003 struct gsm_meas_rep_cell *mrc = &mr->cell[i];
Harald Welte350c2d32009-12-25 23:02:22 +01001004 DEBUGP(DMEAS, "IDX=%u ARFCN=%u BSIC=%u => %d dBm\n",
1005 mrc->neigh_idx, mrc->arfcn, mrc->bsic, rxlev2dbm(mrc->rxlev));
Harald Welte0e4fa782009-12-16 16:52:07 +01001006 }
Harald Weltec20bd1d2009-11-29 19:07:28 +01001007}
1008
Harald Welte59b04682009-06-10 05:40:52 +08001009static int rsl_rx_meas_res(struct msgb *msg)
1010{
1011 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1012 struct tlv_parsed tp;
Harald Weltef9476812009-12-15 21:36:05 +01001013 struct gsm_meas_rep *mr = lchan_next_meas_rep(msg->lchan);
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001014 uint8_t len;
1015 const uint8_t *val;
Harald Weltec20bd1d2009-11-29 19:07:28 +01001016 int rc;
Harald Welte59b04682009-06-10 05:40:52 +08001017
Harald Welte4baa9c52009-12-21 13:27:11 +01001018 /* check if this channel is actually active */
1019 /* FIXME: maybe this check should be way more generic/centralized */
Harald Weltec88a4432009-12-29 10:44:17 +01001020 if (msg->lchan->state != LCHAN_S_ACTIVE) {
Holger Hans Peter Freyther67a2e292010-07-29 14:50:57 +08001021 LOGP(DRSL, LOGL_DEBUG, "%s: MEAS RES for inactive channel\n",
Harald Weltec88a4432009-12-29 10:44:17 +01001022 gsm_lchan_name(msg->lchan));
Harald Welte4baa9c52009-12-21 13:27:11 +01001023 return 0;
Harald Weltec88a4432009-12-29 10:44:17 +01001024 }
Harald Welte4baa9c52009-12-21 13:27:11 +01001025
Harald Weltef9476812009-12-15 21:36:05 +01001026 memset(mr, 0, sizeof(*mr));
Harald Welteaa0efa12009-12-16 23:29:34 +01001027 mr->lchan = msg->lchan;
Harald Welte4efcc542009-11-30 19:16:47 +01001028
Harald Welte59b04682009-06-10 05:40:52 +08001029 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
1030
Harald Weltec20bd1d2009-11-29 19:07:28 +01001031 if (!TLVP_PRESENT(&tp, RSL_IE_MEAS_RES_NR) ||
1032 !TLVP_PRESENT(&tp, RSL_IE_UPLINK_MEAS) ||
1033 !TLVP_PRESENT(&tp, RSL_IE_BS_POWER))
1034 return -EIO;
1035
1036 /* Mandatory Parts */
Harald Weltef9476812009-12-15 21:36:05 +01001037 mr->nr = *TLVP_VAL(&tp, RSL_IE_MEAS_RES_NR);
Harald Weltec20bd1d2009-11-29 19:07:28 +01001038
1039 len = TLVP_LEN(&tp, RSL_IE_UPLINK_MEAS);
1040 val = TLVP_VAL(&tp, RSL_IE_UPLINK_MEAS);
1041 if (len >= 3) {
1042 if (val[0] & 0x40)
Harald Weltef9476812009-12-15 21:36:05 +01001043 mr->flags |= MEAS_REP_F_DL_DTX;
1044 mr->ul.full.rx_lev = val[0] & 0x3f;
1045 mr->ul.sub.rx_lev = val[1] & 0x3f;
1046 mr->ul.full.rx_qual = val[2]>>3 & 0x7;
1047 mr->ul.sub.rx_qual = val[2] & 0x7;
Harald Welte59b04682009-06-10 05:40:52 +08001048 }
Harald Weltec20bd1d2009-11-29 19:07:28 +01001049
Harald Weltef9476812009-12-15 21:36:05 +01001050 mr->bs_power = *TLVP_VAL(&tp, RSL_IE_BS_POWER);
Harald Weltec20bd1d2009-11-29 19:07:28 +01001051
1052 /* Optional Parts */
Harald Welte59b04682009-06-10 05:40:52 +08001053 if (TLVP_PRESENT(&tp, RSL_IE_MS_TIMING_OFFSET))
Harald Weltef9476812009-12-15 21:36:05 +01001054 mr->ms_timing_offset =
Harald Weltec20bd1d2009-11-29 19:07:28 +01001055 *TLVP_VAL(&tp, RSL_IE_MS_TIMING_OFFSET);
1056
Harald Weltea1467eb2009-06-20 18:44:35 +02001057 if (TLVP_PRESENT(&tp, RSL_IE_L1_INFO)) {
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001058 struct e1inp_sign_link *sign_link = msg->dst;
1059
Harald Weltec20bd1d2009-11-29 19:07:28 +01001060 val = TLVP_VAL(&tp, RSL_IE_L1_INFO);
Harald Weltef9476812009-12-15 21:36:05 +01001061 mr->flags |= MEAS_REP_F_MS_L1;
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001062 mr->ms_l1.pwr = ms_pwr_dbm(sign_link->trx->bts->band, val[0] >> 3);
Harald Weltec20bd1d2009-11-29 19:07:28 +01001063 if (val[0] & 0x04)
Harald Weltef9476812009-12-15 21:36:05 +01001064 mr->flags |= MEAS_REP_F_FPC;
1065 mr->ms_l1.ta = val[1];
Andreas Eversbergfe56cf82011-12-24 11:49:05 +01001066 /* BS11 and Nokia reports TA shifted by 2 bits */
1067 if (msg->lchan->ts->trx->bts->type == GSM_BTS_TYPE_BS11
1068 || msg->lchan->ts->trx->bts->type == GSM_BTS_TYPE_NOKIA_SITE)
Andreas Eversberg0f18e5e2011-12-16 17:45:37 +01001069 mr->ms_l1.ta >>= 2;
Harald Weltea1467eb2009-06-20 18:44:35 +02001070 }
Harald Welte59b04682009-06-10 05:40:52 +08001071 if (TLVP_PRESENT(&tp, RSL_IE_L3_INFO)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001072 msg->l3h = (uint8_t *) TLVP_VAL(&tp, RSL_IE_L3_INFO);
Harald Weltef9476812009-12-15 21:36:05 +01001073 rc = gsm48_parse_meas_rep(mr, msg);
Harald Weltec20bd1d2009-11-29 19:07:28 +01001074 if (rc < 0)
1075 return rc;
1076 }
1077
Harald Welte50290cc2012-07-02 17:12:08 +02001078 print_meas_rep(msg->lchan, mr);
Harald Welte59b04682009-06-10 05:40:52 +08001079
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +01001080 send_lchan_signal(S_LCHAN_MEAS_REP, msg->lchan, mr);
Harald Welte4efcc542009-11-30 19:16:47 +01001081
Harald Welte59b04682009-06-10 05:40:52 +08001082 return 0;
1083}
1084
Harald Welte6720a432009-11-29 22:45:52 +01001085/* Chapter 8.4.7 */
1086static int rsl_rx_hando_det(struct msgb *msg)
1087{
1088 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1089 struct tlv_parsed tp;
1090
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001091 DEBUGP(DRSL, "%s HANDOVER DETECT ", gsm_lchan_name(msg->lchan));
Harald Welte6720a432009-11-29 22:45:52 +01001092
1093 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
1094
1095 if (TLVP_PRESENT(&tp, RSL_IE_ACCESS_DELAY))
1096 DEBUGPC(DRSL, "access delay = %u\n",
1097 *TLVP_VAL(&tp, RSL_IE_ACCESS_DELAY));
1098 else
1099 DEBUGPC(DRSL, "\n");
1100
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +01001101 send_lchan_signal(S_LCHAN_HANDOVER_DETECT, msg->lchan, NULL);
Harald Welte6720a432009-11-29 22:45:52 +01001102
1103 return 0;
1104}
1105
Harald Welte59b04682009-06-10 05:40:52 +08001106static int abis_rsl_rx_dchan(struct msgb *msg)
1107{
1108 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
1109 int rc = 0;
1110 char *ts_name;
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001111 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001112
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001113 msg->lchan = lchan_lookup(sign_link->trx, rslh->chan_nr);
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001114 ts_name = gsm_lchan_name(msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001115
Harald Welte59b04682009-06-10 05:40:52 +08001116 switch (rslh->c.msg_type) {
1117 case RSL_MT_CHAN_ACTIV_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001118 DEBUGP(DRSL, "%s CHANNEL ACTIVATE ACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001119 rc = rsl_rx_chan_act_ack(msg);
1120 break;
1121 case RSL_MT_CHAN_ACTIV_NACK:
Harald Welte59b04682009-06-10 05:40:52 +08001122 rc = rsl_rx_chan_act_nack(msg);
1123 break;
1124 case RSL_MT_CONN_FAIL:
1125 rc = rsl_rx_conn_fail(msg);
1126 break;
1127 case RSL_MT_MEAS_RES:
1128 rc = rsl_rx_meas_res(msg);
1129 break;
Harald Welte6720a432009-11-29 22:45:52 +01001130 case RSL_MT_HANDO_DET:
1131 rc = rsl_rx_hando_det(msg);
1132 break;
Harald Welte59b04682009-06-10 05:40:52 +08001133 case RSL_MT_RF_CHAN_REL_ACK:
Harald Welte9773f6c2011-01-14 14:16:16 +01001134 rc = rsl_rx_rf_chan_rel_ack(msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001135 break;
1136 case RSL_MT_MODE_MODIFY_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001137 DEBUGP(DRSL, "%s CHANNEL MODE MODIFY ACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001138 break;
1139 case RSL_MT_MODE_MODIFY_NACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001140 LOGP(DRSL, LOGL_ERROR, "%s CHANNEL MODE MODIFY NACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001141 break;
Harald Welteaed946e2009-10-24 10:29:22 +02001142 case RSL_MT_IPAC_PDCH_ACT_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001143 DEBUGPC(DRSL, "%s IPAC PDCH ACT ACK\n", ts_name);
Harald Welte2b361522010-03-28 14:42:09 +08001144 msg->lchan->ts->flags |= TS_F_PDCH_MODE;
Harald Welteaed946e2009-10-24 10:29:22 +02001145 break;
1146 case RSL_MT_IPAC_PDCH_ACT_NACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001147 LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH ACT NACK\n", ts_name);
Harald Welteaed946e2009-10-24 10:29:22 +02001148 break;
1149 case RSL_MT_IPAC_PDCH_DEACT_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001150 DEBUGP(DRSL, "%s IPAC PDCH DEACT ACK\n", ts_name);
Harald Welte2b361522010-03-28 14:42:09 +08001151 msg->lchan->ts->flags &= ~TS_F_PDCH_MODE;
Harald Welteaed946e2009-10-24 10:29:22 +02001152 break;
1153 case RSL_MT_IPAC_PDCH_DEACT_NACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001154 LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH DEACT NACK\n", ts_name);
Harald Welteaed946e2009-10-24 10:29:22 +02001155 break;
Harald Welte59b04682009-06-10 05:40:52 +08001156 case RSL_MT_PHY_CONTEXT_CONF:
1157 case RSL_MT_PREPROC_MEAS_RES:
1158 case RSL_MT_TALKER_DET:
1159 case RSL_MT_LISTENER_DET:
1160 case RSL_MT_REMOTE_CODEC_CONF_REP:
1161 case RSL_MT_MR_CODEC_MOD_ACK:
1162 case RSL_MT_MR_CODEC_MOD_NACK:
1163 case RSL_MT_MR_CODEC_MOD_PER:
Harald Weltede4477a2009-12-24 12:20:20 +01001164 LOGP(DRSL, LOGL_NOTICE, "%s Unimplemented Abis RSL DChan "
1165 "msg 0x%02x\n", ts_name, rslh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001166 break;
1167 default:
Harald Weltede4477a2009-12-24 12:20:20 +01001168 LOGP(DRSL, LOGL_NOTICE, "%s unknown Abis RSL DChan msg 0x%02x\n",
1169 ts_name, rslh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001170 return -EINVAL;
1171 }
1172
1173 return rc;
1174}
1175
1176static int rsl_rx_error_rep(struct msgb *msg)
1177{
1178 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
Harald Weltef1a168d2009-07-28 17:58:09 +02001179 struct tlv_parsed tp;
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001180 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001181
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001182 LOGP(DRSL, LOGL_ERROR, "%s ERROR REPORT ", gsm_trx_name(sign_link->trx));
Harald Weltef1a168d2009-07-28 17:58:09 +02001183
1184 rsl_tlv_parse(&tp, rslh->data, msgb_l2len(msg)-sizeof(*rslh));
1185
1186 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
Harald Weltede4477a2009-12-24 12:20:20 +01001187 print_rsl_cause(LOGL_ERROR, TLVP_VAL(&tp, RSL_IE_CAUSE),
Harald Weltef1a168d2009-07-28 17:58:09 +02001188 TLVP_LEN(&tp, RSL_IE_CAUSE));
1189
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001190 LOGPC(DRSL, LOGL_ERROR, "\n");
Harald Welte59b04682009-06-10 05:40:52 +08001191
1192 return 0;
1193}
1194
1195static int abis_rsl_rx_trx(struct msgb *msg)
1196{
1197 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001198 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001199 int rc = 0;
1200
1201 switch (rslh->msg_type) {
1202 case RSL_MT_ERROR_REPORT:
1203 rc = rsl_rx_error_rep(msg);
1204 break;
1205 case RSL_MT_RF_RES_IND:
1206 /* interference on idle channels of TRX */
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001207 //DEBUGP(DRSL, "%s RF Resource Indication\n", gsm_trx_name(sign_link->trx));
Harald Welte59b04682009-06-10 05:40:52 +08001208 break;
1209 case RSL_MT_OVERLOAD:
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +02001210 /* indicate CCCH / ACCH / processor overload */
Harald Welte (local)ab788cf2009-12-28 23:14:22 +01001211 LOGP(DRSL, LOGL_ERROR, "%s CCCH/ACCH/CPU Overload\n",
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001212 gsm_trx_name(sign_link->trx));
Harald Welte59b04682009-06-10 05:40:52 +08001213 break;
Dieter Spaar49c843e2011-07-28 00:01:50 +02001214 case 0x42: /* Nokia specific: SI End ACK */
1215 LOGP(DRSL, LOGL_INFO, "Nokia SI End ACK\n");
1216 break;
1217 case 0x43: /* Nokia specific: SI End NACK */
1218 LOGP(DRSL, LOGL_INFO, "Nokia SI End NACK\n");
1219 break;
Harald Welte59b04682009-06-10 05:40:52 +08001220 default:
Harald Welte (local)ab788cf2009-12-28 23:14:22 +01001221 LOGP(DRSL, LOGL_NOTICE, "%s Unknown Abis RSL TRX message "
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001222 "type 0x%02x\n", gsm_trx_name(sign_link->trx), rslh->msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001223 return -EINVAL;
1224 }
1225 return rc;
1226}
1227
Harald Welte427dbc42009-08-10 00:26:10 +02001228/* If T3101 expires, we never received a response to IMMEDIATE ASSIGN */
1229static void t3101_expired(void *data)
1230{
1231 struct gsm_lchan *lchan = data;
1232
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +08001233 rsl_rf_chan_release(lchan, 1);
Harald Welte427dbc42009-08-10 00:26:10 +02001234}
1235
Holger Hans Peter Freyther4a00c062010-05-31 21:33:15 +08001236/* If T3111 expires, we will send the RF Channel Request */
1237static void t3111_expired(void *data)
1238{
1239 struct gsm_lchan *lchan = data;
1240
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +08001241 rsl_rf_chan_release(lchan, 0);
Holger Hans Peter Freyther4a00c062010-05-31 21:33:15 +08001242}
1243
laforge50312e82010-06-21 12:08:52 +02001244#define GSM48_LEN2PLEN(a) (((a) << 2) | 1)
1245
Harald Weltea00fdd72010-12-23 14:39:29 +01001246/* Format an IMM ASS REJ according to 04.08 Chapter 9.1.20 */
1247static int rsl_send_imm_ass_rej(struct gsm_bts *bts,
1248 unsigned int num_req_refs,
1249 struct gsm48_req_ref *rqd_refs,
1250 uint8_t wait_ind)
1251{
1252 uint8_t buf[GSM_MACBLOCK_LEN];
1253 struct gsm48_imm_ass_rej *iar = (struct gsm48_imm_ass_rej *)buf;
1254
1255 /* create IMMEDIATE ASSIGN REJECT 04.08 message */
1256 memset(iar, 0, sizeof(*iar));
1257 iar->proto_discr = GSM48_PDISC_RR;
1258 iar->msg_type = GSM48_MT_RR_IMM_ASS;
1259 iar->page_mode = GSM48_PM_SAME;
1260
1261 memcpy(&iar->req_ref1, &rqd_refs[0], sizeof(iar->req_ref1));
1262 iar->wait_ind1 = wait_ind;
1263
1264 if (num_req_refs >= 2)
1265 memcpy(&iar->req_ref2, &rqd_refs[1], sizeof(iar->req_ref2));
1266 else
1267 memcpy(&iar->req_ref2, &rqd_refs[0], sizeof(iar->req_ref2));
1268 iar->wait_ind2 = wait_ind;
1269
1270 if (num_req_refs >= 3)
1271 memcpy(&iar->req_ref3, &rqd_refs[2], sizeof(iar->req_ref3));
1272 else
1273 memcpy(&iar->req_ref3, &rqd_refs[0], sizeof(iar->req_ref3));
1274 iar->wait_ind3 = wait_ind;
1275
1276 if (num_req_refs >= 4)
1277 memcpy(&iar->req_ref4, &rqd_refs[3], sizeof(iar->req_ref4));
1278 else
1279 memcpy(&iar->req_ref4, &rqd_refs[0], sizeof(iar->req_ref4));
1280 iar->wait_ind4 = wait_ind;
1281
1282 return rsl_imm_assign_cmd(bts, sizeof(iar), (uint8_t *) iar);
1283}
1284
Harald Welte59b04682009-06-10 05:40:52 +08001285/* MS has requested a channel on the RACH */
1286static int rsl_rx_chan_rqd(struct msgb *msg)
1287{
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001288 struct e1inp_sign_link *sign_link = msg->dst;
1289 struct gsm_bts *bts = sign_link->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +08001290 struct abis_rsl_dchan_hdr *rqd_hdr = msgb_l2(msg);
1291 struct gsm48_req_ref *rqd_ref;
Harald Welte59b04682009-06-10 05:40:52 +08001292 enum gsm_chan_t lctype;
1293 enum gsm_chreq_reason_t chreq_reason;
1294 struct gsm_lchan *lchan;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001295 uint8_t rqd_ta;
Holger Hans Peter Freytherdb392032010-09-06 08:58:42 +08001296 int is_lu;
Harald Welte59b04682009-06-10 05:40:52 +08001297
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001298 uint16_t arfcn;
Holger Hans Peter Freytherefd75b52012-02-03 20:10:13 +01001299 uint8_t subch;
Harald Welte59b04682009-06-10 05:40:52 +08001300
1301 /* parse request reference to be used in immediate assign */
1302 if (rqd_hdr->data[0] != RSL_IE_REQ_REFERENCE)
1303 return -EINVAL;
1304
1305 rqd_ref = (struct gsm48_req_ref *) &rqd_hdr->data[1];
1306
1307 /* parse access delay and use as TA */
1308 if (rqd_hdr->data[sizeof(struct gsm48_req_ref)+1] != RSL_IE_ACCESS_DELAY)
1309 return -EINVAL;
1310 rqd_ta = rqd_hdr->data[sizeof(struct gsm48_req_ref)+2];
1311
1312 /* determine channel type (SDCCH/TCH_F/TCH_H) based on
1313 * request reference RA */
Holger Hans Peter Freytherf0f37f12010-09-06 09:36:02 +08001314 lctype = get_ctype_by_chreq(bts->network, rqd_ref->ra);
1315 chreq_reason = get_reason_by_chreq(rqd_ref->ra, bts->network->neci);
Harald Welte59b04682009-06-10 05:40:52 +08001316
Pablo Neira Ayuso1c450742011-05-06 12:13:10 +02001317 osmo_counter_inc(bts->network->stats.chreq.total);
Harald Welte3edc5a92009-12-22 00:41:05 +01001318
Holger Hans Peter Freytherdb392032010-09-06 08:58:42 +08001319 /*
1320 * We want LOCATION UPDATES to succeed and will assign a TCH
1321 * if we have no SDCCH available.
1322 */
1323 is_lu = !!(chreq_reason == GSM_CHREQ_REASON_LOCATION_UPD);
1324
Harald Welte59b04682009-06-10 05:40:52 +08001325 /* check availability / allocate channel */
Holger Hans Peter Freytherdb392032010-09-06 08:58:42 +08001326 lchan = lchan_alloc(bts, lctype, is_lu);
Harald Welte59b04682009-06-10 05:40:52 +08001327 if (!lchan) {
Harald Welte (local)e0bb5fa2009-12-27 13:48:09 +01001328 LOGP(DRSL, LOGL_NOTICE, "BTS %d CHAN RQD: no resources for %s 0x%x\n",
Harald Welte (local)02204d02009-12-27 18:05:25 +01001329 msg->lchan->ts->trx->bts->nr, gsm_lchant_name(lctype), rqd_ref->ra);
Pablo Neira Ayuso1c450742011-05-06 12:13:10 +02001330 osmo_counter_inc(bts->network->stats.chreq.no_channel);
Harald Weltea00fdd72010-12-23 14:39:29 +01001331 /* FIXME gather multiple CHAN RQD and reject up to 4 at the same time */
1332 if (bts->network->T3122)
1333 rsl_send_imm_ass_rej(bts, 1, rqd_ref, bts->network->T3122 & 0xff);
Harald Welte59b04682009-06-10 05:40:52 +08001334 return -ENOMEM;
1335 }
1336
Harald Weltec88a4432009-12-29 10:44:17 +01001337 if (lchan->state != LCHAN_S_NONE)
1338 LOGP(DRSL, LOGL_NOTICE, "%s lchan_alloc() returned channel "
Harald Welteab2534c2009-12-29 10:52:38 +01001339 "in state %s\n", gsm_lchan_name(lchan),
1340 gsm_lchans_name(lchan->state));
Harald Welte (local)c3be50c2009-12-27 18:12:29 +01001341
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001342 /* save the RACH data as we need it after the CHAN ACT ACK */
1343 lchan->rqd_ref = talloc_zero(bts, struct gsm48_req_ref);
1344 if (!lchan->rqd_ref) {
1345 LOGP(DRSL, LOGL_ERROR, "Failed to allocate gsm48_req_ref.\n");
1346 lchan_free(lchan);
1347 return -ENOMEM;
1348 }
1349
Holger Hans Peter Freyther161cec12011-12-29 23:33:04 +01001350 rsl_lchan_set_state(lchan, LCHAN_S_ACT_REQ);
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001351 memcpy(lchan->rqd_ref, rqd_ref, sizeof(*rqd_ref));
1352 lchan->rqd_ta = rqd_ta;
1353
Harald Welte59b04682009-06-10 05:40:52 +08001354 arfcn = lchan->ts->trx->arfcn;
1355 subch = lchan->nr;
1356
Harald Welted2dd9de2009-08-30 15:37:11 +09001357 lchan->encr.alg_id = RSL_ENC_ALG_A5(0); /* no encryption */
Harald Welte (local)cbd46102009-08-13 10:14:26 +02001358 lchan->ms_power = ms_pwr_ctl_lvl(bts->band, bts->ms_max_power);
Harald Welte9a229e12009-08-10 00:45:40 +02001359 lchan->bs_power = 0; /* 0dB reduction, output power = Pn */
Harald Welte39274f42009-07-29 15:41:29 +02001360 lchan->rsl_cmode = RSL_CMOD_SPD_SIGN;
Harald Welte77234e12009-08-28 23:28:28 +09001361 lchan->tch_mode = GSM48_CMODE_SIGN;
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001362
Harald Welte32951ea2011-08-10 23:26:33 +02001363 /* Start another timer or assume the BTS sends a ACK/NACK? */
1364 lchan->act_timer.cb = lchan_act_tmr_cb;
1365 lchan->act_timer.data = lchan;
1366 osmo_timer_schedule(&lchan->act_timer, 4, 0);
1367
Andreas Eversberg0f18e5e2011-12-16 17:45:37 +01001368 DEBUGP(DRSL, "%s Activating ARFCN(%u) SS(%u) lctype %s "
1369 "r=%s ra=0x%02x ta=%d\n", gsm_lchan_name(lchan), arfcn, subch,
1370 gsm_lchant_name(lchan->type), gsm_chreq_name(chreq_reason),
1371 rqd_ref->ra, rqd_ta);
1372
1373 /* BS11 requires TA shifted by 2 bits */
1374 if (bts->type == GSM_BTS_TYPE_BS11)
1375 rqd_ta <<= 2;
Harald Welteb90d7bd2009-12-17 00:31:10 +01001376 rsl_chan_activate_lchan(lchan, 0x00, rqd_ta, 0);
Harald Welte59b04682009-06-10 05:40:52 +08001377
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001378 return 0;
1379}
1380
1381static int rsl_send_imm_assignment(struct gsm_lchan *lchan)
1382{
1383 struct gsm_bts *bts = lchan->ts->trx->bts;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001384 uint8_t buf[GSM_MACBLOCK_LEN];
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001385 struct gsm48_imm_ass *ia = (struct gsm48_imm_ass *) buf;
1386
Harald Welte59b04682009-06-10 05:40:52 +08001387 /* create IMMEDIATE ASSIGN 04.08 messge */
laforgee06d5982010-06-20 15:18:46 +02001388 memset(ia, 0, sizeof(*ia));
laforge50312e82010-06-21 12:08:52 +02001389 /* we set ia->l2_plen once we know the length of the MA below */
laforgee06d5982010-06-20 15:18:46 +02001390 ia->proto_discr = GSM48_PDISC_RR;
1391 ia->msg_type = GSM48_MT_RR_IMM_ASS;
1392 ia->page_mode = GSM48_PM_SAME;
1393 gsm48_lchan2chan_desc(&ia->chan_desc, lchan);
Harald Weltea42a93f2010-06-14 22:26:10 +02001394
Harald Welte59b04682009-06-10 05:40:52 +08001395 /* use request reference extracted from CHAN_RQD */
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001396 memcpy(&ia->req_ref, lchan->rqd_ref, sizeof(ia->req_ref));
1397 ia->timing_advance = lchan->rqd_ta;
Harald Weltea42a93f2010-06-14 22:26:10 +02001398 if (!lchan->ts->hopping.enabled) {
laforgee06d5982010-06-20 15:18:46 +02001399 ia->mob_alloc_len = 0;
Harald Weltea42a93f2010-06-14 22:26:10 +02001400 } else {
laforgee06d5982010-06-20 15:18:46 +02001401 ia->mob_alloc_len = lchan->ts->hopping.ma_len;
1402 memcpy(ia->mob_alloc, lchan->ts->hopping.ma_data, ia->mob_alloc_len);
Harald Weltea42a93f2010-06-14 22:26:10 +02001403 }
Harald Welte07f32182010-06-28 18:41:27 +02001404 /* we need to subtract 1 byte from sizeof(*ia) since ia includes the l2_plen field */
1405 ia->l2_plen = GSM48_LEN2PLEN((sizeof(*ia)-1) + ia->mob_alloc_len);
Harald Welte59b04682009-06-10 05:40:52 +08001406
Harald Welte427dbc42009-08-10 00:26:10 +02001407 /* Start timer T3101 to wait for GSM48_MT_RR_PAG_RESP */
1408 lchan->T3101.cb = t3101_expired;
1409 lchan->T3101.data = lchan;
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +02001410 osmo_timer_schedule(&lchan->T3101, bts->network->T3101, 0);
Harald Welte59b04682009-06-10 05:40:52 +08001411
1412 /* send IMMEDIATE ASSIGN CMD on RSL to BTS (to send on CCCH to MS) */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001413 return rsl_imm_assign_cmd(bts, sizeof(*ia)+ia->mob_alloc_len, (uint8_t *) ia);
Harald Welte59b04682009-06-10 05:40:52 +08001414}
1415
Holger Hans Peter Freyther285af692012-02-03 20:26:25 +01001416/* current load on the CCCH */
Harald Welte59b04682009-06-10 05:40:52 +08001417static int rsl_rx_ccch_load(struct msgb *msg)
1418{
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001419 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001420 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
Holger Hans Peter Freyther285af692012-02-03 20:26:25 +01001421 struct ccch_signal_data sd;
1422
1423 sd.bts = sign_link->trx->bts;
1424 sd.rach_slot_count = -1;
1425 sd.rach_busy_count = -1;
1426 sd.rach_access_count = -1;
Harald Welte59b04682009-06-10 05:40:52 +08001427
1428 switch (rslh->data[0]) {
1429 case RSL_IE_PAGING_LOAD:
Holger Hans Peter Freyther285af692012-02-03 20:26:25 +01001430 sd.pg_buf_space = rslh->data[1] << 8 | rslh->data[2];
1431 if (is_ipaccess_bts(sign_link->trx->bts) && sd.pg_buf_space == 0xffff) {
Harald Welte008a4922010-04-19 10:24:07 +02001432 /* paging load below configured threshold, use 50 as default */
Holger Hans Peter Freyther285af692012-02-03 20:26:25 +01001433 sd.pg_buf_space = 50;
Harald Welte008a4922010-04-19 10:24:07 +02001434 }
Holger Hans Peter Freyther285af692012-02-03 20:26:25 +01001435 paging_update_buffer_space(sign_link->trx->bts, sd.pg_buf_space);
1436 osmo_signal_dispatch(SS_CCCH, S_CCCH_PAGING_LOAD, &sd);
Harald Welte59b04682009-06-10 05:40:52 +08001437 break;
1438 case RSL_IE_RACH_LOAD:
1439 if (msg->data_len >= 7) {
Holger Hans Peter Freyther285af692012-02-03 20:26:25 +01001440 sd.rach_slot_count = rslh->data[2] << 8 | rslh->data[3];
1441 sd.rach_busy_count = rslh->data[4] << 8 | rslh->data[5];
1442 sd.rach_access_count = rslh->data[6] << 8 | rslh->data[7];
1443 osmo_signal_dispatch(SS_CCCH, S_CCCH_RACH_LOAD, &sd);
Harald Welte59b04682009-06-10 05:40:52 +08001444 }
1445 break;
1446 default:
1447 break;
1448 }
1449
1450 return 0;
1451}
1452
1453static int abis_rsl_rx_cchan(struct msgb *msg)
1454{
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001455 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001456 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
1457 int rc = 0;
1458
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001459 msg->lchan = lchan_lookup(sign_link->trx, rslh->chan_nr);
Harald Welte59b04682009-06-10 05:40:52 +08001460
1461 switch (rslh->c.msg_type) {
1462 case RSL_MT_CHAN_RQD:
1463 /* MS has requested a channel on the RACH */
1464 rc = rsl_rx_chan_rqd(msg);
1465 break;
1466 case RSL_MT_CCCH_LOAD_IND:
1467 /* current load on the CCCH */
1468 rc = rsl_rx_ccch_load(msg);
1469 break;
1470 case RSL_MT_DELETE_IND:
1471 /* CCCH overloaded, IMM_ASSIGN was dropped */
1472 case RSL_MT_CBCH_LOAD_IND:
1473 /* current load on the CBCH */
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001474 LOGP(DRSL, LOGL_NOTICE, "Unimplemented Abis RSL TRX message "
1475 "type 0x%02x\n", rslh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001476 break;
1477 default:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001478 LOGP(DRSL, LOGL_NOTICE, "Unknown Abis RSL TRX message type "
1479 "0x%02x\n", rslh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001480 return -EINVAL;
1481 }
1482
1483 return rc;
1484}
1485
1486static int rsl_rx_rll_err_ind(struct msgb *msg)
1487{
1488 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001489 uint8_t *rlm_cause = rllh->data;
Harald Welte59b04682009-06-10 05:40:52 +08001490
Harald Welte (local)bd76cce2009-12-26 23:55:00 +01001491 LOGP(DRLL, LOGL_ERROR, "%s ERROR INDICATION cause=%s\n",
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001492 gsm_lchan_name(msg->lchan),
Harald Welteb30935e2010-03-25 12:13:02 +08001493 rsl_rlm_cause_name(rlm_cause[1]));
Harald Welteed9a5ab2009-08-09 13:47:35 +02001494
1495 rll_indication(msg->lchan, rllh->link_id, BSC_RLLR_IND_ERR_IND);
Harald Welte (local)bd76cce2009-12-26 23:55:00 +01001496
Holger Hans Peter Freyther27942e92010-04-17 06:48:29 +02001497 if (rlm_cause[1] == RLL_CAUSE_T200_EXPIRED) {
Pablo Neira Ayuso1c450742011-05-06 12:13:10 +02001498 osmo_counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rll_err);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +08001499 return rsl_rf_chan_release(msg->lchan, 1);
Holger Hans Peter Freyther27942e92010-04-17 06:48:29 +02001500 }
Harald Welte692f5852009-07-04 09:40:05 +02001501
Harald Welte59b04682009-06-10 05:40:52 +08001502 return 0;
1503}
1504
Holger Hans Peter Freyther65f08522010-04-08 22:39:34 +02001505static void rsl_handle_release(struct gsm_lchan *lchan)
1506{
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001507 int sapi;
Holger Hans Peter Freyther4a00c062010-05-31 21:33:15 +08001508 struct gsm_bts *bts;
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001509
1510 /* maybe we have only brought down one RLL */
Holger Hans Peter Freytherd26cbc82010-04-08 22:47:44 +02001511 if (lchan->state != LCHAN_S_REL_REQ)
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001512 return;
1513
1514 for (sapi = 0; sapi < ARRAY_SIZE(lchan->sapis); ++sapi) {
1515 if (lchan->sapis[sapi] == LCHAN_SAPI_UNUSED)
1516 continue;
Harald Welte497aa982010-12-24 12:51:07 +01001517 LOGP(DRSL, LOGL_DEBUG, "%s waiting for SAPI=%d to be released.\n",
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001518 gsm_lchan_name(lchan), sapi);
1519 return;
1520 }
1521
Holger Hans Peter Freytherd26cbc82010-04-08 22:47:44 +02001522
1523
Holger Hans Peter Freyther4a00c062010-05-31 21:33:15 +08001524 /* wait a bit to send the RF Channel Release */
1525 lchan->T3111.cb = t3111_expired;
1526 lchan->T3111.data = lchan;
1527 bts = lchan->ts->trx->bts;
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +02001528 osmo_timer_schedule(&lchan->T3111, bts->network->T3111, 0);
Holger Hans Peter Freyther65f08522010-04-08 22:39:34 +02001529}
1530
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +02001531/* ESTABLISH INDICATION, LOCATION AREA UPDATE REQUEST
Harald Welte59b04682009-06-10 05:40:52 +08001532 0x02, 0x06,
1533 0x01, 0x20,
1534 0x02, 0x00,
1535 0x0b, 0x00, 0x0f, 0x05, 0x08, ... */
1536
1537static int abis_rsl_rx_rll(struct msgb *msg)
1538{
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001539 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001540 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
1541 int rc = 0;
1542 char *ts_name;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001543 uint8_t sapi = rllh->link_id & 7;
Harald Welte59b04682009-06-10 05:40:52 +08001544
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001545 msg->lchan = lchan_lookup(sign_link->trx, rllh->chan_nr);
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001546 ts_name = gsm_lchan_name(msg->lchan);
Harald Weltede4477a2009-12-24 12:20:20 +01001547 DEBUGP(DRLL, "%s SAPI=%u ", ts_name, sapi);
Harald Welte59b04682009-06-10 05:40:52 +08001548
1549 switch (rllh->c.msg_type) {
1550 case RSL_MT_DATA_IND:
1551 DEBUGPC(DRLL, "DATA INDICATION\n");
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +02001552 if (msgb_l2len(msg) >
Harald Welte59b04682009-06-10 05:40:52 +08001553 sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) &&
1554 rllh->data[0] == RSL_IE_L3_INFO) {
1555 msg->l3h = &rllh->data[3];
Harald Welte (local)64994ce2009-08-14 11:41:12 +02001556 return gsm0408_rcvmsg(msg, rllh->link_id);
Harald Welte59b04682009-06-10 05:40:52 +08001557 }
1558 break;
1559 case RSL_MT_EST_IND:
1560 DEBUGPC(DRLL, "ESTABLISH INDICATION\n");
Harald Welte427dbc42009-08-10 00:26:10 +02001561 /* lchan is established, stop T3101 */
Holger Hans Peter Freytherd8318052009-10-28 14:23:39 +01001562 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_MS;
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +02001563 osmo_timer_del(&msg->lchan->T3101);
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +02001564 if (msgb_l2len(msg) >
Harald Welte59b04682009-06-10 05:40:52 +08001565 sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) &&
1566 rllh->data[0] == RSL_IE_L3_INFO) {
1567 msg->l3h = &rllh->data[3];
Harald Welte (local)64994ce2009-08-14 11:41:12 +02001568 return gsm0408_rcvmsg(msg, rllh->link_id);
Harald Welte59b04682009-06-10 05:40:52 +08001569 }
1570 break;
Harald Welteed9a5ab2009-08-09 13:47:35 +02001571 case RSL_MT_EST_CONF:
Harald Welte61402172009-08-09 14:13:58 +02001572 DEBUGPC(DRLL, "ESTABLISH CONFIRM\n");
Holger Hans Peter Freytherd8318052009-10-28 14:23:39 +01001573 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_NET;
Harald Welteed9a5ab2009-08-09 13:47:35 +02001574 rll_indication(msg->lchan, rllh->link_id,
1575 BSC_RLLR_IND_EST_CONF);
1576 break;
Harald Welte59b04682009-06-10 05:40:52 +08001577 case RSL_MT_REL_IND:
Harald Welte0f2e3c12009-08-08 13:15:07 +02001578 /* BTS informs us of having received DISC from MS */
Harald Welteb6601442009-08-04 02:50:21 +02001579 DEBUGPC(DRLL, "RELEASE INDICATION\n");
Holger Hans Peter Freytherd8318052009-10-28 14:23:39 +01001580 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_UNUSED;
Harald Welteed9a5ab2009-08-09 13:47:35 +02001581 rll_indication(msg->lchan, rllh->link_id,
1582 BSC_RLLR_IND_REL_IND);
Holger Hans Peter Freyther65f08522010-04-08 22:39:34 +02001583 rsl_handle_release(msg->lchan);
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001584 rsl_lchan_rll_release(msg->lchan, rllh->link_id);
Harald Welte59b04682009-06-10 05:40:52 +08001585 break;
1586 case RSL_MT_REL_CONF:
Harald Welte0f2e3c12009-08-08 13:15:07 +02001587 /* BTS informs us of having received UA from MS,
1588 * in response to DISC that we've sent earlier */
Harald Welteb6601442009-08-04 02:50:21 +02001589 DEBUGPC(DRLL, "RELEASE CONFIRMATION\n");
Holger Hans Peter Freytherd8318052009-10-28 14:23:39 +01001590 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_UNUSED;
Holger Hans Peter Freyther65f08522010-04-08 22:39:34 +02001591 rsl_handle_release(msg->lchan);
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001592 rsl_lchan_rll_release(msg->lchan, rllh->link_id);
Harald Welte59b04682009-06-10 05:40:52 +08001593 break;
1594 case RSL_MT_ERROR_IND:
Harald Welte59b04682009-06-10 05:40:52 +08001595 rc = rsl_rx_rll_err_ind(msg);
1596 break;
1597 case RSL_MT_UNIT_DATA_IND:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001598 LOGP(DRLL, LOGL_NOTICE, "unimplemented Abis RLL message "
1599 "type 0x%02x\n", rllh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001600 break;
1601 default:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001602 LOGP(DRLL, LOGL_NOTICE, "unknown Abis RLL message "
1603 "type 0x%02x\n", rllh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001604 }
Harald Welte59b04682009-06-10 05:40:52 +08001605 return rc;
1606}
1607
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001608static uint8_t ipa_smod_s_for_lchan(struct gsm_lchan *lchan)
Harald Welte98d79f92009-07-28 18:11:56 +02001609{
Harald Welteb284b472009-12-02 01:58:23 +05301610 switch (lchan->tch_mode) {
Harald Welte98d79f92009-07-28 18:11:56 +02001611 case GSM48_CMODE_SPEECH_V1:
Harald Welteb284b472009-12-02 01:58:23 +05301612 switch (lchan->type) {
1613 case GSM_LCHAN_TCH_F:
1614 return 0x00;
1615 case GSM_LCHAN_TCH_H:
1616 return 0x03;
1617 default:
1618 break;
1619 }
Harald Welte98d79f92009-07-28 18:11:56 +02001620 case GSM48_CMODE_SPEECH_EFR:
Harald Welteb284b472009-12-02 01:58:23 +05301621 switch (lchan->type) {
1622 case GSM_LCHAN_TCH_F:
1623 return 0x01;
1624 /* there's no half-rate EFR */
1625 default:
1626 break;
1627 }
Harald Welte98d79f92009-07-28 18:11:56 +02001628 case GSM48_CMODE_SPEECH_AMR:
Harald Welteb284b472009-12-02 01:58:23 +05301629 switch (lchan->type) {
1630 case GSM_LCHAN_TCH_F:
1631 return 0x02;
1632 case GSM_LCHAN_TCH_H:
1633 return 0x05;
1634 default:
1635 break;
1636 }
1637 default:
1638 break;
Harald Welte98d79f92009-07-28 18:11:56 +02001639 }
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001640 LOGP(DRSL, LOGL_ERROR, "Cannot determine ip.access speech mode for "
Harald Welteb284b472009-12-02 01:58:23 +05301641 "tch_mode == 0x%02x\n", lchan->tch_mode);
Harald Welte98d79f92009-07-28 18:11:56 +02001642 return 0;
Harald Welte98d79f92009-07-28 18:11:56 +02001643}
1644
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001645static uint8_t ipa_rtp_pt_for_lchan(struct gsm_lchan *lchan)
Sylvain Munaut1338a552009-12-20 22:06:40 +01001646{
1647 switch (lchan->tch_mode) {
1648 case GSM48_CMODE_SPEECH_V1:
1649 switch (lchan->type) {
1650 case GSM_LCHAN_TCH_F:
1651 return RTP_PT_GSM_FULL;
1652 case GSM_LCHAN_TCH_H:
1653 return RTP_PT_GSM_HALF;
1654 default:
1655 break;
1656 }
1657 case GSM48_CMODE_SPEECH_EFR:
1658 switch (lchan->type) {
1659 case GSM_LCHAN_TCH_F:
1660 return RTP_PT_GSM_EFR;
1661 /* there's no half-rate EFR */
1662 default:
1663 break;
1664 }
1665 case GSM48_CMODE_SPEECH_AMR:
1666 switch (lchan->type) {
1667 case GSM_LCHAN_TCH_F:
Sylvain Munaut1338a552009-12-20 22:06:40 +01001668 case GSM_LCHAN_TCH_H:
Holger Hans Peter Freytherd78bee82011-07-21 10:24:46 +02001669 return RTP_PT_AMR;
Sylvain Munaut1338a552009-12-20 22:06:40 +01001670 default:
1671 break;
1672 }
1673 default:
1674 break;
1675 }
1676 LOGP(DRSL, LOGL_ERROR, "Cannot determine ip.access rtp payload type for "
1677 "tch_mode == 0x%02x\n & lchan_type == %d",
1678 lchan->tch_mode, lchan->type);
1679 return 0;
1680}
1681
Harald Welte59b04682009-06-10 05:40:52 +08001682/* ip.access specific RSL extensions */
Harald Weltebffa4992009-12-19 16:42:06 +01001683static void ipac_parse_rtp(struct gsm_lchan *lchan, struct tlv_parsed *tv)
1684{
1685 struct in_addr ip;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001686 uint16_t port, conn_id;
Harald Weltebffa4992009-12-19 16:42:06 +01001687
1688 if (TLVP_PRESENT(tv, RSL_IE_IPAC_LOCAL_IP)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001689 ip.s_addr = *((uint32_t *) TLVP_VAL(tv, RSL_IE_IPAC_LOCAL_IP));
Harald Weltebffa4992009-12-19 16:42:06 +01001690 DEBUGPC(DRSL, "LOCAL_IP=%s ", inet_ntoa(ip));
1691 lchan->abis_ip.bound_ip = ntohl(ip.s_addr);
1692 }
1693
1694 if (TLVP_PRESENT(tv, RSL_IE_IPAC_LOCAL_PORT)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001695 port = *((uint16_t *) TLVP_VAL(tv, RSL_IE_IPAC_LOCAL_PORT));
Harald Weltebffa4992009-12-19 16:42:06 +01001696 port = ntohs(port);
1697 DEBUGPC(DRSL, "LOCAL_PORT=%u ", port);
1698 lchan->abis_ip.bound_port = port;
1699 }
1700
1701 if (TLVP_PRESENT(tv, RSL_IE_IPAC_CONN_ID)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001702 conn_id = *((uint16_t *) TLVP_VAL(tv, RSL_IE_IPAC_CONN_ID));
Harald Weltebffa4992009-12-19 16:42:06 +01001703 conn_id = ntohs(conn_id);
1704 DEBUGPC(DRSL, "CON_ID=%u ", conn_id);
1705 lchan->abis_ip.conn_id = conn_id;
1706 }
1707
1708 if (TLVP_PRESENT(tv, RSL_IE_IPAC_RTP_PAYLOAD2)) {
1709 lchan->abis_ip.rtp_payload2 =
1710 *TLVP_VAL(tv, RSL_IE_IPAC_RTP_PAYLOAD2);
1711 DEBUGPC(DRSL, "RTP_PAYLOAD2=0x%02x ",
1712 lchan->abis_ip.rtp_payload2);
1713 }
1714
1715 if (TLVP_PRESENT(tv, RSL_IE_IPAC_SPEECH_MODE)) {
1716 lchan->abis_ip.speech_mode =
1717 *TLVP_VAL(tv, RSL_IE_IPAC_SPEECH_MODE);
1718 DEBUGPC(DRSL, "speech_mode=0x%02x ",
1719 lchan->abis_ip.speech_mode);
1720 }
1721
1722 if (TLVP_PRESENT(tv, RSL_IE_IPAC_REMOTE_IP)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001723 ip.s_addr = *((uint32_t *) TLVP_VAL(tv, RSL_IE_IPAC_REMOTE_IP));
Harald Weltebffa4992009-12-19 16:42:06 +01001724 DEBUGPC(DRSL, "REMOTE_IP=%s ", inet_ntoa(ip));
1725 lchan->abis_ip.connect_ip = ntohl(ip.s_addr);
1726 }
1727
1728 if (TLVP_PRESENT(tv, RSL_IE_IPAC_REMOTE_PORT)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001729 port = *((uint16_t *) TLVP_VAL(tv, RSL_IE_IPAC_REMOTE_PORT));
Harald Weltebffa4992009-12-19 16:42:06 +01001730 port = ntohs(port);
1731 DEBUGPC(DRSL, "REMOTE_PORT=%u ", port);
1732 lchan->abis_ip.connect_port = port;
1733 }
1734}
1735
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001736int rsl_ipacc_crcx(struct gsm_lchan *lchan)
Harald Welte59b04682009-06-10 05:40:52 +08001737{
1738 struct msgb *msg = rsl_msgb_alloc();
1739 struct abis_rsl_dchan_hdr *dh;
1740
1741 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001742 init_dchan_hdr(dh, RSL_MT_IPAC_CRCX);
Harald Welte59b04682009-06-10 05:40:52 +08001743 dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
Harald Weltee6d51f92011-06-25 10:02:33 +02001744 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001745
Harald Welte98d79f92009-07-28 18:11:56 +02001746 /* 0x1- == receive-only, 0x-1 == EFR codec */
Harald Weltebffa4992009-12-19 16:42:06 +01001747 lchan->abis_ip.speech_mode = 0x10 | ipa_smod_s_for_lchan(lchan);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001748 lchan->abis_ip.rtp_payload = ipa_rtp_pt_for_lchan(lchan);
Harald Weltebffa4992009-12-19 16:42:06 +01001749 msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, lchan->abis_ip.speech_mode);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001750 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD, lchan->abis_ip.rtp_payload);
Harald Welte98d79f92009-07-28 18:11:56 +02001751
Sylvain Munaut1338a552009-12-20 22:06:40 +01001752 DEBUGP(DRSL, "%s IPAC_BIND speech_mode=0x%02x RTP_PAYLOAD=%d\n",
1753 gsm_lchan_name(lchan), lchan->abis_ip.speech_mode,
1754 lchan->abis_ip.rtp_payload);
Harald Welte98d79f92009-07-28 18:11:56 +02001755
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001756 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +08001757
1758 return abis_rsl_sendmsg(msg);
1759}
1760
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001761int rsl_ipacc_mdcx(struct gsm_lchan *lchan, uint32_t ip, uint16_t port,
1762 uint8_t rtp_payload2)
Harald Welte59b04682009-06-10 05:40:52 +08001763{
1764 struct msgb *msg = rsl_msgb_alloc();
1765 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001766 uint32_t *att_ip;
Harald Welte98d79f92009-07-28 18:11:56 +02001767 struct in_addr ia;
Harald Welte59b04682009-06-10 05:40:52 +08001768
1769 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001770 init_dchan_hdr(dh, RSL_MT_IPAC_MDCX);
Harald Welte59b04682009-06-10 05:40:52 +08001771 dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
Harald Weltee6d51f92011-06-25 10:02:33 +02001772 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001773
Harald Weltebffa4992009-12-19 16:42:06 +01001774 /* we need to store these now as MDCX_ACK does not return them :( */
1775 lchan->abis_ip.rtp_payload2 = rtp_payload2;
1776 lchan->abis_ip.connect_port = port;
1777 lchan->abis_ip.connect_ip = ip;
1778
Harald Weltefb4a9e92009-07-29 12:12:18 +02001779 /* 0x0- == both directions, 0x-1 == EFR codec */
Harald Weltebffa4992009-12-19 16:42:06 +01001780 lchan->abis_ip.speech_mode = 0x00 | ipa_smod_s_for_lchan(lchan);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001781 lchan->abis_ip.rtp_payload = ipa_rtp_pt_for_lchan(lchan);
Harald Weltefb4a9e92009-07-29 12:12:18 +02001782
Harald Welte98d79f92009-07-28 18:11:56 +02001783 ia.s_addr = htonl(ip);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001784 DEBUGP(DRSL, "%s IPAC_MDCX IP=%s PORT=%d RTP_PAYLOAD=%d RTP_PAYLOAD2=%d "
1785 "CONN_ID=%d speech_mode=0x%02x\n", gsm_lchan_name(lchan),
1786 inet_ntoa(ia), port, lchan->abis_ip.rtp_payload, rtp_payload2,
1787 lchan->abis_ip.conn_id, lchan->abis_ip.speech_mode);
Harald Welte98d79f92009-07-28 18:11:56 +02001788
Harald Weltebffa4992009-12-19 16:42:06 +01001789 msgb_tv16_put(msg, RSL_IE_IPAC_CONN_ID, lchan->abis_ip.conn_id);
1790 msgb_v_put(msg, RSL_IE_IPAC_REMOTE_IP);
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001791 att_ip = (uint32_t *) msgb_put(msg, sizeof(ip));
Harald Weltebffa4992009-12-19 16:42:06 +01001792 *att_ip = ia.s_addr;
1793 msgb_tv16_put(msg, RSL_IE_IPAC_REMOTE_PORT, port);
1794 msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, lchan->abis_ip.speech_mode);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001795 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD, lchan->abis_ip.rtp_payload);
Harald Welte98d79f92009-07-28 18:11:56 +02001796 if (rtp_payload2)
1797 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD2, rtp_payload2);
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001798
1799 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +08001800
1801 return abis_rsl_sendmsg(msg);
1802}
1803
Harald Welte9947d9f2009-12-20 16:51:09 +01001804/* tell BTS to connect RTP stream to our local RTP socket */
1805int rsl_ipacc_mdcx_to_rtpsock(struct gsm_lchan *lchan)
1806{
1807 struct rtp_socket *rs = lchan->abis_ip.rtp_socket;
1808 int rc;
1809
1810 rc = rsl_ipacc_mdcx(lchan, ntohl(rs->rtp.sin_local.sin_addr.s_addr),
1811 ntohs(rs->rtp.sin_local.sin_port),
1812 /* FIXME: use RTP payload of bound socket, not BTS*/
1813 lchan->abis_ip.rtp_payload2);
1814
1815 return rc;
1816}
1817
Harald Welte6f40df02010-12-23 12:59:52 +01001818int rsl_ipacc_pdch_activate(struct gsm_bts_trx_ts *ts, int act)
Harald Welteaed946e2009-10-24 10:29:22 +02001819{
1820 struct msgb *msg = rsl_msgb_alloc();
1821 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001822 uint8_t msg_type;
Harald Welte2b361522010-03-28 14:42:09 +08001823
1824 if (act)
1825 msg_type = RSL_MT_IPAC_PDCH_ACT;
1826 else
1827 msg_type = RSL_MT_IPAC_PDCH_DEACT;
Harald Welteaed946e2009-10-24 10:29:22 +02001828
1829 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Harald Welte2b361522010-03-28 14:42:09 +08001830 init_dchan_hdr(dh, msg_type);
Harald Welteaed946e2009-10-24 10:29:22 +02001831 dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
Harald Weltee6d51f92011-06-25 10:02:33 +02001832 dh->chan_nr = gsm_ts2chan_nr(ts, 0);
Harald Welteaed946e2009-10-24 10:29:22 +02001833
Harald Welte6f40df02010-12-23 12:59:52 +01001834 DEBUGP(DRSL, "%s IPAC_PDCH_%sACT\n", gsm_ts_name(ts),
Harald Welte2b361522010-03-28 14:42:09 +08001835 act ? "" : "DE");
Harald Welteaed946e2009-10-24 10:29:22 +02001836
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001837 msg->dst = ts->trx->rsl_link;
Harald Welteaed946e2009-10-24 10:29:22 +02001838
1839 return abis_rsl_sendmsg(msg);
1840}
1841
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001842static int abis_rsl_rx_ipacc_crcx_ack(struct msgb *msg)
Harald Welte59b04682009-06-10 05:40:52 +08001843{
1844 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1845 struct tlv_parsed tv;
Harald Welte87504212009-12-02 01:56:49 +05301846 struct gsm_lchan *lchan = msg->lchan;
Harald Welte59b04682009-06-10 05:40:52 +08001847
1848 /* the BTS has acknowledged a local bind, it now tells us the IP
1849 * address and port number to which it has bound the given logical
1850 * channel */
1851
1852 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
1853 if (!TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_PORT) ||
1854 !TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_IP) ||
Harald Welteb9498952009-07-12 09:45:05 +02001855 !TLVP_PRESENT(&tv, RSL_IE_IPAC_CONN_ID)) {
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001856 LOGP(DRSL, LOGL_NOTICE, "mandatory IE missing");
Harald Welte59b04682009-06-10 05:40:52 +08001857 return -EINVAL;
1858 }
Harald Welte50517742009-12-20 15:42:44 +01001859
Harald Weltebffa4992009-12-19 16:42:06 +01001860 ipac_parse_rtp(lchan, &tv);
Harald Welte50517742009-12-20 15:42:44 +01001861
Pablo Neira Ayusoef717c62011-05-06 12:12:31 +02001862 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_CRCX_ACK, msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001863
1864 return 0;
1865}
1866
Harald Weltebffa4992009-12-19 16:42:06 +01001867static int abis_rsl_rx_ipacc_mdcx_ack(struct msgb *msg)
1868{
1869 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1870 struct tlv_parsed tv;
1871 struct gsm_lchan *lchan = msg->lchan;
1872
1873 /* the BTS has acknowledged a remote connect request and
1874 * it now tells us the IP address and port number to which it has
1875 * connected the given logical channel */
1876
1877 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
1878 ipac_parse_rtp(lchan, &tv);
Pablo Neira Ayusoef717c62011-05-06 12:12:31 +02001879 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_MDCX_ACK, msg->lchan);
Harald Weltebffa4992009-12-19 16:42:06 +01001880
1881 return 0;
1882}
1883
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001884static int abis_rsl_rx_ipacc_dlcx_ind(struct msgb *msg)
Harald Welte59b04682009-06-10 05:40:52 +08001885{
1886 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1887 struct tlv_parsed tv;
1888
1889 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
Harald Welte59b04682009-06-10 05:40:52 +08001890
Harald Weltef1a168d2009-07-28 17:58:09 +02001891 if (TLVP_PRESENT(&tv, RSL_IE_CAUSE))
Harald Weltede4477a2009-12-24 12:20:20 +01001892 print_rsl_cause(LOGL_DEBUG, TLVP_VAL(&tv, RSL_IE_CAUSE),
Harald Weltef1a168d2009-07-28 17:58:09 +02001893 TLVP_LEN(&tv, RSL_IE_CAUSE));
Harald Welte59b04682009-06-10 05:40:52 +08001894
Pablo Neira Ayusoef717c62011-05-06 12:12:31 +02001895 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_DLCX_IND, msg->lchan);
Harald Welteba4e58d2009-07-28 18:02:05 +02001896
Harald Welte59b04682009-06-10 05:40:52 +08001897 return 0;
1898}
1899
1900static int abis_rsl_rx_ipacc(struct msgb *msg)
1901{
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001902 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001903 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
Harald Weltede4477a2009-12-24 12:20:20 +01001904 char *ts_name;
Harald Welte59b04682009-06-10 05:40:52 +08001905 int rc = 0;
1906
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001907 msg->lchan = lchan_lookup(sign_link->trx, rllh->chan_nr);
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001908 ts_name = gsm_lchan_name(msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001909
1910 switch (rllh->c.msg_type) {
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001911 case RSL_MT_IPAC_CRCX_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001912 DEBUGP(DRSL, "%s IPAC_CRCX_ACK ", ts_name);
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001913 rc = abis_rsl_rx_ipacc_crcx_ack(msg);
Harald Welte59b04682009-06-10 05:40:52 +08001914 break;
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001915 case RSL_MT_IPAC_CRCX_NACK:
Harald Welte59b04682009-06-10 05:40:52 +08001916 /* somehow the BTS was unable to bind the lchan to its local
1917 * port?!? */
Harald Weltede4477a2009-12-24 12:20:20 +01001918 LOGP(DRSL, LOGL_ERROR, "%s IPAC_CRCX_NACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001919 break;
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001920 case RSL_MT_IPAC_MDCX_ACK:
Harald Welte59b04682009-06-10 05:40:52 +08001921 /* the BTS tells us that a connect operation was successful */
Harald Weltede4477a2009-12-24 12:20:20 +01001922 DEBUGP(DRSL, "%s IPAC_MDCX_ACK ", ts_name);
Harald Weltebffa4992009-12-19 16:42:06 +01001923 rc = abis_rsl_rx_ipacc_mdcx_ack(msg);
Harald Welte59b04682009-06-10 05:40:52 +08001924 break;
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001925 case RSL_MT_IPAC_MDCX_NACK:
Harald Welte59b04682009-06-10 05:40:52 +08001926 /* somehow the BTS was unable to connect the lchan to a remote
1927 * port */
Harald Weltede4477a2009-12-24 12:20:20 +01001928 LOGP(DRSL, LOGL_ERROR, "%s IPAC_MDCX_NACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001929 break;
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001930 case RSL_MT_IPAC_DLCX_IND:
Harald Weltede4477a2009-12-24 12:20:20 +01001931 DEBUGP(DRSL, "%s IPAC_DLCX_IND ", ts_name);
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001932 rc = abis_rsl_rx_ipacc_dlcx_ind(msg);
Harald Welte59b04682009-06-10 05:40:52 +08001933 break;
1934 default:
Harald Weltede4477a2009-12-24 12:20:20 +01001935 LOGP(DRSL, LOGL_NOTICE, "Unknown ip.access msg_type 0x%02x\n",
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001936 rllh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001937 break;
1938 }
1939 DEBUGPC(DRSL, "\n");
1940
1941 return rc;
1942}
1943
1944
1945/* Entry-point where L2 RSL from BTS enters */
1946int abis_rsl_rcvmsg(struct msgb *msg)
1947{
Holger Hans Peter Freytherc7d94092009-11-20 15:14:01 +01001948 struct abis_rsl_common_hdr *rslh;
Harald Welte59b04682009-06-10 05:40:52 +08001949 int rc = 0;
1950
Holger Hans Peter Freytherc7d94092009-11-20 15:14:01 +01001951 if (!msg) {
1952 DEBUGP(DRSL, "Empty RSL msg?..\n");
1953 return -1;
1954 }
1955
1956 if (msgb_l2len(msg) < sizeof(*rslh)) {
1957 DEBUGP(DRSL, "Truncated RSL message with l2len: %u\n", msgb_l2len(msg));
Harald Weltece807262012-05-31 20:22:34 +02001958 msgb_free(msg);
Holger Hans Peter Freytherc7d94092009-11-20 15:14:01 +01001959 return -1;
1960 }
1961
1962 rslh = msgb_l2(msg);
1963
Harald Welte59b04682009-06-10 05:40:52 +08001964 switch (rslh->msg_discr & 0xfe) {
1965 case ABIS_RSL_MDISC_RLL:
1966 rc = abis_rsl_rx_rll(msg);
1967 break;
1968 case ABIS_RSL_MDISC_DED_CHAN:
1969 rc = abis_rsl_rx_dchan(msg);
1970 break;
1971 case ABIS_RSL_MDISC_COM_CHAN:
1972 rc = abis_rsl_rx_cchan(msg);
1973 break;
1974 case ABIS_RSL_MDISC_TRX:
1975 rc = abis_rsl_rx_trx(msg);
1976 break;
1977 case ABIS_RSL_MDISC_LOC:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001978 LOGP(DRSL, LOGL_NOTICE, "unimplemented RSL msg disc 0x%02x\n",
Harald Welte59b04682009-06-10 05:40:52 +08001979 rslh->msg_discr);
1980 break;
1981 case ABIS_RSL_MDISC_IPACCESS:
1982 rc = abis_rsl_rx_ipacc(msg);
1983 break;
1984 default:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001985 LOGP(DRSL, LOGL_NOTICE, "unknown RSL message discriminator "
1986 "0x%02x\n", rslh->msg_discr);
Harald Weltece807262012-05-31 20:22:34 +02001987 rc = -EINVAL;
Harald Welte59b04682009-06-10 05:40:52 +08001988 }
1989 msgb_free(msg);
1990 return rc;
1991}
1992
Holger Hans Peter Freytherb67f4082010-07-21 15:54:32 +08001993int rsl_sms_cb_command(struct gsm_bts *bts, uint8_t chan_number,
1994 uint8_t cb_command, const uint8_t *data, int len)
1995{
1996 struct abis_rsl_dchan_hdr *dh;
1997 struct msgb *cb_cmd;
1998
1999 cb_cmd = rsl_msgb_alloc();
2000 if (!cb_cmd)
2001 return -1;
2002
2003 dh = (struct abis_rsl_dchan_hdr *) msgb_put(cb_cmd, sizeof*dh);
2004 init_dchan_hdr(dh, RSL_MT_SMS_BC_CMD);
2005 dh->chan_nr = RSL_CHAN_SDCCH4_ACCH; /* TODO: check the chan config */
2006
2007 msgb_tv_put(cb_cmd, RSL_IE_CB_CMD_TYPE, cb_command);
2008 msgb_tlv_put(cb_cmd, RSL_IE_SMSCB_MSG, len, data);
2009
2010 cb_cmd->trx = bts->c0;
2011
2012 return abis_rsl_sendmsg(cb_cmd);
2013}
Dieter Spaar49c843e2011-07-28 00:01:50 +02002014
2015int rsl_nokia_si_begin(struct gsm_bts_trx *trx)
2016{
2017 struct abis_rsl_common_hdr *ch;
2018 struct msgb *msg = rsl_msgb_alloc();
2019
2020 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
2021 ch->msg_discr = ABIS_RSL_MDISC_TRX;
2022 ch->msg_type = 0x40; /* Nokia SI Begin */
2023
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02002024 msg->dst = trx->rsl_link;
Dieter Spaar49c843e2011-07-28 00:01:50 +02002025
2026 return abis_rsl_sendmsg(msg);
2027}
2028
2029int rsl_nokia_si_end(struct gsm_bts_trx *trx)
2030{
2031 struct abis_rsl_common_hdr *ch;
2032 struct msgb *msg = rsl_msgb_alloc();
2033
2034 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
2035 ch->msg_discr = ABIS_RSL_MDISC_TRX;
2036 ch->msg_type = 0x41; /* Nokia SI End */
2037
2038 msgb_tv_put(msg, 0xFD, 0x00); /* Nokia Pagemode Info, No paging reorganisation required */
2039
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02002040 msg->dst = trx->rsl_link;
Dieter Spaar49c843e2011-07-28 00:01:50 +02002041
2042 return abis_rsl_sendmsg(msg);
2043}
2044
2045int rsl_bs_power_control(struct gsm_bts_trx *trx, uint8_t channel, uint8_t reduction)
2046{
2047 struct abis_rsl_common_hdr *ch;
2048 struct msgb *msg = rsl_msgb_alloc();
2049
2050 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
2051 ch->msg_discr = ABIS_RSL_MDISC_DED_CHAN;
2052 ch->msg_type = RSL_MT_BS_POWER_CONTROL;
2053
2054 msgb_tv_put(msg, RSL_IE_CHAN_NR, channel);
2055 msgb_tv_put(msg, RSL_IE_BS_POWER, reduction); /* reduction in 2dB steps */
2056
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02002057 msg->dst = trx->rsl_link;
Dieter Spaar49c843e2011-07-28 00:01:50 +02002058
2059 return abis_rsl_sendmsg(msg);
2060}