blob: 83cf2ec1f1b518435961e73630faaf2b28420394 [file] [log] [blame]
Harald Weltea43f7892009-12-01 18:04:30 +05301/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface,
2 * rest octet handling according to
3 * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
4
5/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
6 *
7 * All Rights Reserved
8 *
9 * This program is free software; you can redistribute it and/or modify
Harald Welte9af6ddf2011-01-01 15:25:50 +010010 * it under the terms of the GNU Affero General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
Harald Weltea43f7892009-12-01 18:04:30 +053012 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Harald Welte9af6ddf2011-01-01 15:25:50 +010017 * GNU Affero General Public License for more details.
Harald Weltea43f7892009-12-01 18:04:30 +053018 *
Harald Welte9af6ddf2011-01-01 15:25:50 +010019 * You should have received a copy of the GNU Affero General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Harald Weltea43f7892009-12-01 18:04:30 +053021 *
22 */
23
24#include <string.h>
25#include <stdlib.h>
26#include <errno.h>
27
28#include <openbsc/gsm_data.h>
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010029#include <osmocom/core/bitvec.h>
Harald Weltea43f7892009-12-01 18:04:30 +053030#include <openbsc/rest_octets.h>
31
32/* generate SI1 rest octets */
Holger Hans Peter Freytherf876c392013-03-06 12:02:33 +010033int rest_octets_si1(uint8_t *data, uint8_t *nch_pos, int is1800_net)
Harald Weltea43f7892009-12-01 18:04:30 +053034{
35 struct bitvec bv;
36
37 memset(&bv, 0, sizeof(bv));
38 bv.data = data;
Holger Hans Peter Freyther4cffc452010-01-06 06:44:37 +010039 bv.data_len = 1;
Harald Weltea43f7892009-12-01 18:04:30 +053040
41 if (nch_pos) {
42 bitvec_set_bit(&bv, H);
43 bitvec_set_uint(&bv, *nch_pos, 5);
44 } else
45 bitvec_set_bit(&bv, L);
46
Holger Hans Peter Freytherf876c392013-03-06 12:02:33 +010047 if (is1800_net)
48 bitvec_set_bit(&bv, L);
49 else
50 bitvec_set_bit(&bv, H);
51
52 bitvec_spare_padding(&bv, 6);
Holger Hans Peter Freythercaa14862010-01-06 07:49:58 +010053 return bv.data_len;
Harald Weltea43f7892009-12-01 18:04:30 +053054}
55
56/* Append selection parameters to bitvec */
57static void append_selection_params(struct bitvec *bv,
58 const struct gsm48_si_selection_params *sp)
59{
60 if (sp->present) {
61 bitvec_set_bit(bv, H);
62 bitvec_set_bit(bv, sp->cbq);
63 bitvec_set_uint(bv, sp->cell_resel_off, 6);
64 bitvec_set_uint(bv, sp->temp_offs, 3);
65 bitvec_set_uint(bv, sp->penalty_time, 5);
66 } else
67 bitvec_set_bit(bv, L);
68}
69
70/* Append power offset to bitvec */
71static void append_power_offset(struct bitvec *bv,
72 const struct gsm48_si_power_offset *po)
73{
74 if (po->present) {
75 bitvec_set_bit(bv, H);
76 bitvec_set_uint(bv, po->power_offset, 2);
77 } else
78 bitvec_set_bit(bv, L);
79}
80
81/* Append GPRS indicator to bitvec */
82static void append_gprs_ind(struct bitvec *bv,
83 const struct gsm48_si3_gprs_ind *gi)
84{
85 if (gi->present) {
86 bitvec_set_bit(bv, H);
87 bitvec_set_uint(bv, gi->ra_colour, 3);
88 /* 0 == SI13 in BCCH Norm, 1 == SI13 sent on BCCH Ext */
89 bitvec_set_bit(bv, gi->si13_position);
90 } else
91 bitvec_set_bit(bv, L);
92}
93
94
95/* Generate SI3 Rest Octests (Chapter 10.5.2.34 / Table 10.4.72) */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +020096int rest_octets_si3(uint8_t *data, const struct gsm48_si_ro_info *si3)
Harald Weltea43f7892009-12-01 18:04:30 +053097{
98 struct bitvec bv;
99
100 memset(&bv, 0, sizeof(bv));
101 bv.data = data;
Holger Hans Peter Freyther4cffc452010-01-06 06:44:37 +0100102 bv.data_len = 4;
Harald Weltea43f7892009-12-01 18:04:30 +0530103
104 /* Optional Selection Parameters */
105 append_selection_params(&bv, &si3->selection_params);
106
107 /* Optional Power Offset */
108 append_power_offset(&bv, &si3->power_offset);
109
110 /* Do we have a SI2ter on the BCCH? */
111 if (si3->si2ter_indicator)
112 bitvec_set_bit(&bv, H);
113 else
114 bitvec_set_bit(&bv, L);
115
116 /* Early Classmark Sending Control */
117 if (si3->early_cm_ctrl)
118 bitvec_set_bit(&bv, H);
119 else
120 bitvec_set_bit(&bv, L);
121
122 /* Do we have a SI Type 9 on the BCCH? */
123 if (si3->scheduling.present) {
124 bitvec_set_bit(&bv, H);
125 bitvec_set_uint(&bv, si3->scheduling.where, 3);
126 } else
127 bitvec_set_bit(&bv, L);
128
129 /* GPRS Indicator */
130 append_gprs_ind(&bv, &si3->gprs_ind);
131
Maxf3f35052016-04-15 16:04:44 +0200132 /* 3G Early Classmark Sending Restriction controlled by
133 * early_cm_ctrl above */
134 bitvec_set_bit(&bv, H);
135
136 if (si3->si2quater_indicator) {
137 bitvec_set_bit(&bv, H); /* indicator struct present */
138 bitvec_set_uint(&bv, 0, 1); /* message is sent on BCCH Norm */
139 }
140
Holger Hans Peter Freythercaa14862010-01-06 07:49:58 +0100141 bitvec_spare_padding(&bv, (bv.data_len*8)-1);
142 return bv.data_len;
Harald Weltea43f7892009-12-01 18:04:30 +0530143}
144
145static int append_lsa_params(struct bitvec *bv,
146 const struct gsm48_lsa_params *lsa_params)
147{
148 /* FIXME */
Holger Hans Peter Freytherae80f922010-04-10 00:05:16 +0200149 return -1;
Harald Weltea43f7892009-12-01 18:04:30 +0530150}
151
152/* Generate SI4 Rest Octets (Chapter 10.5.2.35) */
Holger Hans Peter Freyther7ff77ec2010-12-29 23:06:22 +0100153int rest_octets_si4(uint8_t *data, const struct gsm48_si_ro_info *si4, int len)
Harald Weltea43f7892009-12-01 18:04:30 +0530154{
155 struct bitvec bv;
156
157 memset(&bv, 0, sizeof(bv));
158 bv.data = data;
Holger Hans Peter Freyther7ff77ec2010-12-29 23:06:22 +0100159 bv.data_len = len;
Harald Weltea43f7892009-12-01 18:04:30 +0530160
161 /* SI4 Rest Octets O */
162 append_selection_params(&bv, &si4->selection_params);
163 append_power_offset(&bv, &si4->power_offset);
164 append_gprs_ind(&bv, &si4->gprs_ind);
165
166 if (0 /* FIXME */) {
167 /* H and SI4 Rest Octets S */
168 bitvec_set_bit(&bv, H);
169
170 /* LSA Parameters */
171 if (si4->lsa_params.present) {
172 bitvec_set_bit(&bv, H);
173 append_lsa_params(&bv, &si4->lsa_params);
174 } else
175 bitvec_set_bit(&bv, L);
176
177 /* Cell Identity */
178 if (1) {
179 bitvec_set_bit(&bv, H);
180 bitvec_set_uint(&bv, si4->cell_id, 16);
181 } else
182 bitvec_set_bit(&bv, L);
183
184 /* LSA ID Information */
185 if (0) {
186 bitvec_set_bit(&bv, H);
187 /* FIXME */
188 } else
189 bitvec_set_bit(&bv, L);
190 } else {
191 /* L and break indicator */
192 bitvec_set_bit(&bv, L);
193 bitvec_set_bit(&bv, si4->break_ind ? H : L);
194 }
195
Holger Hans Peter Freythercaa14862010-01-06 07:49:58 +0100196 return bv.data_len;
Harald Weltea43f7892009-12-01 18:04:30 +0530197}
198
199/* GPRS Mobile Allocation as per TS 04.60 Chapter 12.10a:
200 < GPRS Mobile Allocation IE > ::=
201 < HSN : bit (6) >
202 { 0 | 1 < RFL number list : < RFL number list struct > > }
203 { 0 < MA_LENGTH : bit (6) >
204 < MA_BITMAP: bit (val(MA_LENGTH) + 1) >
205 | 1 { 0 | 1 <ARFCN index list : < ARFCN index list struct > > } } ;
206
207 < RFL number list struct > :: =
208 < RFL_NUMBER : bit (4) >
209 { 0 | 1 < RFL number list struct > } ;
210 < ARFCN index list struct > ::=
211 < ARFCN_INDEX : bit(6) >
212 { 0 | 1 < ARFCN index list struct > } ;
213 */
214static int append_gprs_mobile_alloc(struct bitvec *bv)
215{
216 /* Hopping Sequence Number */
217 bitvec_set_uint(bv, 0, 6);
218
219 if (0) {
220 /* We want to use a RFL number list */
221 bitvec_set_bit(bv, 1);
222 /* FIXME: RFL number list */
223 } else
224 bitvec_set_bit(bv, 0);
225
226 if (0) {
227 /* We want to use a MA_BITMAP */
228 bitvec_set_bit(bv, 0);
229 /* FIXME: MA_LENGTH, MA_BITMAP, ... */
230 } else {
231 bitvec_set_bit(bv, 1);
232 if (0) {
233 /* We want to provide an ARFCN index list */
234 bitvec_set_bit(bv, 1);
235 /* FIXME */
236 } else
237 bitvec_set_bit(bv, 0);
238 }
239 return 0;
240}
241
242static int encode_t3192(unsigned int t3192)
243{
244 if (t3192 == 0)
245 return 3;
246 else if (t3192 <= 80)
247 return 4;
248 else if (t3192 <= 120)
249 return 5;
250 else if (t3192 <= 160)
251 return 6;
252 else if (t3192 <= 200)
253 return 7;
254 else if (t3192 <= 500)
255 return 0;
256 else if (t3192 <= 1000)
257 return 1;
258 else if (t3192 <= 1500)
259 return 2;
260 else
261 return -EINVAL;
262}
263
264static int encode_drx_timer(unsigned int drx)
265{
266 if (drx == 0)
267 return 0;
268 else if (drx == 1)
269 return 1;
270 else if (drx == 2)
271 return 2;
272 else if (drx <= 4)
273 return 3;
274 else if (drx <= 8)
275 return 4;
276 else if (drx <= 16)
277 return 5;
278 else if (drx <= 32)
279 return 6;
280 else if (drx <= 64)
281 return 7;
282 else
283 return -EINVAL;
284}
285
286/* GPRS Cell Options as per TS 04.60 Chapter 12.24
287 < GPRS Cell Options IE > ::=
288 < NMO : bit(2) >
289 < T3168 : bit(3) >
290 < T3192 : bit(3) >
291 < DRX_TIMER_MAX: bit(3) >
292 < ACCESS_BURST_TYPE: bit >
293 < CONTROL_ACK_TYPE : bit >
294 < BS_CV_MAX: bit(4) >
295 { 0 | 1 < PAN_DEC : bit(3) >
296 < PAN_INC : bit(3) >
297 < PAN_MAX : bit(3) >
298 { 0 | 1 < Extension Length : bit(6) >
299 < bit (val(Extension Length) + 1
300 & { < Extension Information > ! { bit ** = <no string> } } ;
301 < Extension Information > ::=
302 { 0 | 1 < EGPRS_PACKET_CHANNEL_REQUEST : bit >
303 < BEP_PERIOD : bit(4) > }
304 < PFC_FEATURE_MODE : bit >
305 < DTM_SUPPORT : bit >
306 <BSS_PAGING_COORDINATION: bit >
307 <spare bit > ** ;
308 */
Harald Weltea4e2d042009-12-20 17:08:22 +0100309static int append_gprs_cell_opt(struct bitvec *bv,
310 const struct gprs_cell_options *gco)
Harald Weltea43f7892009-12-01 18:04:30 +0530311{
312 int t3192, drx_timer_max;
313
314 t3192 = encode_t3192(gco->t3192);
315 if (t3192 < 0)
316 return t3192;
317
318 drx_timer_max = encode_drx_timer(gco->drx_timer_max);
319 if (drx_timer_max < 0)
320 return drx_timer_max;
321
322 bitvec_set_uint(bv, gco->nmo, 2);
323 bitvec_set_uint(bv, gco->t3168 / 500, 3);
324 bitvec_set_uint(bv, t3192, 3);
325 bitvec_set_uint(bv, drx_timer_max, 3);
326 /* ACCESS_BURST_TYPE: Hard-code 8bit */
327 bitvec_set_bit(bv, 0);
328 /* CONTROL_ACK_TYPE: Hard-code to RLC/MAC control block */
329 bitvec_set_bit(bv, 1);
330 bitvec_set_uint(bv, gco->bs_cv_max, 4);
331
Harald Weltea4b16652010-05-31 12:54:23 +0200332 if (0) {
333 /* hard-code no PAN_{DEC,INC,MAX} */
334 bitvec_set_bit(bv, 0);
335 } else {
336 /* copied from ip.access BSC protocol trace */
337 bitvec_set_bit(bv, 1);
338 bitvec_set_uint(bv, 1, 3); /* DEC */
339 bitvec_set_uint(bv, 1, 3); /* INC */
340 bitvec_set_uint(bv, 15, 3); /* MAX */
341 }
Harald Weltea43f7892009-12-01 18:04:30 +0530342
Harald Welteda0586a2010-04-18 14:49:05 +0200343 if (!gco->ext_info_present) {
344 /* no extension information */
345 bitvec_set_bit(bv, 0);
346 } else {
347 /* extension information */
348 bitvec_set_bit(bv, 1);
349 if (!gco->ext_info.egprs_supported) {
350 /* 6bit length of extension */
Harald Welte39608dc2010-04-18 22:47:22 +0200351 bitvec_set_uint(bv, (1 + 3)-1, 6);
Harald Welteda0586a2010-04-18 14:49:05 +0200352 /* EGPRS supported in the cell */
353 bitvec_set_bit(bv, 0);
354 } else {
355 /* 6bit length of extension */
Harald Welte39608dc2010-04-18 22:47:22 +0200356 bitvec_set_uint(bv, (1 + 5 + 3)-1, 6);
Harald Welteda0586a2010-04-18 14:49:05 +0200357 /* EGPRS supported in the cell */
358 bitvec_set_bit(bv, 1);
359 /* 1bit EGPRS PACKET CHANNEL REQUEST */
360 bitvec_set_bit(bv, gco->ext_info.use_egprs_p_ch_req);
361 /* 4bit BEP PERIOD */
362 bitvec_set_uint(bv, gco->ext_info.bep_period, 4);
363 }
364 bitvec_set_bit(bv, gco->ext_info.pfc_supported);
365 bitvec_set_bit(bv, gco->ext_info.dtm_supported);
366 bitvec_set_bit(bv, gco->ext_info.bss_paging_coordination);
367 }
Harald Weltea43f7892009-12-01 18:04:30 +0530368
369 return 0;
370}
371
372static void append_gprs_pwr_ctrl_pars(struct bitvec *bv,
Harald Weltea4e2d042009-12-20 17:08:22 +0100373 const struct gprs_power_ctrl_pars *pcp)
Harald Weltea43f7892009-12-01 18:04:30 +0530374{
375 bitvec_set_uint(bv, pcp->alpha, 4);
376 bitvec_set_uint(bv, pcp->t_avg_w, 5);
377 bitvec_set_uint(bv, pcp->t_avg_t, 5);
378 bitvec_set_uint(bv, pcp->pc_meas_chan, 1);
379 bitvec_set_uint(bv, pcp->n_avg_i, 4);
380}
381
Harald Welte5fda9082010-04-18 22:41:01 +0200382/* Generate SI13 Rest Octests (04.08 Chapter 10.5.2.37b) */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200383int rest_octets_si13(uint8_t *data, const struct gsm48_si13_info *si13)
Harald Weltea43f7892009-12-01 18:04:30 +0530384{
385 struct bitvec bv;
386
387 memset(&bv, 0, sizeof(bv));
388 bv.data = data;
Holger Hans Peter Freyther4cffc452010-01-06 06:44:37 +0100389 bv.data_len = 20;
Harald Weltea43f7892009-12-01 18:04:30 +0530390
391 if (0) {
392 /* No rest octets */
393 bitvec_set_bit(&bv, L);
394 } else {
395 bitvec_set_bit(&bv, H);
396 bitvec_set_uint(&bv, si13->bcch_change_mark, 3);
397 bitvec_set_uint(&bv, si13->si_change_field, 4);
Harald Welte97a282b2010-03-14 15:37:43 +0800398 if (1) {
Harald Weltea43f7892009-12-01 18:04:30 +0530399 bitvec_set_bit(&bv, 0);
400 } else {
401 bitvec_set_bit(&bv, 1);
402 bitvec_set_uint(&bv, si13->bcch_change_mark, 2);
403 append_gprs_mobile_alloc(&bv);
404 }
405 if (!si13->pbcch_present) {
406 /* PBCCH not present in cell */
407 bitvec_set_bit(&bv, 0);
408 bitvec_set_uint(&bv, si13->no_pbcch.rac, 8);
409 bitvec_set_bit(&bv, si13->no_pbcch.spgc_ccch_sup);
410 bitvec_set_uint(&bv, si13->no_pbcch.prio_acc_thr, 3);
411 bitvec_set_uint(&bv, si13->no_pbcch.net_ctrl_ord, 2);
412 append_gprs_cell_opt(&bv, &si13->cell_opts);
413 append_gprs_pwr_ctrl_pars(&bv, &si13->pwr_ctrl_pars);
414 } else {
415 /* PBCCH present in cell */
416 bitvec_set_bit(&bv, 1);
417 bitvec_set_uint(&bv, si13->pbcch.psi1_rep_per, 4);
418 /* PBCCH Descripiton */
419 bitvec_set_uint(&bv, si13->pbcch.pb, 4);
420 bitvec_set_uint(&bv, si13->pbcch.tsc, 3);
421 bitvec_set_uint(&bv, si13->pbcch.tn, 3);
422 switch (si13->pbcch.carrier_type) {
423 case PBCCH_BCCH:
424 bitvec_set_bit(&bv, 0);
425 bitvec_set_bit(&bv, 0);
426 break;
427 case PBCCH_ARFCN:
428 bitvec_set_bit(&bv, 0);
429 bitvec_set_bit(&bv, 1);
430 bitvec_set_uint(&bv, si13->pbcch.arfcn, 10);
431 break;
432 case PBCCH_MAIO:
433 bitvec_set_bit(&bv, 1);
434 bitvec_set_uint(&bv, si13->pbcch.maio, 6);
435 break;
436 }
437 }
Harald Welte5fda9082010-04-18 22:41:01 +0200438 /* 3GPP TS 44.018 Release 6 / 10.5.2.37b */
439 bitvec_set_bit(&bv, H); /* added Release 99 */
440 /* claim our SGSN is compatible with Release 99, as EDGE and EGPRS
441 * was only added in this Release */
442 bitvec_set_bit(&bv, 1);
Harald Weltea43f7892009-12-01 18:04:30 +0530443 }
Holger Hans Peter Freythercaa14862010-01-06 07:49:58 +0100444 bitvec_spare_padding(&bv, (bv.data_len*8)-1);
445 return bv.data_len;
Harald Weltea43f7892009-12-01 18:04:30 +0530446}