blob: 1f96458b1fc3aac198b17aca2bf23657357729d2 [file] [log] [blame]
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +02001/* encoding.cpp
2 *
3 * Copyright (C) 2012 Ivan Klyuchnikov
4 * Copyright (C) 2012 Andreas Eversberg <jolly@eversberg.eu>
5 * Copyright (C) 2013 by Holger Hans Peter Freyther
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
Holger Hans Peter Freyther63f29d62013-10-19 19:04:03 +020022#include <encoding.h>
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +020023#include <gprs_rlcmac.h>
Holger Hans Peter Freyther34bd8bd2013-10-19 21:10:38 +020024#include <bts.h>
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +020025#include <tbf.h>
26#include <gprs_debug.h>
sivasankari8adfcd02017-01-16 15:41:21 +053027#include <egprs_rlc_compression.h>
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +020028
Tom Tsoudf698092016-07-11 17:05:19 -070029extern "C" {
30#include <osmocom/gprs/protocol/gsm_04_60.h>
31}
32
Maxd5720542016-07-14 15:41:17 +020033#include <osmocom/gsm/protocol/gsm_04_08.h>
34
35#include <stdbool.h>
Jacob Erlbeckf0e40392016-01-08 10:07:53 +010036#include <errno.h>
37#include <string.h>
38
Maxae483812016-07-28 12:03:08 +020039/* { 0 | 1 < TIMING_ADVANCE_INDEX : bit (4) > } */
40static inline bool write_tai(bitvec *dest, unsigned& wp, int8_t tai)
41{
42 if (tai < 0) { /* No TIMING_ADVANCE_INDEX: */
Alexander Couzensccde5c92017-02-04 03:10:08 +010043 bitvec_write_field(dest, &wp, 0, 1);
Maxae483812016-07-28 12:03:08 +020044 return false;
45 }
46 /* TIMING_ADVANCE_INDEX: */
Alexander Couzensccde5c92017-02-04 03:10:08 +010047 bitvec_write_field(dest, &wp, 1, 1);
48 bitvec_write_field(dest, &wp, tai, 4);
Maxae483812016-07-28 12:03:08 +020049 return true;
50}
51
52/* { 0 | 1 < TIMING_ADVANCE_VALUE : bit (6) > } */
53static inline void write_ta(bitvec *dest, unsigned& wp, int8_t ta)
54{
55 if (ta < 0) /* No TIMING_ADVANCE_VALUE: */
Alexander Couzensccde5c92017-02-04 03:10:08 +010056 bitvec_write_field(dest, &wp, 0, 1);
Maxae483812016-07-28 12:03:08 +020057 else { /* TIMING_ADVANCE_VALUE: */
Alexander Couzensccde5c92017-02-04 03:10:08 +010058 bitvec_write_field(dest, &wp, 1, 1);
59 bitvec_write_field(dest, &wp, ta, 6);
Maxae483812016-07-28 12:03:08 +020060 }
61}
62
Maxa4f570f2017-12-15 11:21:57 +010063/* 3GPP TS 44.060 Table 12.5.2.1 */
64static inline uint16_t enc_ws(uint16_t ws)
65{
66 return (ws - 64) / 32;
67}
68
69static inline void write_ws(bitvec *dest, unsigned int *write_index, uint16_t ws)
70{
71 dest->cur_bit = *write_index;
72
73 bitvec_set_u64(dest, enc_ws(ws), 5, false);
74
75 *write_index += 5;
76}
77
Maxae483812016-07-28 12:03:08 +020078/* 3GPP TS 44.060 ยง 12.12:
79 { 0 | 1 < TIMING_ADVANCE_VALUE : bit (6) > }
80 { 0 | 1 < TIMING_ADVANCE_INDEX : bit (4) >
81 < TIMING_ADVANCE_TIMESLOT_NUMBER : bit (3) > }
82 */
83static inline void write_ta_ie(bitvec *dest, unsigned& wp,
84 int8_t ta, int8_t tai, uint8_t ts)
85{
86 write_ta(dest, wp, ta);
87 if (write_tai(dest, wp, tai)) /* TIMING_ADVANCE_TIMESLOT_NUMBER: */
Alexander Couzensccde5c92017-02-04 03:10:08 +010088 bitvec_write_field(dest, &wp, ts, 3);
Maxae483812016-07-28 12:03:08 +020089}
90
Neels Hofmeyr39f84582018-02-27 22:41:07 +010091static int write_ia_rest_downlink(
92 gprs_rlcmac_dl_tbf *tbf,
93 bitvec * dest, unsigned& wp,
94 uint8_t polling, bool ta_valid, uint32_t fn,
95 uint8_t alpha, uint8_t gamma, int8_t ta_idx)
Jacob Erlbeck18831c32016-02-01 15:23:35 +010096{
Neels Hofmeyr39f84582018-02-27 22:41:07 +010097 if (!tbf) {
98 LOGP(DRLCMACDL, LOGL_ERROR,
99 "Cannot encode DL IMMEDIATE ASSIGNMENT without TBF\n");
100 return -EINVAL;
101 }
102 // GSM 04.08 10.5.2.16 IA Rest Octets
103 bitvec_write_field(dest, &wp, 3, 2); // "HH"
104 bitvec_write_field(dest, &wp, 1, 2); // "01" Packet Downlink Assignment
105 bitvec_write_field(dest, &wp,tbf->tlli(),32); // TLLI
106 bitvec_write_field(dest, &wp,0x1,1); // switch TFI : on
107 bitvec_write_field(dest, &wp,tbf->tfi(),5); // TFI
108 bitvec_write_field(dest, &wp,0x0,1); // RLC acknowledged mode
109 if (alpha) {
110 bitvec_write_field(dest, &wp,0x1,1); // ALPHA = present
111 bitvec_write_field(dest, &wp,alpha,4); // ALPHA
112 } else {
113 bitvec_write_field(dest, &wp,0x0,1); // ALPHA = not present
114 }
115 bitvec_write_field(dest, &wp,gamma,5); // GAMMA power control parameter
116 bitvec_write_field(dest, &wp,polling,1); // Polling Bit
117 bitvec_write_field(dest, &wp, ta_valid, 1); // N. B: NOT related to TAI!
118 write_tai(dest, wp, ta_idx);
Jacob Erlbeck18831c32016-02-01 15:23:35 +0100119 if (polling) {
Neels Hofmeyr39f84582018-02-27 22:41:07 +0100120 bitvec_write_field(dest, &wp,0x1,1); // TBF Starting TIME present
121 bitvec_write_field(dest, &wp,(fn / (26 * 51)) % 32,5); // T1'
122 bitvec_write_field(dest, &wp,fn % 51,6); // T3
123 bitvec_write_field(dest, &wp,fn % 26,5); // T2
124 } else {
125 bitvec_write_field(dest, &wp,0x0,1); // TBF Starting TIME present
126 }
127 bitvec_write_field(dest, &wp,0x0,1); // P0 not present
128 // bitvec_write_field(dest, &wp,0x1,1); // P0 not present
129 // bitvec_write_field(dest, &wp,,0xb,4);
Jacob Erlbeckbe80c362016-02-01 16:39:52 +0100130 if (tbf->is_egprs_enabled()) {
Neels Hofmeyr39f84582018-02-27 22:41:07 +0100131 /* see GMS 44.018, 10.5.2.16 */
132 bitvec_write_field(dest, &wp, 1, 1); // "H"
133 write_ws(dest, &wp, tbf->window_size()); // EGPRS Window Size
134 bitvec_write_field(dest, &wp, 0x0, 2); // LINK_QUALITY_MEASUREMENT_MODE
135 bitvec_write_field(dest, &wp, 0, 1); // BEP_PERIOD2 not present
136 }
Jacob Erlbeck2647a332016-02-01 16:13:38 +0100137
138 return 0;
Jacob Erlbeck18831c32016-02-01 15:23:35 +0100139}
140
Neels Hofmeyr782da2c2018-02-27 22:40:07 +0100141static int write_ia_rest_uplink(
142 gprs_rlcmac_ul_tbf *tbf,
143 bitvec * dest, unsigned& wp,
144 uint8_t usf, uint32_t fn,
145 uint8_t alpha, uint8_t gamma, int8_t ta_idx)
Jacob Erlbeck18831c32016-02-01 15:23:35 +0100146{
Neels Hofmeyr782da2c2018-02-27 22:40:07 +0100147 OSMO_ASSERT(!tbf || !tbf->is_egprs_enabled());
Jacob Erlbeckbe80c362016-02-01 16:39:52 +0100148
Neels Hofmeyr782da2c2018-02-27 22:40:07 +0100149 // GMS 04.08 10.5.2.37b 10.5.2.16
150 bitvec_write_field(dest, &wp, 3, 2); // "HH"
151 bitvec_write_field(dest, &wp, 0, 2); // "0" Packet Uplink Assignment
152 if (tbf == NULL) {
153 bitvec_write_field(dest, &wp, 0, 1); // Block Allocation : Single Block Allocation
154 if (alpha) {
155 bitvec_write_field(dest, &wp,0x1,1); // ALPHA = present
156 bitvec_write_field(dest, &wp,alpha,4); // ALPHA = present
157 } else
158 bitvec_write_field(dest, &wp,0x0,1); // ALPHA = not present
159 bitvec_write_field(dest, &wp,gamma,5); // GAMMA power control parameter
160 write_tai(dest, wp, ta_idx);
161 bitvec_write_field(dest, &wp, 1, 1); // TBF_STARTING_TIME_FLAG
162 bitvec_write_field(dest, &wp,(fn / (26 * 51)) % 32,5); // T1'
163 bitvec_write_field(dest, &wp,fn % 51,6); // T3
164 bitvec_write_field(dest, &wp,fn % 26,5); // T2
Jacob Erlbeck18831c32016-02-01 15:23:35 +0100165 } else {
Neels Hofmeyr782da2c2018-02-27 22:40:07 +0100166 bitvec_write_field(dest, &wp, 1, 1); // Block Allocation : Not Single Block Allocation
167 bitvec_write_field(dest, &wp, tbf->tfi(), 5); // TFI_ASSIGNMENT Temporary Flow Identity
168 bitvec_write_field(dest, &wp, 0, 1); // POLLING
169 bitvec_write_field(dest, &wp, 0, 1); // ALLOCATION_TYPE: dynamic
170 bitvec_write_field(dest, &wp, usf, 3); // USF
171 bitvec_write_field(dest, &wp, 0, 1); // USF_GRANULARITY
172 bitvec_write_field(dest, &wp, 0, 1); // "0" power control: Not Present
173 bitvec_write_field(dest, &wp, tbf->current_cs().to_num()-1, 2); // CHANNEL_CODING_COMMAND
174 bitvec_write_field(dest, &wp, 1, 1); // TLLI_BLOCK_CHANNEL_CODING
175 if (alpha) {
176 bitvec_write_field(dest, &wp,0x1,1); // ALPHA = present
177 bitvec_write_field(dest, &wp,alpha,4); // ALPHA
178 } else
179 bitvec_write_field(dest, &wp,0x0,1); // ALPHA = not present
180 bitvec_write_field(dest, &wp,gamma,5); // GAMMA power control parameter
181 /* note: there is no choise for TAI and no starting time */
182 bitvec_write_field(dest, &wp, 0, 1); // switch TIMING_ADVANCE_INDEX = off
183 bitvec_write_field(dest, &wp, 0, 1); // TBF_STARTING_TIME_FLAG
Jacob Erlbeck18831c32016-02-01 15:23:35 +0100184 }
Jacob Erlbeck2647a332016-02-01 16:13:38 +0100185 return 0;
Jacob Erlbeck18831c32016-02-01 15:23:35 +0100186}
187
Neels Hofmeyre6e48982018-02-27 22:42:07 +0100188static int write_ia_rest_egprs_uplink(
189 gprs_rlcmac_ul_tbf *tbf,
190 bitvec * dest, unsigned& wp,
191 uint8_t usf, uint32_t fn,
192 uint8_t alpha, uint8_t gamma, int8_t ta_idx,
193 enum ph_burst_type burst_type, uint16_t ra)
Jacob Erlbeckbe80c362016-02-01 16:39:52 +0100194{
Neels Hofmeyre6e48982018-02-27 22:42:07 +0100195 uint8_t extended_ra = 0;
bhargava465f5bb2016-09-02 16:50:43 +0530196
Neels Hofmeyre6e48982018-02-27 22:42:07 +0100197 extended_ra = (ra & 0x1F);
bhargava465f5bb2016-09-02 16:50:43 +0530198
Neels Hofmeyre6e48982018-02-27 22:42:07 +0100199 bitvec_write_field(dest, &wp, 1, 2); /* LH */
200 bitvec_write_field(dest, &wp, 0, 2); /* 0 EGPRS Uplink Assignment */
201 bitvec_write_field(dest, &wp, extended_ra, 5); /* Extended RA */
202 bitvec_write_field(dest, &wp, 0, 1); /* Access technology Request */
bhargava465f5bb2016-09-02 16:50:43 +0530203
Neels Hofmeyre6e48982018-02-27 22:42:07 +0100204 if (tbf == NULL) {
bhargava465f5bb2016-09-02 16:50:43 +0530205
Neels Hofmeyre6e48982018-02-27 22:42:07 +0100206 bitvec_write_field(dest, &wp, 0, 1); /* multiblock allocation */
bhargava465f5bb2016-09-02 16:50:43 +0530207
Neels Hofmeyre6e48982018-02-27 22:42:07 +0100208 if (alpha) {
209 bitvec_write_field(dest, &wp, 0x1, 1); /* ALPHA =yes */
210 bitvec_write_field(dest, &wp, alpha, 4); /* ALPHA */
211 } else {
212 bitvec_write_field(dest, &wp, 0x0, 1); /* ALPHA = no */
213 }
bhargava465f5bb2016-09-02 16:50:43 +0530214
Neels Hofmeyre6e48982018-02-27 22:42:07 +0100215 bitvec_write_field(dest, &wp, gamma, 5); /* GAMMA power contrl */
216 bitvec_write_field(dest, &wp, (fn / (26 * 51)) % 32, 5);/* T1' */
217 bitvec_write_field(dest, &wp, fn % 51, 6); /* T3 */
218 bitvec_write_field(dest, &wp, fn % 26, 5); /* T2 */
219 bitvec_write_field(dest, &wp, 0, 2); /* Radio block allocation */
bhargava465f5bb2016-09-02 16:50:43 +0530220
Neels Hofmeyre6e48982018-02-27 22:42:07 +0100221 bitvec_write_field(dest, &wp, 0, 1);
bhargava465f5bb2016-09-02 16:50:43 +0530222
223 } else {
Neels Hofmeyre6e48982018-02-27 22:42:07 +0100224 bitvec_write_field(dest, &wp, 1, 1); /* single block alloc */
225 bitvec_write_field(dest, &wp, tbf->tfi(), 5);/* TFI assignment */
226 bitvec_write_field(dest, &wp, 0, 1); /* polling bit */
227 bitvec_write_field(dest, &wp, 0, 1); /* constant */
228 bitvec_write_field(dest, &wp, usf, 3); /* USF bit */
229 bitvec_write_field(dest, &wp, 0, 1); /* USF granularity */
230 bitvec_write_field(dest, &wp, 0, 1); /* P0 */
231 /* MCS */
232 bitvec_write_field(dest, &wp, tbf->current_cs().to_num()-1, 4);
233 /* tlli channel block */
234 bitvec_write_field(dest, &wp, tbf->tlli(), 1);
235 bitvec_write_field(dest, &wp, 0, 1); /* BEP period present */
236 bitvec_write_field(dest, &wp, 0, 1); /* resegmentation */
237 write_ws(dest, &wp, tbf->window_size()); /* EGPRS window size */
bhargava465f5bb2016-09-02 16:50:43 +0530238
Neels Hofmeyre6e48982018-02-27 22:42:07 +0100239 if (alpha) {
240 bitvec_write_field(dest, &wp, 0x1, 1); /* ALPHA =yes */
241 bitvec_write_field(dest, &wp, alpha, 4); /* ALPHA */
242 } else {
243 bitvec_write_field(dest, &wp, 0x0, 1); /* ALPHA = no */
244 }
bhargava465f5bb2016-09-02 16:50:43 +0530245
Neels Hofmeyre6e48982018-02-27 22:42:07 +0100246 bitvec_write_field(dest, &wp, gamma, 5); /* GAMMA power contrl */
247 bitvec_write_field(dest, &wp, 0, 1); /* TIMING_ADVANCE_INDEX */
248 bitvec_write_field(dest, &wp, 0, 1); /* TBF_STARTING_TIME_FLAG */
249 bitvec_write_field(dest, &wp, 0, 1); /* NULL */
bhargava465f5bb2016-09-02 16:50:43 +0530250 }
251
252 return 0;
Jacob Erlbeckbe80c362016-02-01 16:39:52 +0100253}
254
Jacob Erlbeck18831c32016-02-01 15:23:35 +0100255/*
aravind sirsikarc0c3afd2016-11-09 16:27:00 +0530256 * Immediate assignment reject, sent on the CCCH/AGCH
257 * see GSM 44.018, 9.1.20 + 10.5.2.30
258 */
259int Encoding::write_immediate_assignment_reject(
260 bitvec *dest, uint16_t ra,
261 uint32_t ref_fn,
262 enum ph_burst_type burst_type)
263{
264 unsigned wp = 0;
265 int plen;
266 int i;
267
Alexander Couzensccde5c92017-02-04 03:10:08 +0100268 bitvec_write_field(dest, &wp, 0x0, 4); // Skip Indicator
269 bitvec_write_field(dest, &wp, 0x6, 4); // Protocol Discriminator
270 bitvec_write_field(dest, &wp, 0x3A, 8); // Immediate Assign Message Type
aravind sirsikarc0c3afd2016-11-09 16:27:00 +0530271
272 // feature indicator
Alexander Couzensccde5c92017-02-04 03:10:08 +0100273 bitvec_write_field(dest, &wp, 0x0, 1); // spare
274 bitvec_write_field(dest, &wp, 0x0, 1); // spare
275 bitvec_write_field(dest, &wp, 0x0, 1); // no cs
276 bitvec_write_field(dest, &wp, 0x1, 1); // implicit detach for PS
aravind sirsikarc0c3afd2016-11-09 16:27:00 +0530277
Alexander Couzensccde5c92017-02-04 03:10:08 +0100278 bitvec_write_field(dest, &wp, 0x0, 4); // Page Mode
aravind sirsikarc0c3afd2016-11-09 16:27:00 +0530279 /*
280 * 9.1.20.2 of 44.018 version 11.7.0 Release 11
281 * Filling of the message
282 * If necessary the request reference information element and the
283 * wait indication information element should be duplicated to
284 * fill the message.
285 * TODO: group rejection for multiple MS
286 */
287 for (i = 0; i < 4; i++) {
288 //10.5.2.30 Request Reference
289 if (((burst_type == GSM_L1_BURST_TYPE_ACCESS_1) ||
290 (burst_type == GSM_L1_BURST_TYPE_ACCESS_2))) {
291 //9.1.20.2a of 44.018 version 11.7.0 Release 11
Alexander Couzensccde5c92017-02-04 03:10:08 +0100292 bitvec_write_field(dest, &wp, 0x7f, 8); /* RACH value */
aravind sirsikarc0c3afd2016-11-09 16:27:00 +0530293 } else {
Alexander Couzensccde5c92017-02-04 03:10:08 +0100294 bitvec_write_field(dest, &wp, ra, 8); /* RACH value */
aravind sirsikarc0c3afd2016-11-09 16:27:00 +0530295 }
296
Alexander Couzensccde5c92017-02-04 03:10:08 +0100297 bitvec_write_field(dest, &wp,
aravind sirsikarc0c3afd2016-11-09 16:27:00 +0530298 (ref_fn / (26 * 51)) % 32, 5); // T1'
Alexander Couzensccde5c92017-02-04 03:10:08 +0100299 bitvec_write_field(dest, &wp, ref_fn % 51, 6); // T3
300 bitvec_write_field(dest, &wp, ref_fn % 26, 5); // T2
aravind sirsikarc0c3afd2016-11-09 16:27:00 +0530301
302 /* TODO: Make it configurable */
Alexander Couzensccde5c92017-02-04 03:10:08 +0100303 bitvec_write_field(dest, &wp, 20, 8); //Wait Indication 1
aravind sirsikarc0c3afd2016-11-09 16:27:00 +0530304 }
305
306 plen = wp / 8;
307
308 if ((wp % 8)) {
309 LOGP(DRLCMACUL, LOGL_ERROR, "Length of IMM.ASS.Rej without"
310 "rest octets is not multiple of 8 bits, PLEASE FIX!\n");
311 return -1;
312 }
313
314 // Extended RA
315 else if (((burst_type == GSM_L1_BURST_TYPE_ACCESS_1) ||
316 (burst_type == GSM_L1_BURST_TYPE_ACCESS_2))) {
317 //9.1.20.2a of 44.018 version 11.7.0 Release 11
318 uint8_t extended_ra = 0;
319
320 extended_ra = (ra & 0x1F);
Alexander Couzensccde5c92017-02-04 03:10:08 +0100321 bitvec_write_field(dest, &wp, 0x1, 1);
322 bitvec_write_field(dest, &wp, extended_ra, 5); /* Extended RA */
aravind sirsikarc0c3afd2016-11-09 16:27:00 +0530323 } else {
Alexander Couzensccde5c92017-02-04 03:10:08 +0100324 bitvec_write_field(dest, &wp, 0x0, 1);
aravind sirsikarc0c3afd2016-11-09 16:27:00 +0530325 }
Alexander Couzensccde5c92017-02-04 03:10:08 +0100326 bitvec_write_field(dest, &wp, 0x0, 1);
327 bitvec_write_field(dest, &wp, 0x0, 1);
328 bitvec_write_field(dest, &wp, 0x0, 1);
aravind sirsikarc0c3afd2016-11-09 16:27:00 +0530329
330 return plen;
331}
332
Max0a8fae82017-03-08 18:53:30 +0100333static inline void log_alert_exit(const char * error)
334{
335 LOGP(DRLCMACUL, LOGL_ERROR, error);
336 pcu_tx_txt_ind(PCU_OML_ALERT, error);
337 exit(1);
338}
339
aravind sirsikarc0c3afd2016-11-09 16:27:00 +0530340/*
Jacob Erlbeck18831c32016-02-01 15:23:35 +0100341 * Immediate assignment, sent on the CCCH/AGCH
342 * see GSM 04.08, 9.1.18 and GSM 44.018, 9.1.18 + 10.5.2.16
343 */
Holger Hans Peter Freyther63f29d62013-10-19 19:04:03 +0200344int Encoding::write_immediate_assignment(
Jacob Erlbeck2647a332016-02-01 16:13:38 +0100345 struct gprs_rlcmac_tbf *tbf,
bhargava465f5bb2016-09-02 16:50:43 +0530346 bitvec * dest, uint8_t downlink, uint16_t ra,
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200347 uint32_t ref_fn, uint8_t ta, uint16_t arfcn, uint8_t ts, uint8_t tsc,
Jacob Erlbeck2647a332016-02-01 16:13:38 +0100348 uint8_t usf, uint8_t polling, uint32_t fn, uint8_t alpha,
bhargava465f5bb2016-09-02 16:50:43 +0530349 uint8_t gamma, int8_t ta_idx, enum ph_burst_type burst_type, uint8_t sb)
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200350{
351 unsigned wp = 0;
Jacob Erlbeck2647a332016-02-01 16:13:38 +0100352 int plen;
353 int rc;
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200354
Alexander Couzensccde5c92017-02-04 03:10:08 +0100355 bitvec_write_field(dest, &wp,0x0,4); // Skip Indicator
356 bitvec_write_field(dest, &wp,0x6,4); // Protocol Discriminator
357 bitvec_write_field(dest, &wp,0x3F,8); // Immediate Assignment Message Type
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200358
359 // 10.5.2.25b Dedicated mode or TBF
Alexander Couzensccde5c92017-02-04 03:10:08 +0100360 bitvec_write_field(dest, &wp,0x0,1); // spare
361 bitvec_write_field(dest, &wp,0x0,1); // TMA : Two-message assignment: No meaning
362 bitvec_write_field(dest, &wp,downlink,1); // Downlink : Downlink assignment to mobile in packet idle mode
363 bitvec_write_field(dest, &wp,0x1,1); // T/D : TBF or dedicated mode: this message assigns a Temporary Block Flow (TBF).
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200364
Alexander Couzensccde5c92017-02-04 03:10:08 +0100365 bitvec_write_field(dest, &wp,0x0,4); // Page Mode
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200366
367 // GSM 04.08 10.5.2.25a Packet Channel Description
Alexander Couzensccde5c92017-02-04 03:10:08 +0100368 bitvec_write_field(dest, &wp,0x1,5); // Channel type
369 bitvec_write_field(dest, &wp,ts,3); // TN
370 bitvec_write_field(dest, &wp,tsc,3); // TSC
371 bitvec_write_field(dest, &wp,0x0,3); // non-hopping RF channel configuraion
372 bitvec_write_field(dest, &wp,arfcn,10); // ARFCN
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200373
374 //10.5.2.30 Request Reference
bhargava465f5bb2016-09-02 16:50:43 +0530375 if (((burst_type == GSM_L1_BURST_TYPE_ACCESS_1) ||
376 (burst_type == GSM_L1_BURST_TYPE_ACCESS_2))) {
Alexander Couzensccde5c92017-02-04 03:10:08 +0100377 bitvec_write_field(dest, &wp, 0x7f, 8); /* RACH value */
bhargava465f5bb2016-09-02 16:50:43 +0530378 } else {
Alexander Couzensccde5c92017-02-04 03:10:08 +0100379 bitvec_write_field(dest, &wp, ra, 8); /* RACH value */
bhargava465f5bb2016-09-02 16:50:43 +0530380 }
381
Alexander Couzensccde5c92017-02-04 03:10:08 +0100382 bitvec_write_field(dest, &wp,(ref_fn / (26 * 51)) % 32,5); // T1'
383 bitvec_write_field(dest, &wp,ref_fn % 51,6); // T3
384 bitvec_write_field(dest, &wp,ref_fn % 26,5); // T2
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200385
386 // 10.5.2.40 Timing Advance
Alexander Couzensccde5c92017-02-04 03:10:08 +0100387 bitvec_write_field(dest, &wp,0x0,2); // spare
388 bitvec_write_field(dest, &wp,ta,6); // Timing Advance value
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200389
390 // No mobile allocation in non-hopping systems.
391 // A zero-length LV. Just write L=0.
Alexander Couzensccde5c92017-02-04 03:10:08 +0100392 bitvec_write_field(dest, &wp,0,8);
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200393
Max0a8fae82017-03-08 18:53:30 +0100394 if ((wp % 8))
395 log_alert_exit("Length of IMM.ASS without rest octets is not "
396 "multiple of 8 bits, PLEASE FIX!\n");
397
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200398 plen = wp / 8;
399
Neels Hofmeyr39f84582018-02-27 22:41:07 +0100400 if (downlink)
401 rc = write_ia_rest_downlink(as_dl_tbf(tbf), dest, wp,
402 polling, gsm48_ta_is_valid(ta), fn,
403 alpha, gamma, ta_idx);
404 else if (((burst_type == GSM_L1_BURST_TYPE_ACCESS_1) ||
Neels Hofmeyre6e48982018-02-27 22:42:07 +0100405 (burst_type == GSM_L1_BURST_TYPE_ACCESS_2)))
406 rc = write_ia_rest_egprs_uplink(as_ul_tbf(tbf), dest, wp,
407 usf, fn,
408 alpha, gamma, ta_idx, burst_type, ra);
409 else
Neels Hofmeyr782da2c2018-02-27 22:40:07 +0100410 rc = write_ia_rest_uplink(as_ul_tbf(tbf), dest, wp,
411 usf, fn,
412 alpha, gamma, ta_idx);
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200413
Jacob Erlbeck2647a332016-02-01 16:13:38 +0100414 if (rc < 0) {
415 LOGP(DRLCMAC, LOGL_ERROR,
416 "Failed to create IMMEDIATE ASSIGMENT (%s) for %s\n",
417 downlink ? "downlink" : "uplink",
418 tbf ? tbf->name() : "single block allocation");
419 return rc;
420 }
421
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200422 return plen;
423}
424
425/* generate uplink assignment */
Holger Hans Peter Freyther63f29d62013-10-19 19:04:03 +0200426void Encoding::write_packet_uplink_assignment(
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200427 struct gprs_rlcmac_bts *bts,
428 bitvec * dest, uint8_t old_tfi,
429 uint8_t old_downlink, uint32_t tlli, uint8_t use_tlli,
Jacob Erlbeckf2694b72016-01-26 21:46:26 +0100430 struct gprs_rlcmac_ul_tbf *tbf, uint8_t poll, uint8_t rrbp, uint8_t alpha,
Jacob Erlbeck76d767c2015-09-28 18:54:32 +0200431 uint8_t gamma, int8_t ta_idx, int8_t use_egprs)
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200432{
433 // TODO We should use our implementation of encode RLC/MAC Control messages.
434 unsigned wp = 0;
435 uint8_t ts;
Maxae483812016-07-28 12:03:08 +0200436 /* timeslot assigned for the Continuous Timing Advance procedure */
437 uint8_t ta_ts = 0; /* FIXME: supply it as parameter from caller */
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200438
Alexander Couzensccde5c92017-02-04 03:10:08 +0100439 bitvec_write_field(dest, &wp,0x1,2); // Payload Type
440 bitvec_write_field(dest, &wp,0x0,2); // Uplink block with TDMA framenumber (N+13)
441 bitvec_write_field(dest, &wp,poll,1); // Suppl/Polling Bit
442 bitvec_write_field(dest, &wp,0x0,3); // Uplink state flag
443 bitvec_write_field(dest, &wp,0xa,6); // MESSAGE TYPE
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200444
Alexander Couzensccde5c92017-02-04 03:10:08 +0100445 bitvec_write_field(dest, &wp,0x0,2); // Page Mode
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200446
Alexander Couzensccde5c92017-02-04 03:10:08 +0100447 bitvec_write_field(dest, &wp,0x0,1); // switch PERSIST_LEVEL: off
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200448 if (use_tlli) {
Alexander Couzensccde5c92017-02-04 03:10:08 +0100449 bitvec_write_field(dest, &wp,0x2,2); // switch TLLI : on
450 bitvec_write_field(dest, &wp,tlli,32); // TLLI
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200451 } else {
Alexander Couzensccde5c92017-02-04 03:10:08 +0100452 bitvec_write_field(dest, &wp,0x0,1); // switch TFI : on
453 bitvec_write_field(dest, &wp,old_downlink,1); // 0=UPLINK TFI, 1=DL TFI
454 bitvec_write_field(dest, &wp,old_tfi,5); // TFI
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200455 }
456
Jacob Erlbeck76d767c2015-09-28 18:54:32 +0200457 if (!use_egprs) {
Alexander Couzensccde5c92017-02-04 03:10:08 +0100458 bitvec_write_field(dest, &wp,0x0,1); // Message escape
459 bitvec_write_field(dest, &wp,tbf->current_cs().to_num()-1, 2); // CHANNEL_CODING_COMMAND
460 bitvec_write_field(dest, &wp,0x1,1); // TLLI_BLOCK_CHANNEL_CODING
Maxae483812016-07-28 12:03:08 +0200461 write_ta_ie(dest, wp,tbf->ta(), ta_idx, ta_ts);
Jacob Erlbeck76d767c2015-09-28 18:54:32 +0200462 } else { /* EPGRS */
Alexander Couzensccde5c92017-02-04 03:10:08 +0100463 bitvec_write_field(dest, &wp,0x1,1); // Message escape
464 bitvec_write_field(dest, &wp,0x0,2); // EGPRS message contents
465 bitvec_write_field(dest, &wp,0x0,1); // No CONTENTION_RESOLUTION_TLLI
466 bitvec_write_field(dest, &wp,0x0,1); // No COMPACT reduced MA
467 bitvec_write_field(dest, &wp,tbf->current_cs().to_num()-1, 4); // EGPRS Modulation and Coding IE
Aravind Sirsikar505a86d2016-07-26 18:26:21 +0530468 /* 0: no RESEGMENT, 1: Segmentation*/
Alexander Couzensccde5c92017-02-04 03:10:08 +0100469 bitvec_write_field(dest, &wp, 0x1, 1);
Maxa4f570f2017-12-15 11:21:57 +0100470 write_ws(dest, &wp, tbf->window_size()); // EGPRS Window Size
Alexander Couzensccde5c92017-02-04 03:10:08 +0100471 bitvec_write_field(dest, &wp,0x0,1); // No Access Technologies Request
472 bitvec_write_field(dest, &wp,0x0,1); // No ARAC RETRANSMISSION REQUEST
473 bitvec_write_field(dest, &wp,0x1,1); // TLLI_BLOCK_CHANNEL_CODING
474 bitvec_write_field(dest, &wp,0x0,1); // No BEP_PERIOD2
Maxae483812016-07-28 12:03:08 +0200475 write_ta_ie(dest, wp,tbf->ta(), ta_idx, ta_ts);
Alexander Couzensccde5c92017-02-04 03:10:08 +0100476 bitvec_write_field(dest, &wp,0x0,1); // No Packet Extended Timing Advance
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200477 }
478
479#if 1
Alexander Couzensccde5c92017-02-04 03:10:08 +0100480 bitvec_write_field(dest, &wp,0x1,1); // Frequency Parameters information elements = present
481 bitvec_write_field(dest, &wp,tbf->tsc(),3); // Training Sequence Code (TSC)
482 bitvec_write_field(dest, &wp,0x0,2); // ARFCN = present
483 bitvec_write_field(dest, &wp,tbf->trx->arfcn,10); // ARFCN
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200484#else
Alexander Couzensccde5c92017-02-04 03:10:08 +0100485 bitvec_write_field(dest, &wp,0x0,1); // Frequency Parameters = off
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200486#endif
487
Alexander Couzensccde5c92017-02-04 03:10:08 +0100488 bitvec_write_field(dest, &wp,0x1,2); // Dynamic Allocation
Jacob Erlbeckedfd7e32015-11-17 16:30:58 +0100489
Alexander Couzensccde5c92017-02-04 03:10:08 +0100490 bitvec_write_field(dest, &wp,0x0,1); // Extended Dynamic Allocation = off
491 bitvec_write_field(dest, &wp,0x0,1); // P0 = off
Jacob Erlbeckedfd7e32015-11-17 16:30:58 +0100492
Alexander Couzensccde5c92017-02-04 03:10:08 +0100493 bitvec_write_field(dest, &wp,0x0,1); // USF_GRANULARITY
494 bitvec_write_field(dest, &wp,0x1,1); // switch TFI : on
495 bitvec_write_field(dest, &wp,tbf->tfi(),5);// TFI
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200496
Alexander Couzensccde5c92017-02-04 03:10:08 +0100497 bitvec_write_field(dest, &wp,0x0,1); //
498 bitvec_write_field(dest, &wp,0x0,1); // TBF Starting Time = off
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200499 if (alpha || gamma) {
Alexander Couzensccde5c92017-02-04 03:10:08 +0100500 bitvec_write_field(dest, &wp,0x1,1); // Timeslot Allocation with Power Control
501 bitvec_write_field(dest, &wp,alpha,4); // ALPHA
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200502 } else
Alexander Couzensccde5c92017-02-04 03:10:08 +0100503 bitvec_write_field(dest, &wp,0x0,1); // Timeslot Allocation
Jacob Erlbeckedfd7e32015-11-17 16:30:58 +0100504
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200505 for (ts = 0; ts < 8; ts++) {
506 if (tbf->pdch[ts]) {
Alexander Couzensccde5c92017-02-04 03:10:08 +0100507 bitvec_write_field(dest, &wp,0x1,1); // USF_TN(i): on
508 bitvec_write_field(dest, &wp,tbf->m_usf[ts],3); // USF_TN(i)
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200509 if (alpha || gamma)
Alexander Couzensccde5c92017-02-04 03:10:08 +0100510 bitvec_write_field(dest, &wp,gamma,5); // GAMMA power control parameter
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200511 } else
Alexander Couzensccde5c92017-02-04 03:10:08 +0100512 bitvec_write_field(dest, &wp,0x0,1); // USF_TN(i): off
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200513 }
Alexander Couzensccde5c92017-02-04 03:10:08 +0100514 // bitvec_write_field(dest, &wp,0x0,1); // Measurement Mapping struct not present
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200515}
516
517
518/* generate downlink assignment */
Jacob Erlbeck166c9fc2016-01-07 16:04:29 +0100519void Encoding::write_packet_downlink_assignment(RlcMacDownlink_t * block,
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100520 bool old_tfi_is_valid, uint8_t old_tfi, uint8_t old_downlink,
Maxa4f570f2017-12-15 11:21:57 +0100521 struct gprs_rlcmac_dl_tbf *tbf, uint8_t poll, uint8_t rrbp,
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100522 uint8_t alpha, uint8_t gamma, int8_t ta_idx,
Jacob Erlbeckf2694b72016-01-26 21:46:26 +0100523 uint8_t ta_ts, bool use_egprs)
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200524{
525 // Packet downlink assignment TS 44.060 11.2.7
526
Jacob Erlbeck166c9fc2016-01-07 16:04:29 +0100527 PDA_AdditionsR99_t *pda_r99;
528
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200529 uint8_t tn;
530
531 block->PAYLOAD_TYPE = 0x1; // RLC/MAC control block that does not include the optional octets of the RLC/MAC control header
Jacob Erlbeckf2694b72016-01-26 21:46:26 +0100532 block->RRBP = rrbp; // 0: N+13
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200533 block->SP = poll; // RRBP field is valid
534 block->USF = 0x0; // Uplink state flag
535
536 block->u.Packet_Downlink_Assignment.MESSAGE_TYPE = 0x2; // Packet Downlink Assignment
537 block->u.Packet_Downlink_Assignment.PAGE_MODE = 0x0; // Normal Paging
538
539 block->u.Packet_Downlink_Assignment.Exist_PERSISTENCE_LEVEL = 0x0; // PERSISTENCE_LEVEL: off
540
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100541 if (old_tfi_is_valid) {
542 block->u.Packet_Downlink_Assignment.ID.UnionType = 0x0; // TFI = on
543 block->u.Packet_Downlink_Assignment.ID.u.Global_TFI.UnionType = old_downlink; // 0=UPLINK TFI, 1=DL TFI
544 block->u.Packet_Downlink_Assignment.ID.u.Global_TFI.u.UPLINK_TFI = old_tfi; // TFI
545 } else {
546 block->u.Packet_Downlink_Assignment.ID.UnionType = 0x1; // TLLI
547 block->u.Packet_Downlink_Assignment.ID.u.TLLI = tbf->tlli();
548 }
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200549
550 block->u.Packet_Downlink_Assignment.MAC_MODE = 0x0; // Dynamic Allocation
551 block->u.Packet_Downlink_Assignment.RLC_MODE = 0x0; // RLC acknowledged mode
Daniel Willmann73191a42014-05-30 17:58:00 +0200552 block->u.Packet_Downlink_Assignment.CONTROL_ACK = tbf->was_releasing; // NW establishes no new DL TBF for the MS with running timer T3192
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200553 block->u.Packet_Downlink_Assignment.TIMESLOT_ALLOCATION = 0; // timeslot(s)
554 for (tn = 0; tn < 8; tn++) {
555 if (tbf->pdch[tn])
556 block->u.Packet_Downlink_Assignment.TIMESLOT_ALLOCATION |= 0x80 >> tn; // timeslot(s)
557 }
558
559 block->u.Packet_Downlink_Assignment.Packet_Timing_Advance.Exist_TIMING_ADVANCE_VALUE = 0x1; // TIMING_ADVANCE_VALUE = on
Jacob Erlbeck9200ce62015-05-22 17:48:04 +0200560 block->u.Packet_Downlink_Assignment.Packet_Timing_Advance.TIMING_ADVANCE_VALUE = tbf->ta(); // TIMING_ADVANCE_VALUE
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200561 if (ta_idx < 0) {
562 block->u.Packet_Downlink_Assignment.Packet_Timing_Advance.Exist_IndexAndtimeSlot = 0x0; // TIMING_ADVANCE_INDEX = off
563 } else {
564 block->u.Packet_Downlink_Assignment.Packet_Timing_Advance.Exist_IndexAndtimeSlot = 0x1; // TIMING_ADVANCE_INDEX = on
565 block->u.Packet_Downlink_Assignment.Packet_Timing_Advance.TIMING_ADVANCE_INDEX = ta_idx; // TIMING_ADVANCE_INDEX
566 block->u.Packet_Downlink_Assignment.Packet_Timing_Advance.TIMING_ADVANCE_TIMESLOT_NUMBER = ta_ts; // TIMING_ADVANCE_TS
567 }
568
569 block->u.Packet_Downlink_Assignment.Exist_P0_and_BTS_PWR_CTRL_MODE = 0x0; // POWER CONTROL = off
570
571 block->u.Packet_Downlink_Assignment.Exist_Frequency_Parameters = 0x1; // Frequency Parameters = on
Holger Hans Peter Freyther8f399de2013-12-25 20:22:35 +0100572 block->u.Packet_Downlink_Assignment.Frequency_Parameters.TSC = tbf->tsc(); // Training Sequence Code (TSC)
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200573 block->u.Packet_Downlink_Assignment.Frequency_Parameters.UnionType = 0x0; // ARFCN = on
Holger Hans Peter Freytherfc498c92013-10-27 13:38:54 +0100574 block->u.Packet_Downlink_Assignment.Frequency_Parameters.u.ARFCN = tbf->trx->arfcn; // ARFCN
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200575
576 block->u.Packet_Downlink_Assignment.Exist_DOWNLINK_TFI_ASSIGNMENT = 0x1; // DOWNLINK TFI ASSIGNMENT = on
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100577 block->u.Packet_Downlink_Assignment.DOWNLINK_TFI_ASSIGNMENT = tbf->tfi(); // TFI
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200578
579 block->u.Packet_Downlink_Assignment.Exist_Power_Control_Parameters = 0x1; // Power Control Parameters = on
580 block->u.Packet_Downlink_Assignment.Power_Control_Parameters.ALPHA = alpha; // ALPHA
581
582 for (tn = 0; tn < 8; tn++)
583 {
584 if (tbf->pdch[tn])
585 {
586 block->u.Packet_Downlink_Assignment.Power_Control_Parameters.Slot[tn].Exist = 0x1; // Slot[i] = on
587 block->u.Packet_Downlink_Assignment.Power_Control_Parameters.Slot[tn].GAMMA_TN = gamma; // GAMMA_TN
588 }
589 else
590 {
591 block->u.Packet_Downlink_Assignment.Power_Control_Parameters.Slot[tn].Exist = 0x0; // Slot[i] = off
592 }
593 }
594
595 block->u.Packet_Downlink_Assignment.Exist_TBF_Starting_Time = 0x0; // TBF Starting TIME = off
596 block->u.Packet_Downlink_Assignment.Exist_Measurement_Mapping = 0x0; // Measurement_Mapping = off
Jacob Erlbeck166c9fc2016-01-07 16:04:29 +0100597 if (!use_egprs) {
598 block->u.Packet_Downlink_Assignment.Exist_AdditionsR99 = 0x0; // AdditionsR99 = off
599 return;
600 }
Jacob Erlbeck36df7742016-01-19 15:53:30 +0100601
Jacob Erlbeck166c9fc2016-01-07 16:04:29 +0100602 block->u.Packet_Downlink_Assignment.Exist_AdditionsR99 = 0x1; // AdditionsR99 = on
603 pda_r99 = &block->u.Packet_Downlink_Assignment.AdditionsR99;
604 pda_r99->Exist_EGPRS_Params = 1;
Maxa4f570f2017-12-15 11:21:57 +0100605 pda_r99->EGPRS_WindowSize = enc_ws(tbf->window_size()); /* see TS 44.060, table 12.5.2.1 */
Jacob Erlbeck166c9fc2016-01-07 16:04:29 +0100606 pda_r99->LINK_QUALITY_MEASUREMENT_MODE = 0x0; /* no meas, see TS 44.060, table 11.2.7.2 */
607 pda_r99->Exist_BEP_PERIOD2 = 0; /* No extra EGPRS BEP PERIOD */
608 pda_r99->Exist_Packet_Extended_Timing_Advance = 0;
609 pda_r99->Exist_COMPACT_ReducedMA = 0;
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200610}
611
Stefan Sperling513c9bc2018-05-02 14:53:16 +0200612/* Generate paging request. See 44.018, sections 10 and 9.1.22 */
Holger Hans Peter Freyther63f29d62013-10-19 19:04:03 +0200613int Encoding::write_paging_request(bitvec * dest, uint8_t *ptmsi, uint16_t ptmsi_len)
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200614{
615 unsigned wp = 0;
616 int plen;
617
Alexander Couzensccde5c92017-02-04 03:10:08 +0100618 bitvec_write_field(dest, &wp,0x0,4); // Skip Indicator
619 bitvec_write_field(dest, &wp,0x6,4); // Protocol Discriminator
Stefan Sperling513c9bc2018-05-02 14:53:16 +0200620 bitvec_write_field(dest, &wp,0x21,8); // Paging Request Message Type 1
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200621
Alexander Couzensccde5c92017-02-04 03:10:08 +0100622 bitvec_write_field(dest, &wp,0x0,4); // Page Mode
623 bitvec_write_field(dest, &wp,0x0,4); // Channel Needed
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200624
625 // Mobile Identity
Alexander Couzensccde5c92017-02-04 03:10:08 +0100626 bitvec_write_field(dest, &wp,ptmsi_len+1,8); // Mobile Identity length
627 bitvec_write_field(dest, &wp,0xf,4); // unused
628 bitvec_write_field(dest, &wp,0x4,4); // PTMSI type
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200629 for (int i = 0; i < ptmsi_len; i++)
630 {
Alexander Couzensccde5c92017-02-04 03:10:08 +0100631 bitvec_write_field(dest, &wp,ptmsi[i],8); // PTMSI
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200632 }
Max0a8fae82017-03-08 18:53:30 +0100633
634 if ((wp % 8))
635 log_alert_exit("Length of PAG.REQ without rest octets is not "
636 "multiple of 8 bits, PLEASE FIX!\n");
637
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200638 plen = wp / 8;
Stefan Sperling513c9bc2018-05-02 14:53:16 +0200639 bitvec_write_field(dest, &wp,0x0,1); // "L" Notification List Number; NLN(PCH) = off
Alexander Couzensccde5c92017-02-04 03:10:08 +0100640 bitvec_write_field(dest, &wp,0x0,1); // "L" Priority1 = off
641 bitvec_write_field(dest, &wp,0x1,1); // "L" Priority2 = off
642 bitvec_write_field(dest, &wp,0x0,1); // "L" Group Call information = off
643 bitvec_write_field(dest, &wp,0x0,1); // "H" Packet Page Indication 1 = packet paging procedure
644 bitvec_write_field(dest, &wp,0x1,1); // "H" Packet Page Indication 2 = packet paging procedure
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200645
646 return plen;
647}
648
Daniel Willmann5241c1a2013-12-11 14:35:29 +0100649/**
650 * The index of the array show_rbb is the bit position inside the rbb
651 * (show_rbb[63] relates to BSN ssn-1)
652 */
653void Encoding::encode_rbb(const char *show_rbb, uint8_t *rbb)
654{
655 uint8_t rbb_byte = 0;
656
657 // RECEIVE_BLOCK_BITMAP
658 for (int i = 0; i < 64; i++) {
659 /* Set bit at the appropriate position (see 3GPP TS 04.60 9.1.8.1) */
660 if (show_rbb[i] == 'R')
661 rbb_byte |= 1<< (7-(i%8));
662
663 if((i%8) == 7) {
664 rbb[i/8] = rbb_byte;
665 rbb_byte = 0;
666 }
667 }
668}
669
Jacob Erlbeck37005a12015-12-22 14:58:34 +0100670static void write_packet_ack_nack_desc_gprs(
671 struct gprs_rlcmac_bts *bts, bitvec * dest, unsigned& wp,
672 gprs_rlc_ul_window *window, bool is_final)
673{
674 char rbb[65];
675
676 window->update_rbb(rbb);
677
678 rbb[64] = 0;
679 LOGP(DRLCMACUL, LOGL_DEBUG, "- V(N): \"%s\" R=Received "
680 "I=Invalid\n", rbb);
681
Alexander Couzensccde5c92017-02-04 03:10:08 +0100682 bitvec_write_field(dest, &wp, is_final, 1); // FINAL_ACK_INDICATION
683 bitvec_write_field(dest, &wp, window->ssn(), 7); // STARTING_SEQUENCE_NUMBER
Jacob Erlbeck37005a12015-12-22 14:58:34 +0100684
685 for (int i = 0; i < 64; i++) {
686 /* Set bit at the appropriate position (see 3GPP TS 04.60 9.1.8.1) */
687 bool is_ack = (rbb[i] == 'R');
Alexander Couzensccde5c92017-02-04 03:10:08 +0100688 bitvec_write_field(dest, &wp, is_ack, 1);
Jacob Erlbeck37005a12015-12-22 14:58:34 +0100689 }
690}
691
692static void write_packet_uplink_ack_gprs(
693 struct gprs_rlcmac_bts *bts, bitvec * dest, unsigned& wp,
694 struct gprs_rlcmac_ul_tbf *tbf, bool is_final)
695{
696
Alexander Couzensccde5c92017-02-04 03:10:08 +0100697 bitvec_write_field(dest, &wp, tbf->current_cs().to_num() - 1, 2); // CHANNEL_CODING_COMMAND
Maxea98b7d2018-01-04 15:13:27 +0100698 write_packet_ack_nack_desc_gprs(bts, dest, wp, tbf->window(), is_final);
Jacob Erlbeck37005a12015-12-22 14:58:34 +0100699
Alexander Couzensccde5c92017-02-04 03:10:08 +0100700 bitvec_write_field(dest, &wp, 1, 1); // 1: have CONTENTION_RESOLUTION_TLLI
701 bitvec_write_field(dest, &wp, tbf->tlli(), 32); // CONTENTION_RESOLUTION_TLLI
Jacob Erlbeck37005a12015-12-22 14:58:34 +0100702
Alexander Couzensccde5c92017-02-04 03:10:08 +0100703 bitvec_write_field(dest, &wp, 0, 1); // 0: don't have Packet Timing Advance
704 bitvec_write_field(dest, &wp, 0, 1); // 0: don't have Power Control Parameters
705 bitvec_write_field(dest, &wp, 0, 1); // 0: don't have Extension Bits
706 bitvec_write_field(dest, &wp, 0, 1); // fixed 0
707 bitvec_write_field(dest, &wp, 1, 1); // 1: have Additions R99
708 bitvec_write_field(dest, &wp, 0, 1); // 0: don't have Packet Extended Timing Advance
709 bitvec_write_field(dest, &wp, 1, 1); // TBF_EST (enabled)
710 bitvec_write_field(dest, &wp, 0, 1); // 0: don't have REL 5
Jacob Erlbeck37005a12015-12-22 14:58:34 +0100711};
712
713static void write_packet_ack_nack_desc_egprs(
714 struct gprs_rlcmac_bts *bts, bitvec * dest, unsigned& wp,
sivasankari8adfcd02017-01-16 15:41:21 +0530715 gprs_rlc_ul_window *window, bool is_final, unsigned& rest_bits)
Jacob Erlbeck37005a12015-12-22 14:58:34 +0100716{
sivasankari8adfcd02017-01-16 15:41:21 +0530717 unsigned int urbb_len = 0;
718 uint8_t crbb_len = 0;
719 uint8_t len;
Jacob Erlbeck37005a12015-12-22 14:58:34 +0100720 bool bow = true;
721 bool eow = true;
722 int ssn = window->mod_sns(window->v_q() + 1);
sivasankari8adfcd02017-01-16 15:41:21 +0530723 unsigned int num_blocks = window->mod_sns(window->v_r() - window->v_q());
Jacob Erlbeck37005a12015-12-22 14:58:34 +0100724 int esn_crbb = window->mod_sns(ssn - 1);
sivasankari8adfcd02017-01-16 15:41:21 +0530725 static uint8_t rbb[RLC_EGPRS_MAX_WS] = {'\0'};
726 uint8_t iter = 0;
Pravin Kumarvel06bdb352016-10-24 12:21:21 +0530727 int is_compressed = 0;
sivasankari8adfcd02017-01-16 15:41:21 +0530728 bool try_compression = false;
729 uint8_t ucmp_bmplen;
730 uint8_t crbb_bitmap[23] = {'\0'};
731 bitvec ucmp_vec;
732 bitvec crbb_vec;
733 uint8_t uclen_crbb = 0;
Pravin Kumarvel06bdb352016-10-24 12:21:21 +0530734 bool len_coded = true;
sivasankari8adfcd02017-01-16 15:41:21 +0530735 uint8_t crbb_start_clr_code;
Pravin Kumarvel06bdb352016-10-24 12:21:21 +0530736 uint8_t i;
sivasankari8adfcd02017-01-16 15:41:21 +0530737#if 0
738 /* static size of 16 bits*/
739 ..0. .... = ACKNACK: (Union)
740 Desc
741
742 ...0 .... = FINAL_ACK_INDICATION: False
743
744 .... 1... = BEGINNING_OF_WINDOW: 1
745
746 .... .1.. = END_OF_WINDOW: 1
747
748 .... ..10 0101 0001 1... .... = STARTING_SEQUENCE_NUMBER: 1187
749
750 .0.. .... = CRBB Exist: 0
751#endif
752 rest_bits -= 16;
Jacob Erlbeck37005a12015-12-22 14:58:34 +0100753
754 if (num_blocks > 0)
755 /* V(Q) is NACK and omitted -> SSN = V(Q) + 1 */
756 num_blocks -= 1;
757
758 if (num_blocks > window->ws())
759 num_blocks = window->ws();
sivasankari8adfcd02017-01-16 15:41:21 +0530760 /* Try Compression as number of blocks does not fit */
761 if (num_blocks > rest_bits) {
762 try_compression = true;
763 }
764 if (try_compression == true) {
765 ucmp_bmplen = window->update_egprs_rbb(rbb);
766 ucmp_vec.data = rbb;
767 ucmp_vec.cur_bit = ucmp_bmplen;
768 ucmp_vec.data_len = 127;
769 crbb_vec.data = crbb_bitmap;
770 crbb_vec.cur_bit = 0;
771 crbb_vec.data_len = 127;
772 LOGP(DRLCMACUL, LOGL_DEBUG,
773 "rest_bits=%d uncompressed len %d and uncompressed bitmap = %s\n",
774 rest_bits, ucmp_bmplen,
775 osmo_hexdump(ucmp_vec.data, (ucmp_bmplen+7)/8));
Jacob Erlbeck37005a12015-12-22 14:58:34 +0100776
sivasankari8adfcd02017-01-16 15:41:21 +0530777 is_compressed = egprs_compress::compress_rbb(&ucmp_vec, /* Uncompressed bitmap*/
778 &crbb_vec, /*Compressed bitmap vector */
779 &uclen_crbb,
780 (rest_bits - 16));/* CRBBlength:7 colourcode:1 dissector length:8*/
781 LOGP(DRLCMACUL, LOGL_DEBUG,
782 "the ucmp len=%d uclen_crbb=%d num_blocks=%d crbb length %d, "
783 "and the CRBB bitmap = %s\n",
784 ucmp_bmplen, uclen_crbb, num_blocks, crbb_vec.cur_bit,
785 osmo_hexdump(crbb_bitmap, (crbb_vec.cur_bit+7)/8));
786 crbb_len = crbb_vec.cur_bit;
787 }
788
789 if (is_compressed == 0) {
790 /* length field takes 8 bits*/
791 if (num_blocks > rest_bits - 8) {
Pravin Kumarvel06bdb352016-10-24 12:21:21 +0530792 eow = false;
sivasankari8adfcd02017-01-16 15:41:21 +0530793 urbb_len = rest_bits;
Pravin Kumarvel06bdb352016-10-24 12:21:21 +0530794 len_coded = false;
sivasankari8adfcd02017-01-16 15:41:21 +0530795 } else if (num_blocks == rest_bits) {
796 urbb_len = rest_bits;
Pravin Kumarvel06bdb352016-10-24 12:21:21 +0530797 len_coded = false;
Pravin Kumarvel06bdb352016-10-24 12:21:21 +0530798 } else
799 urbb_len = num_blocks;
sivasankari8adfcd02017-01-16 15:41:21 +0530800
Jacob Erlbeck37005a12015-12-22 14:58:34 +0100801 len = urbb_len + 15;
Pravin Kumarvel06bdb352016-10-24 12:21:21 +0530802 } else {
sivasankari8adfcd02017-01-16 15:41:21 +0530803 if (num_blocks > uclen_crbb) {
804 eow = false;
805 urbb_len = num_blocks - uclen_crbb;
806 }
807 /* Union bit takes 1 bit */
808 /* Other fields in descr of compresed bitmap takes 23 bits
809 * -8 = CRBB_STARTING_COLOR_CODE + CRBB_LENGTH */
810 if (urbb_len > (rest_bits - crbb_len - 8)) {
811 eow = false;
812 len_coded = false;
813 urbb_len = rest_bits - crbb_len - 8;
814 /* -16 = ACKNACK Dissector length + CRBB_STARTING_COLOR_CODE + CRBB_LENGTH */
815 } else if (urbb_len > (rest_bits - crbb_len - 16)) {
816 eow = false;
817 len_coded = false;
818 urbb_len = rest_bits - crbb_len - 16;
819 }
820 len = urbb_len + crbb_len + 23;
Pravin Kumarvel06bdb352016-10-24 12:21:21 +0530821 }
Jacob Erlbeck37005a12015-12-22 14:58:34 +0100822
823 /* EGPRS Ack/Nack Description IE */
Pravin Kumarvel06bdb352016-10-24 12:21:21 +0530824 if (len_coded == false) {
Alexander Couzensccde5c92017-02-04 03:10:08 +0100825 bitvec_write_field(dest, &wp, 0, 1); // 0: don't have length
Jacob Erlbeck37005a12015-12-22 14:58:34 +0100826 } else {
Alexander Couzensccde5c92017-02-04 03:10:08 +0100827 bitvec_write_field(dest, &wp, 1, 1); // 1: have length
828 bitvec_write_field(dest, &wp, len, 8); // length
Jacob Erlbeck37005a12015-12-22 14:58:34 +0100829 }
830
Alexander Couzensccde5c92017-02-04 03:10:08 +0100831 bitvec_write_field(dest, &wp, is_final, 1); // FINAL_ACK_INDICATION
832 bitvec_write_field(dest, &wp, bow, 1); // BEGINNING_OF_WINDOW
833 bitvec_write_field(dest, &wp, eow, 1); // END_OF_WINDOW
834 bitvec_write_field(dest, &wp, ssn, 11); // STARTING_SEQUENCE_NUMBER
Pravin Kumarvel06bdb352016-10-24 12:21:21 +0530835 if (is_compressed) {
Alexander Couzensccde5c92017-02-04 03:10:08 +0100836 bitvec_write_field(dest, &wp, 1, 1); // CRBB_Exist
837 bitvec_write_field(dest, &wp, crbb_len, 7); // CRBB_LENGTH
sivasankari8adfcd02017-01-16 15:41:21 +0530838 crbb_start_clr_code = (0x80 & ucmp_vec.data[0])>>7;
Alexander Couzensccde5c92017-02-04 03:10:08 +0100839 bitvec_write_field(dest, &wp, crbb_start_clr_code, 1); // CRBB_clr_code
sivasankari8adfcd02017-01-16 15:41:21 +0530840 LOGP(DRLCMACUL, LOGL_DEBUG,
841 "EGPRS CRBB, crbb_len = %d, crbb_start_clr_code = %d\n",
842 crbb_len, crbb_start_clr_code);
843 while (crbb_len != 0) {
844 if (crbb_len > 8) {
Alexander Couzensccde5c92017-02-04 03:10:08 +0100845 bitvec_write_field(dest, &wp, crbb_bitmap[iter], 8);
sivasankari8adfcd02017-01-16 15:41:21 +0530846 crbb_len = crbb_len - 8;
847 iter++;
848 } else {
Alexander Couzensccde5c92017-02-04 03:10:08 +0100849 bitvec_write_field(dest, &wp, crbb_bitmap[iter], crbb_len);
sivasankari8adfcd02017-01-16 15:41:21 +0530850 crbb_len = 0;
851 }
852 }
853 esn_crbb = window->mod_sns(esn_crbb + uclen_crbb);
854 } else {
Alexander Couzensccde5c92017-02-04 03:10:08 +0100855 bitvec_write_field(dest, &wp, 0, 1); // CRBB_Exist
sivasankari8adfcd02017-01-16 15:41:21 +0530856 }
Jacob Erlbeck37005a12015-12-22 14:58:34 +0100857 LOGP(DRLCMACUL, LOGL_DEBUG,
Pravin Kumarvel06bdb352016-10-24 12:21:21 +0530858 "EGPRS URBB, urbb len = %d, SSN = %d, ESN_CRBB = %d, "
859 "len present = %s,desc len = %d, "
Jacob Erlbeck37005a12015-12-22 14:58:34 +0100860 "SNS = %d, WS = %d, V(Q) = %d, V(R) = %d%s%s\n",
sivasankari8adfcd02017-01-16 15:41:21 +0530861 urbb_len, ssn, esn_crbb, len_coded ? "yes" : "No" , len,
Jacob Erlbeck37005a12015-12-22 14:58:34 +0100862 window->sns(), window->ws(), window->v_q(), window->v_r(),
863 bow ? ", BOW" : "", eow ? ", EOW" : "");
Pravin Kumarvel06bdb352016-10-24 12:21:21 +0530864
865 for (i = urbb_len; i > 0; i--) {
Jacob Erlbeck37005a12015-12-22 14:58:34 +0100866 /* Set bit at the appropriate position (see 3GPP TS 04.60 12.3.1) */
867 bool is_ack = window->m_v_n.is_received(esn_crbb + i);
Alexander Couzensccde5c92017-02-04 03:10:08 +0100868 bitvec_write_field(dest, &wp, is_ack, 1);
Jacob Erlbeck37005a12015-12-22 14:58:34 +0100869 }
870}
871
872static void write_packet_uplink_ack_egprs(
873 struct gprs_rlcmac_bts *bts, bitvec * dest, unsigned& wp,
874 struct gprs_rlcmac_ul_tbf *tbf, bool is_final)
875{
Alexander Couzensccde5c92017-02-04 03:10:08 +0100876 bitvec_write_field(dest, &wp, 0, 2); // fixed 00
Aravind Sirsikar99ab0a82016-06-15 17:46:41 +0530877 /* CHANNEL_CODING_COMMAND */
Alexander Couzensccde5c92017-02-04 03:10:08 +0100878 bitvec_write_field(dest, &wp,
Aravind Sirsikar99ab0a82016-06-15 17:46:41 +0530879 tbf->current_cs().to_num() - 1, 4);
Aravind Sirsikar505a86d2016-07-26 18:26:21 +0530880 /* 0: no RESEGMENT, 1: Segmentation*/
Alexander Couzensccde5c92017-02-04 03:10:08 +0100881 bitvec_write_field(dest, &wp, 1, 1);
882 bitvec_write_field(dest, &wp, 1, 1); // PRE_EMPTIVE_TRANSMISSION, TODO: This resembles GPRS, change it?
883 bitvec_write_field(dest, &wp, 0, 1); // 0: no PRR_RETRANSMISSION_REQUEST, TODO: clarify
884 bitvec_write_field(dest, &wp, 0, 1); // 0: no ARAC_RETRANSMISSION_REQUEST, TODO: clarify
885 bitvec_write_field(dest, &wp, 1, 1); // 1: have CONTENTION_RESOLUTION_TLLI
886 bitvec_write_field(dest, &wp, tbf->tlli(), 32); // CONTENTION_RESOLUTION_TLLI
887 bitvec_write_field(dest, &wp, 1, 1); // TBF_EST (enabled)
888 bitvec_write_field(dest, &wp, 0, 1); // 0: don't have Packet Timing Advance
889 bitvec_write_field(dest, &wp, 0, 1); // 0: don't have Packet Extended Timing Advance
890 bitvec_write_field(dest, &wp, 0, 1); // 0: don't have Power Control Parameters
891 bitvec_write_field(dest, &wp, 0, 1); // 0: don't have Extension Bits
Jacob Erlbeck37005a12015-12-22 14:58:34 +0100892
sivasankari8adfcd02017-01-16 15:41:21 +0530893 /* -2 for last bit 0 mandatory and REL5 not supported */
894 unsigned bits_ack_nack = dest->data_len * 8 - wp - 2;
Maxea98b7d2018-01-04 15:13:27 +0100895 write_packet_ack_nack_desc_egprs(bts, dest, wp, tbf->window(), is_final, bits_ack_nack);
Jacob Erlbeck37005a12015-12-22 14:58:34 +0100896
Alexander Couzensccde5c92017-02-04 03:10:08 +0100897 bitvec_write_field(dest, &wp, 0, 1); // fixed 0
898 bitvec_write_field(dest, &wp, 0, 1); // 0: don't have REL 5
Jacob Erlbeck37005a12015-12-22 14:58:34 +0100899};
900
901void Encoding::write_packet_uplink_ack(
902 struct gprs_rlcmac_bts *bts, bitvec * dest,
Jacob Erlbeckf2694b72016-01-26 21:46:26 +0100903 struct gprs_rlcmac_ul_tbf *tbf, bool is_final,
904 uint8_t rrbp)
Jacob Erlbeck37005a12015-12-22 14:58:34 +0100905{
906 unsigned wp = 0;
907
908 LOGP(DRLCMACUL, LOGL_DEBUG, "Encoding Ack/Nack for %s "
909 "(final=%d)\n", tbf_name(tbf), is_final);
910
Alexander Couzensccde5c92017-02-04 03:10:08 +0100911 bitvec_write_field(dest, &wp, 0x1, 2); // Payload Type
912 bitvec_write_field(dest, &wp, rrbp, 2); // Uplink block with TDMA framenumber
913 bitvec_write_field(dest, &wp, is_final, 1); // Suppl/Polling Bit
914 bitvec_write_field(dest, &wp, 0x0, 3); // Uplink state flag
915 bitvec_write_field(dest, &wp, 0x9, 6); // MESSAGE TYPE Uplink Ack/Nack
916 bitvec_write_field(dest, &wp, 0x0, 2); // Page Mode
Jacob Erlbeck37005a12015-12-22 14:58:34 +0100917
Alexander Couzensccde5c92017-02-04 03:10:08 +0100918 bitvec_write_field(dest, &wp, 0x0, 2); // fixed 00
919 bitvec_write_field(dest, &wp, tbf->tfi(), 5); // Uplink TFI
Jacob Erlbeck37005a12015-12-22 14:58:34 +0100920
921 if (tbf->is_egprs_enabled()) {
922 /* PU_AckNack_EGPRS = on */
Alexander Couzensccde5c92017-02-04 03:10:08 +0100923 bitvec_write_field(dest, &wp, 1, 1); // 1: EGPRS
Jacob Erlbeck37005a12015-12-22 14:58:34 +0100924 write_packet_uplink_ack_egprs(bts, dest, wp, tbf, is_final);
925 } else {
926 /* PU_AckNack_GPRS = on */
Alexander Couzensccde5c92017-02-04 03:10:08 +0100927 bitvec_write_field(dest, &wp, 0, 1); // 0: GPRS
Jacob Erlbeck37005a12015-12-22 14:58:34 +0100928 write_packet_uplink_ack_gprs(bts, dest, wp, tbf, is_final);
929 }
930
931 LOGP(DRLCMACUL, LOGL_DEBUG,
932 "Uplink Ack/Nack bit count %d, max %d, message = %s\n",
933 wp, dest->data_len * 8,
934 osmo_hexdump(dest->data, dest->data_len));
935}
936
Holger Hans Peter Freyther63f29d62013-10-19 19:04:03 +0200937unsigned Encoding::write_packet_paging_request(bitvec * dest)
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200938{
939 unsigned wp = 0;
940
Alexander Couzensccde5c92017-02-04 03:10:08 +0100941 bitvec_write_field(dest, &wp,0x1,2); // Payload Type
942 bitvec_write_field(dest, &wp,0x0,3); // No polling
943 bitvec_write_field(dest, &wp,0x0,3); // Uplink state flag
944 bitvec_write_field(dest, &wp,0x22,6); // MESSAGE TYPE
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200945
Alexander Couzensccde5c92017-02-04 03:10:08 +0100946 bitvec_write_field(dest, &wp,0x0,2); // Page Mode
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200947
Alexander Couzensccde5c92017-02-04 03:10:08 +0100948 bitvec_write_field(dest, &wp,0x0,1); // No PERSISTENCE_LEVEL
949 bitvec_write_field(dest, &wp,0x0,1); // No NLN
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200950
951 return wp;
952}
953
Holger Hans Peter Freyther63f29d62013-10-19 19:04:03 +0200954unsigned Encoding::write_repeated_page_info(bitvec * dest, unsigned& wp, uint8_t len,
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200955 uint8_t *identity, uint8_t chan_needed)
956{
Alexander Couzensccde5c92017-02-04 03:10:08 +0100957 bitvec_write_field(dest, &wp,0x1,1); // Repeated Page info exists
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200958
Alexander Couzensccde5c92017-02-04 03:10:08 +0100959 bitvec_write_field(dest, &wp,0x1,1); // RR connection paging
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200960
961 if ((identity[0] & 0x07) == 4) {
Alexander Couzensccde5c92017-02-04 03:10:08 +0100962 bitvec_write_field(dest, &wp,0x0,1); // TMSI
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200963 identity++;
964 len--;
965 } else {
Alexander Couzensccde5c92017-02-04 03:10:08 +0100966 bitvec_write_field(dest, &wp,0x0,1); // MI
967 bitvec_write_field(dest, &wp,len,4); // MI len
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200968 }
969 while (len) {
Alexander Couzensccde5c92017-02-04 03:10:08 +0100970 bitvec_write_field(dest, &wp,*identity++,8); // MI data
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200971 len--;
972 }
Alexander Couzensccde5c92017-02-04 03:10:08 +0100973 bitvec_write_field(dest, &wp,chan_needed,2); // CHANNEL_NEEDED
974 bitvec_write_field(dest, &wp,0x0,1); // No eMLPP_PRIORITY
Holger Hans Peter Freyther6ca0a902013-10-19 18:50:22 +0200975
976 return wp;
977}
978
Jacob Erlbeckf0e40392016-01-08 10:07:53 +0100979int Encoding::rlc_write_dl_data_header(const struct gprs_rlc_data_info *rlc,
980 uint8_t *data)
981{
Jacob Erlbeck9e859392016-02-02 11:48:37 +0100982 struct gprs_rlc_dl_header_egprs_1 *egprs1;
983 struct gprs_rlc_dl_header_egprs_2 *egprs2;
Jacob Erlbeckf0e40392016-01-08 10:07:53 +0100984 struct gprs_rlc_dl_header_egprs_3 *egprs3;
985 struct rlc_dl_header *gprs;
986 unsigned int e_fbi_header;
987 GprsCodingScheme cs = rlc->cs;
Jacob Erlbeck9e859392016-02-02 11:48:37 +0100988 unsigned int offs;
989 unsigned int bsn_delta;
Jacob Erlbeckf0e40392016-01-08 10:07:53 +0100990
991 switch(cs.headerTypeData()) {
992 case GprsCodingScheme::HEADER_GPRS_DATA:
993 gprs = static_cast<struct rlc_dl_header *>
994 ((void *)data);
995
996 gprs->usf = rlc->usf;
997 gprs->s_p = rlc->es_p != 0 ? 1 : 0;
998 gprs->rrbp = rlc->rrbp;
999 gprs->pt = 0;
1000 gprs->tfi = rlc->tfi;
1001 gprs->pr = rlc->pr;
1002
1003 gprs->fbi = rlc->block_info[0].cv == 0;
1004 gprs->e = rlc->block_info[0].e;
1005 gprs->bsn = rlc->block_info[0].bsn;
1006 break;
1007
Jacob Erlbeck9e859392016-02-02 11:48:37 +01001008 case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1:
1009 egprs1 = static_cast<struct gprs_rlc_dl_header_egprs_1 *>
1010 ((void *)data);
1011
1012 egprs1->usf = rlc->usf;
1013 egprs1->es_p = rlc->es_p;
1014 egprs1->rrbp = rlc->rrbp;
Tom Tsoudf698092016-07-11 17:05:19 -07001015 egprs1->tfi_hi = rlc->tfi >> 0; /* 1 bit LSB */
1016 egprs1->tfi_lo = rlc->tfi >> 1; /* 4 bits */
Jacob Erlbeck9e859392016-02-02 11:48:37 +01001017 egprs1->pr = rlc->pr;
1018 egprs1->cps = rlc->cps;
1019
Tom Tsoudf698092016-07-11 17:05:19 -07001020 egprs1->bsn1_hi = rlc->block_info[0].bsn >> 0; /* 2 bits LSB */
1021 egprs1->bsn1_mid = rlc->block_info[0].bsn >> 2; /* 8 bits */
1022 egprs1->bsn1_lo = rlc->block_info[0].bsn >> 10; /* 1 bit */
Jacob Erlbeck9e859392016-02-02 11:48:37 +01001023
1024 bsn_delta = (rlc->block_info[1].bsn - rlc->block_info[0].bsn) &
1025 (RLC_EGPRS_SNS - 1);
1026
Tom Tsoudf698092016-07-11 17:05:19 -07001027 egprs1->bsn2_hi = bsn_delta >> 0; /* 7 bits LSB */
1028 egprs1->bsn2_lo = bsn_delta >> 7; /* 3 bits */
Jacob Erlbeck9e859392016-02-02 11:48:37 +01001029
1030 /* first FBI/E header */
1031 e_fbi_header = rlc->block_info[0].e ? 0x01 : 0;
1032 e_fbi_header |= rlc->block_info[0].cv == 0 ? 0x02 : 0; /* FBI */
Jacob Erlbeck0f5c6952016-02-03 18:35:27 +01001033 offs = rlc->data_offs_bits[0] / 8;
1034 OSMO_ASSERT(rlc->data_offs_bits[0] % 8 == 2);
Jacob Erlbeck9e859392016-02-02 11:48:37 +01001035 e_fbi_header <<= 0;
Jacob Erlbeck0f5c6952016-02-03 18:35:27 +01001036 data[offs] = (data[offs] & 0b11111100) | e_fbi_header;
Jacob Erlbeck9e859392016-02-02 11:48:37 +01001037
1038 /* second FBI/E header */
1039 e_fbi_header = rlc->block_info[1].e ? 0x01 : 0;
1040 e_fbi_header |= rlc->block_info[1].cv == 0 ? 0x02 : 0; /* FBI */
1041 offs = rlc->data_offs_bits[1] / 8;
1042 OSMO_ASSERT(rlc->data_offs_bits[1] % 8 == 4);
1043 e_fbi_header <<= 2;
1044 data[offs] = (data[offs] & 0b11110011) | e_fbi_header;
1045 break;
1046
1047 case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_2:
1048 egprs2 = static_cast<struct gprs_rlc_dl_header_egprs_2 *>
1049 ((void *)data);
1050
1051 egprs2->usf = rlc->usf;
1052 egprs2->es_p = rlc->es_p;
1053 egprs2->rrbp = rlc->rrbp;
Tom Tsoudf698092016-07-11 17:05:19 -07001054 egprs2->tfi_hi = rlc->tfi >> 0; /* 1 bit LSB */
1055 egprs2->tfi_lo = rlc->tfi >> 1; /* 4 bits */
Jacob Erlbeck9e859392016-02-02 11:48:37 +01001056 egprs2->pr = rlc->pr;
1057 egprs2->cps = rlc->cps;
1058
Tom Tsoudf698092016-07-11 17:05:19 -07001059 egprs2->bsn1_hi = rlc->block_info[0].bsn >> 0; /* 2 bits LSB */
1060 egprs2->bsn1_mid = rlc->block_info[0].bsn >> 2; /* 8 bits */
1061 egprs2->bsn1_lo = rlc->block_info[0].bsn >> 10; /* 1 bit */
Jacob Erlbeck9e859392016-02-02 11:48:37 +01001062
1063 e_fbi_header = rlc->block_info[0].e ? 0x01 : 0;
1064 e_fbi_header |= rlc->block_info[0].cv == 0 ? 0x02 : 0; /* FBI */
Jacob Erlbeck0f5c6952016-02-03 18:35:27 +01001065 offs = rlc->data_offs_bits[0] / 8;
1066 OSMO_ASSERT(rlc->data_offs_bits[0] % 8 == 6);
Jacob Erlbeck9e859392016-02-02 11:48:37 +01001067 e_fbi_header <<= 4;
Jacob Erlbeck0f5c6952016-02-03 18:35:27 +01001068 data[offs] = (data[offs] & 0b11001111) | e_fbi_header;
Jacob Erlbeck9e859392016-02-02 11:48:37 +01001069 break;
1070
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001071 case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3:
1072 egprs3 = static_cast<struct gprs_rlc_dl_header_egprs_3 *>
1073 ((void *)data);
1074
1075 egprs3->usf = rlc->usf;
1076 egprs3->es_p = rlc->es_p;
1077 egprs3->rrbp = rlc->rrbp;
Tom Tsoudf698092016-07-11 17:05:19 -07001078 egprs3->tfi_hi = rlc->tfi >> 0; /* 1 bit LSB */
1079 egprs3->tfi_lo = rlc->tfi >> 1; /* 4 bits */
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001080 egprs3->pr = rlc->pr;
1081 egprs3->cps = rlc->cps;
1082
Tom Tsoudf698092016-07-11 17:05:19 -07001083 egprs3->bsn1_hi = rlc->block_info[0].bsn >> 0; /* 2 bits LSB */
1084 egprs3->bsn1_mid = rlc->block_info[0].bsn >> 2; /* 8 bits */
1085 egprs3->bsn1_lo = rlc->block_info[0].bsn >> 10; /* 1 bit */
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001086
1087 egprs3->spb = rlc->block_info[0].spb;
1088
1089 e_fbi_header = rlc->block_info[0].e ? 0x01 : 0;
1090 e_fbi_header |= rlc->block_info[0].cv == 0 ? 0x02 : 0; /* FBI */
Jacob Erlbeck0f5c6952016-02-03 18:35:27 +01001091 offs = rlc->data_offs_bits[0] / 8;
1092 OSMO_ASSERT(rlc->data_offs_bits[0] % 8 == 1);
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001093 e_fbi_header <<= 7;
Jacob Erlbeck0f5c6952016-02-03 18:35:27 +01001094 data[offs-1] = (data[offs-1] & 0b01111111) | (e_fbi_header >> 0);
1095 data[offs] = (data[offs] & 0b11111110) | (e_fbi_header >> 8);
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001096 break;
1097
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001098 default:
1099 LOGP(DRLCMACDL, LOGL_ERROR,
1100 "Encoding of uplink %s data blocks not yet supported.\n",
1101 cs.name());
1102 return -ENOTSUP;
1103 };
1104
1105 return 0;
1106}
1107
1108/**
1109 * \brief Copy LSB bitstream RLC data block from byte aligned buffer.
1110 *
1111 * Note that the bitstream is encoded in LSB first order, so the two octets
1112 * 654321xx xxxxxx87 contain the octet 87654321 starting at bit position 3
1113 * (LSB has bit position 1). This is a different order than the one used by
1114 * CSN.1.
1115 *
1116 * \param data_block_idx The block index, 0..1 for header type 1, 0 otherwise
1117 * \param src A pointer to the start of the RLC block (incl. the header)
1118 * \param buffer A data area of a least the size of the RLC block
1119 * \returns the number of bytes copied
1120 */
1121unsigned int Encoding::rlc_copy_from_aligned_buffer(
1122 const struct gprs_rlc_data_info *rlc,
1123 unsigned int data_block_idx,
1124 uint8_t *dst, const uint8_t *buffer)
1125{
1126 unsigned int hdr_bytes;
1127 unsigned int extra_bits;
1128 unsigned int i;
1129
1130 uint8_t c, last_c;
1131 const uint8_t *src;
1132 const struct gprs_rlc_data_block_info *rdbi;
1133
1134 OSMO_ASSERT(data_block_idx < rlc->num_data_blocks);
1135 rdbi = &rlc->block_info[data_block_idx];
1136
1137 hdr_bytes = rlc->data_offs_bits[data_block_idx] / 8;
1138 extra_bits = (rlc->data_offs_bits[data_block_idx] % 8);
1139
1140 if (extra_bits == 0) {
1141 /* It is aligned already */
1142 memmove(dst + hdr_bytes, buffer, rdbi->data_len);
1143 return rdbi->data_len;
1144 }
1145
1146 src = buffer;
1147 dst = dst + hdr_bytes;
1148 last_c = *dst << (8 - extra_bits);
1149
1150 for (i = 0; i < rdbi->data_len; i++) {
1151 c = src[i];
1152 *(dst++) = (last_c >> (8 - extra_bits)) | (c << extra_bits);
1153 last_c = c;
1154 }
1155
1156 /* overwrite the lower extra_bits */
1157 *dst = (*dst & (0xff << extra_bits)) | (last_c >> (8 - extra_bits));
1158
1159 return rdbi->data_len;
1160}
Jacob Erlbeck14bb0942016-01-12 11:58:13 +01001161
Alexander Couzenscb846ec2016-05-30 19:10:48 +02001162/*!
1163 * \brief (GPRS) put llc pdu into an rlc/mac block. fragment the llc pdu if needed
1164 * \param rdbi rlc/mac block info
1165 * \param llc llc pdu
1166 * \param offset given offset within the rlc/mac block
1167 * \param num_chunks count the chunks (llc pdu data) within rlc/mac
1168 * \param data_block buffer holds rlc/mac data
1169 * \param is_final if this is the last rlc/mac within a TBF
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001170 * \param count_payload if not NULL save the written size of payload in bytes into it
Alexander Couzenscb846ec2016-05-30 19:10:48 +02001171 * \return the state of the rlc/mac like if there is more space for another chunk
1172 */
Jacob Erlbeck5058bd62016-01-13 10:51:25 +01001173static Encoding::AppendResult rlc_data_to_dl_append_gprs(
Jacob Erlbeck14bb0942016-01-12 11:58:13 +01001174 struct gprs_rlc_data_block_info *rdbi,
1175 gprs_llc *llc, int *offset, int *num_chunks,
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001176 uint8_t *data_block, bool is_final, int *count_payload)
Jacob Erlbeck14bb0942016-01-12 11:58:13 +01001177{
1178 int chunk;
1179 int space;
1180 struct rlc_li_field *li;
1181 uint8_t *delimiter, *data, *e_pointer;
1182
1183 data = data_block + *offset;
1184 delimiter = data_block + *num_chunks;
1185 e_pointer = (*num_chunks ? delimiter - 1 : NULL);
1186
1187 chunk = llc->chunk_size();
1188 space = rdbi->data_len - *offset;
1189
1190 /* if chunk will exceed block limit */
1191 if (chunk > space) {
1192 LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d "
1193 "larger than space (%d) left in block: copy "
1194 "only remaining space, and we are done\n",
1195 chunk, space);
1196 /* block is filled, so there is no extension */
1197 if (e_pointer)
1198 *e_pointer |= 0x01;
1199 /* fill only space */
1200 llc->consume(data, space);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001201 if (count_payload)
1202 *count_payload = space;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +01001203 /* return data block as message */
1204 *offset = rdbi->data_len;
1205 (*num_chunks)++;
Jacob Erlbeck5058bd62016-01-13 10:51:25 +01001206 return Encoding::AR_NEED_MORE_BLOCKS;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +01001207 }
1208 /* if FINAL chunk would fit precisely in space left */
1209 if (chunk == space && is_final)
1210 {
1211 LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d "
1212 "would exactly fit into space (%d): because "
1213 "this is a final block, we don't add length "
1214 "header, and we are done\n", chunk, space);
1215 /* block is filled, so there is no extension */
1216 if (e_pointer)
1217 *e_pointer |= 0x01;
1218 /* fill space */
1219 llc->consume(data, space);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001220 if (count_payload)
1221 *count_payload = space;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +01001222 *offset = rdbi->data_len;
1223 (*num_chunks)++;
1224 rdbi->cv = 0;
Jacob Erlbeck5058bd62016-01-13 10:51:25 +01001225 return Encoding::AR_COMPLETED_BLOCK_FILLED;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +01001226 }
1227 /* if chunk would fit exactly in space left */
1228 if (chunk == space) {
1229 LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d "
1230 "would exactly fit into space (%d): add length "
1231 "header with LI=0, to make frame extend to "
1232 "next block, and we are done\n", chunk, space);
1233 /* make space for delimiter */
1234 if (delimiter != data)
1235 memmove(delimiter + 1, delimiter,
1236 data - delimiter);
1237 data++;
1238 (*offset)++;
1239 space--;
1240 /* add LI with 0 length */
1241 li = (struct rlc_li_field *)delimiter;
1242 li->e = 1; /* not more extension */
1243 li->m = 0; /* shall be set to 0, in case of li = 0 */
1244 li->li = 0; /* chunk fills the complete space */
1245 rdbi->e = 0; /* 0: extensions present */
1246 // no need to set e_pointer nor increase delimiter
1247 /* fill only space, which is 1 octet less than chunk */
1248 llc->consume(data, space);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001249 if (count_payload)
1250 *count_payload = space;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +01001251 /* return data block as message */
1252 *offset = rdbi->data_len;
1253 (*num_chunks)++;
Jacob Erlbeck5058bd62016-01-13 10:51:25 +01001254 return Encoding::AR_NEED_MORE_BLOCKS;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +01001255 }
1256
1257 LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d is less "
1258 "than remaining space (%d): add length header to "
1259 "to delimit LLC frame\n", chunk, space);
1260 /* the LLC frame chunk ends in this block */
1261 /* make space for delimiter */
1262 if (delimiter != data)
1263 memmove(delimiter + 1, delimiter, data - delimiter);
1264 data++;
1265 (*offset)++;
1266 space--;
1267 /* add LI to delimit frame */
1268 li = (struct rlc_li_field *)delimiter;
1269 li->e = 0; /* Extension bit, maybe set later */
1270 li->m = 0; /* will be set later, if there is more LLC data */
1271 li->li = chunk; /* length of chunk */
1272 rdbi->e = 0; /* 0: extensions present */
1273 (*num_chunks)++;
1274 /* copy (rest of) LLC frame to space and reset later */
1275 llc->consume(data, chunk);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001276 if (count_payload)
1277 *count_payload = chunk;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +01001278 data += chunk;
1279 space -= chunk;
1280 (*offset) += chunk;
1281 /* if we have more data and we have space left */
1282 if (space > 0 && !is_final) {
1283 li->m = 1; /* we indicate more frames to follow */
Jacob Erlbeck5058bd62016-01-13 10:51:25 +01001284 return Encoding::AR_COMPLETED_SPACE_LEFT;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +01001285 }
1286 /* if we don't have more LLC frames */
1287 if (is_final) {
1288 LOGP(DRLCMACDL, LOGL_DEBUG, "-- Final block, so we "
1289 "done.\n");
1290 li->e = 1; /* we cannot extend */
1291 rdbi->cv = 0;
Jacob Erlbeck5058bd62016-01-13 10:51:25 +01001292 return Encoding::AR_COMPLETED_BLOCK_FILLED;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +01001293 }
1294 /* we have no space left */
1295 LOGP(DRLCMACDL, LOGL_DEBUG, "-- No space left, so we are "
1296 "done.\n");
1297 li->e = 1; /* we cannot extend */
Jacob Erlbeck5058bd62016-01-13 10:51:25 +01001298 return Encoding::AR_COMPLETED_BLOCK_FILLED;
1299}
1300
Alexander Couzenscb846ec2016-05-30 19:10:48 +02001301/*!
1302 * \brief (EGPRS) put llc pdu into an rlc/mac block. fragment the llc pdu if needed
1303 * \param rdbi rlc/mac block info
1304 * \param llc llc pdu
1305 * \param offset given offset within the rlc/mac block
1306 * \param num_chunks count the chunks (llc pdu data) within rlc/mac
1307 * \param data_block buffer holds rlc/mac data
1308 * \param is_final if this is the last rlc/mac within a TBF
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001309 * \param count_payload if not NULL save the written size of payload in bytes into it
Alexander Couzenscb846ec2016-05-30 19:10:48 +02001310 * \return the state of the rlc/mac like if there is more space for another chunk
1311 */
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001312static Encoding::AppendResult rlc_data_to_dl_append_egprs(
1313 struct gprs_rlc_data_block_info *rdbi,
1314 gprs_llc *llc, int *offset, int *num_chunks,
1315 uint8_t *data_block,
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001316 bool is_final, int *count_payload)
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001317{
1318 int chunk;
1319 int space;
1320 struct rlc_li_field_egprs *li;
1321 struct rlc_li_field_egprs *prev_li;
1322 uint8_t *delimiter, *data;
1323
1324 data = data_block + *offset;
1325 delimiter = data_block + *num_chunks;
1326 prev_li = (struct rlc_li_field_egprs *)
1327 (*num_chunks ? delimiter - 1 : NULL);
1328
1329 chunk = llc->chunk_size();
1330 space = rdbi->data_len - *offset;
1331
1332 /* if chunk will exceed block limit */
1333 if (chunk > space) {
1334 LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d "
1335 "larger than space (%d) left in block: copy "
1336 "only remaining space, and we are done\n",
1337 chunk, space);
1338 /* fill only space */
1339 llc->consume(data, space);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001340 if (count_payload)
1341 *count_payload = space;
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001342 /* return data block as message */
1343 *offset = rdbi->data_len;
1344 (*num_chunks)++;
1345 return Encoding::AR_NEED_MORE_BLOCKS;
1346 }
1347 /* if FINAL chunk would fit precisely in space left */
1348 if (chunk == space && is_final)
1349 {
1350 LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d "
1351 "would exactly fit into space (%d): because "
1352 "this is a final block, we don't add length "
1353 "header, and we are done\n", chunk, space);
1354 /* fill space */
1355 llc->consume(data, space);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001356 if (count_payload)
1357 *count_payload = space;
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001358 *offset = rdbi->data_len;
1359 (*num_chunks)++;
1360 rdbi->cv = 0;
1361 return Encoding::AR_COMPLETED_BLOCK_FILLED;
1362 }
1363 /* if chunk would fit exactly in space left */
1364 if (chunk == space) {
1365 LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d "
1366 "would exactly fit into space (%d): just copy "
1367 "it, and we are done. The next block will have "
1368 "to start with an empty chunk\n",
1369 chunk, space);
1370 /* fill space */
1371 llc->consume(data, space);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001372 if (count_payload)
1373 *count_payload = space;
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001374 *offset = rdbi->data_len;
1375 (*num_chunks)++;
1376 return Encoding::AR_NEED_MORE_BLOCKS;
1377 }
1378
1379 LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d is less "
1380 "than remaining space (%d): add length header to "
1381 "to delimit LLC frame\n", chunk, space);
1382 /* the LLC frame chunk ends in this block */
1383 /* make space for delimiter */
1384
1385 if (delimiter != data)
1386 memmove(delimiter + 1, delimiter, data - delimiter);
1387
1388 data += 1;
1389 (*offset) += 1;
1390 space -= 1;
1391 /* add LI to delimit frame */
1392 li = (struct rlc_li_field_egprs *)delimiter;
1393 li->e = 1; /* Extension bit, maybe set later */
1394 li->li = chunk; /* length of chunk */
1395 /* tell previous extension header about the new one */
1396 if (prev_li)
1397 prev_li->e = 0;
1398 rdbi->e = 0; /* 0: extensions present */
1399 delimiter++;
1400 prev_li = li;
1401 (*num_chunks)++;
1402 /* copy (rest of) LLC frame to space and reset later */
1403 llc->consume(data, chunk);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001404 if (count_payload)
1405 *count_payload = chunk;
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001406 data += chunk;
1407 space -= chunk;
1408 (*offset) += chunk;
1409 /* if we have more data and we have space left */
1410 if (space > 0) {
1411 if (!is_final)
1412 return Encoding::AR_COMPLETED_SPACE_LEFT;
1413
1414 /* we don't have more LLC frames */
1415 /* We will have to add another chunk with filling octets */
1416 LOGP(DRLCMACDL, LOGL_DEBUG,
1417 "-- There is remaining space (%d): add filling byte chunk\n",
1418 space);
1419
1420 if (delimiter != data)
1421 memmove(delimiter + 1, delimiter, data - delimiter);
1422
1423 data += 1;
1424 (*offset) += 1;
1425 space -= 1;
1426
1427 /* set filling bytes extension */
1428 li = (struct rlc_li_field_egprs *)delimiter;
1429 li->e = 1;
1430 li->li = 127;
1431
1432 /* tell previous extension header about the new one */
1433 if (prev_li)
1434 prev_li->e = 0;
1435
1436 delimiter++;
1437 (*num_chunks)++;
1438
1439 rdbi->cv = 0;
1440
1441 LOGP(DRLCMACDL, LOGL_DEBUG, "-- Final block, so we "
1442 "are done.\n");
1443
1444 *offset = rdbi->data_len;
1445 return Encoding::AR_COMPLETED_BLOCK_FILLED;
1446 }
1447
1448 if (is_final) {
1449 /* we don't have more LLC frames */
1450 LOGP(DRLCMACDL, LOGL_DEBUG, "-- Final block, so we "
1451 "are done.\n");
1452 rdbi->cv = 0;
1453 return Encoding::AR_COMPLETED_BLOCK_FILLED;
1454 }
1455
1456 /* we have no space left */
1457 LOGP(DRLCMACDL, LOGL_DEBUG, "-- No space left, so we are "
1458 "done.\n");
1459 return Encoding::AR_COMPLETED_BLOCK_FILLED;
1460}
1461
Alexander Couzenscb846ec2016-05-30 19:10:48 +02001462/*!
1463 * \brief Encoding::rlc_data_to_dl_append
1464 * \param rdbi rlc/mac block info
1465 * \param cs the coding scheme to use
1466 * \param llc llc pdu
1467 * \param offset given offset within the rlc/mac block
1468 * \param num_chunks count the chunks (llc pdu data) within rlc/mac
1469 * \param data_block buffer holds rlc/mac data
1470 * \param is_final if this is the last rlc/mac within a TBF
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001471 * \param count_payload if not NULL save the written size of payload in bytes into it
Alexander Couzenscb846ec2016-05-30 19:10:48 +02001472 * \return the state of the rlc/mac like if there is more space for another chunk
1473 */
Jacob Erlbeck5058bd62016-01-13 10:51:25 +01001474Encoding::AppendResult Encoding::rlc_data_to_dl_append(
1475 struct gprs_rlc_data_block_info *rdbi, GprsCodingScheme cs,
1476 gprs_llc *llc, int *offset, int *num_chunks,
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001477 uint8_t *data_block, bool is_final, int *count_payload)
Jacob Erlbeck5058bd62016-01-13 10:51:25 +01001478{
1479 if (cs.isGprs())
1480 return rlc_data_to_dl_append_gprs(rdbi,
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001481 llc, offset, num_chunks, data_block, is_final,
1482 count_payload);
Jacob Erlbeck5058bd62016-01-13 10:51:25 +01001483
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001484 if (cs.isEgprs())
1485 return rlc_data_to_dl_append_egprs(rdbi,
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001486 llc, offset, num_chunks, data_block, is_final,
1487 count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001488
Jacob Erlbeck5058bd62016-01-13 10:51:25 +01001489 LOGP(DRLCMACDL, LOGL_ERROR, "%s data block encoding not implemented\n",
1490 cs.name());
1491
1492 return AR_NEED_MORE_BLOCKS;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +01001493}
aravind sirsikared3413e2016-11-11 17:15:10 +05301494
1495/*
1496 * Refer 44.060 version 7.27.0 Release 7
1497 * section 7.1.3.2.1 On receipt of a PACKET RESOURCE REQUEST message
1498 * 8.1.2.5 Establishment of uplink TBF
1499 */
1500void Encoding::write_packet_access_reject(
1501 bitvec * dest, uint32_t tlli)
1502{
1503 unsigned wp = 0;
1504
Alexander Couzensccde5c92017-02-04 03:10:08 +01001505 bitvec_write_field(dest, &wp, 0x1, 2); // Payload Type
1506 bitvec_write_field(dest, &wp, 0x0, 2); // Uplink block with TDMA FN
1507 bitvec_write_field(dest, &wp, 0, 1); // No Polling Bit
1508 bitvec_write_field(dest, &wp, 0x0, 3); // Uplink state flag
1509 bitvec_write_field(dest, &wp,
aravind sirsikared3413e2016-11-11 17:15:10 +05301510 MT_PACKET_ACCESS_REJECT, 6); // MESSAGE TYPE
Alexander Couzensccde5c92017-02-04 03:10:08 +01001511 bitvec_write_field(dest, &wp, 0, 2); // fixed 00
1512 bitvec_write_field(dest, &wp, 0x0, 1); // TLLI / G-RNTI : bit (32)
1513 bitvec_write_field(dest, &wp, tlli, 32); // CONTENTION_RESOLUTION_TLLI
1514 bitvec_write_field(dest, &wp, 1, 1); // WAIT_INDICATION size in seconds
aravind sirsikared3413e2016-11-11 17:15:10 +05301515 /* TODO: make it configurable */
Alexander Couzensccde5c92017-02-04 03:10:08 +01001516 bitvec_write_field(dest, &wp, 5, 8); // WAIT_INDICATION value
1517 bitvec_write_field(dest, &wp, 0, 1); // WAIT_INDICATION size in seconds
aravind sirsikared3413e2016-11-11 17:15:10 +05301518}