blob: c50e7aeca23ed3587582598b779ff6f39f796610 [file] [log] [blame]
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04001/* gprs_rlcmac.cpp
2 *
3 * Copyright (C) 2012 Ivan Klyuchnikov
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20#include <gprs_bssgp_pcu.h>
21#include <pcu_l1_if.h>
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +040022#include <gprs_rlcmac.h>
Ivan Kluchnikov5310d452012-04-17 22:00:31 +040023#include <gsmL1prim.h>
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +040024
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +040025LLIST_HEAD(gprs_rlcmac_tbfs);
26void *rlcmac_tall_ctx;
Andreas Eversberg0aed6542012-06-23 10:33:16 +020027LLIST_HEAD(block_queue);
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +040028
29int tfi_alloc()
30{
31 struct gprs_rlcmac_tbf *tbf;
32 uint32_t tfi_map = 0;
33 uint32_t tfi_ind = 0;
34 uint32_t mask = 1;
35 uint8_t i;
36
37 llist_for_each_entry(tbf, &gprs_rlcmac_tbfs, list) {
38 tfi_ind = 1 << tbf->tfi;
39 tfi_map = tfi_map|tfi_ind;
40 }
41
42 for (i = 0; i < 32; i++) {
43 if(((tfi_map >> i) & mask) == 0) {
44 return i;
45 }
46 }
47 return -1;
48}
49
50/* lookup TBF Entity (by TFI) */
Andreas Eversberg0aed6542012-06-23 10:33:16 +020051struct gprs_rlcmac_tbf *tbf_by_tfi(uint8_t tfi)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +040052{
53 struct gprs_rlcmac_tbf *tbf;
54
55 llist_for_each_entry(tbf, &gprs_rlcmac_tbfs, list) {
56 if (tbf->tfi == tfi)
57 return tbf;
58 }
59 return NULL;
60}
61
Andreas Eversberg0aed6542012-06-23 10:33:16 +020062struct gprs_rlcmac_tbf *tbf_by_tlli(uint32_t tlli)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +040063{
64 struct gprs_rlcmac_tbf *tbf;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +040065 llist_for_each_entry(tbf, &gprs_rlcmac_tbfs, list) {
66 if ((tbf->tlli == tlli)&&(tbf->direction == GPRS_RLCMAC_UL_TBF))
67 return tbf;
68 }
69 return NULL;
70}
71
Andreas Eversberg0aed6542012-06-23 10:33:16 +020072struct gprs_rlcmac_tbf *tbf_alloc(uint8_t tfi, uint8_t trx, uint8_t ts)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +040073{
74 struct gprs_rlcmac_tbf *tbf;
75
76 tbf = talloc_zero(rlcmac_tall_ctx, struct gprs_rlcmac_tbf);
77 if (!tbf)
78 return NULL;
79
80 tbf->tfi = tfi;
Andreas Eversberg0aed6542012-06-23 10:33:16 +020081 tbf->trx = trx;
82 tbf->ts = ts;
83 tbf->arfcn = pcu_l1if_bts.trx[trx].arfcn;
84 tbf->tsc = pcu_l1if_bts.trx[trx].ts[ts].tsc;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +040085 llist_add(&tbf->list, &gprs_rlcmac_tbfs);
86
87 return tbf;
88}
89
Andreas Eversberg0aed6542012-06-23 10:33:16 +020090void tbf_free(struct gprs_rlcmac_tbf *tbf)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +040091{
92 llist_del(&tbf->list);
93 talloc_free(tbf);
94}
95
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +040096
97static void tbf_timer_cb(void *_tbf)
98{
99 struct gprs_rlcmac_tbf *tbf = (struct gprs_rlcmac_tbf *)_tbf;
100
101 tbf->num_T_exp++;
102
103 switch (tbf->T) {
104 case 1111:
105 // TODO: We should add timers for TBF.
106 break;
107 default:
Ivan Kluchnikov856221f2012-06-15 09:31:29 +0400108 LOGP(DRLCMAC, LOGL_NOTICE, "Timer expired in unknown mode: %u \n", tbf->T);
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +0400109 }
110}
111
112static void tbf_timer_start(struct gprs_rlcmac_tbf *tbf, unsigned int T,
113 unsigned int seconds)
114{
115 if (osmo_timer_pending(&tbf->timer))
Ivan Kluchnikov856221f2012-06-15 09:31:29 +0400116 LOGP(DRLCMAC, LOGL_NOTICE, "Starting TBF timer %u while old timer %u pending \n", T, tbf->T);
117
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +0400118 tbf->T = T;
119 tbf->num_T_exp = 0;
120
121 /* FIXME: we should do this only once ? */
122 tbf->timer.data = tbf;
123 tbf->timer.cb = &tbf_timer_cb;
124
125 osmo_timer_schedule(&tbf->timer, seconds, 0);
126}
127
128
129static void tbf_gsm_timer_cb(void *_tbf)
130{
131 struct gprs_rlcmac_tbf *tbf = (struct gprs_rlcmac_tbf *)_tbf;
132
133 tbf->num_fT_exp++;
134
135 switch (tbf->fT) {
136 case 0:
137 // This is timer for delay RLC/MAC data sending after Downlink Immediate Assignment on CCCH.
138 gprs_rlcmac_segment_llc_pdu(tbf);
Ivan Kluchnikova9f1ff22012-05-24 22:25:06 +0400139 LOGP(DRLCMAC, LOGL_NOTICE, "TBF: [DOWNLINK] END TFI: %u TLLI: 0x%08x \n", tbf->tfi, tbf->tlli);
Ivan Kluchnikov9c795ab2012-05-24 23:12:59 +0400140 tbf_free(tbf);
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +0400141 break;
142 default:
Ivan Kluchnikov856221f2012-06-15 09:31:29 +0400143 LOGP(DRLCMAC, LOGL_NOTICE, "Timer expired in unknown mode: %u \n", tbf->fT);
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +0400144 }
145}
146
147static void tbf_gsm_timer_start(struct gprs_rlcmac_tbf *tbf, unsigned int fT,
148 int frames)
149{
150 if (osmo_gsm_timer_pending(&tbf->gsm_timer))
Ivan Kluchnikov856221f2012-06-15 09:31:29 +0400151 LOGP(DRLCMAC, LOGL_NOTICE, "Starting TBF timer %u while old timer %u pending \n", fT, tbf->fT);
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +0400152 tbf->fT = fT;
153 tbf->num_fT_exp = 0;
154
155 /* FIXME: we should do this only once ? */
156 tbf->gsm_timer.data = tbf;
157 tbf->gsm_timer.cb = &tbf_gsm_timer_cb;
158
159 osmo_gsm_timer_schedule(&tbf->gsm_timer, frames);
160}
161
Andreas Eversberg0aed6542012-06-23 10:33:16 +0200162static void gprs_rlcmac_enqueue_block(bitvec *block, int len)
163{
164 struct msgb *msg = msgb_alloc(len, "rlcmac_dl");
165 bitvec_pack(block, msgb_put(msg, len));
166 msgb_enqueue(&block_queue, msg);
167}
168
Ivan Kluchnikov0b450c12012-05-24 22:47:12 +0400169void write_packet_downlink_assignment(bitvec * dest, uint8_t tfi, uint32_t tlli, uint8_t tn, uint8_t ta, uint8_t tsc)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400170{
171 // TODO We should use our implementation of encode RLC/MAC Control messages.
172 unsigned wp = 0;
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400173 bitvec_write_field(dest, wp,0x1,2); // Payload Type
174 bitvec_write_field(dest, wp,0x0,2); // Uplink block with TDMA framenumber
175 bitvec_write_field(dest, wp,0x1,1); // Suppl/Polling Bit
176 bitvec_write_field(dest, wp,0x1,3); // Uplink state flag
177 bitvec_write_field(dest, wp,0x2,6); // MESSAGE TYPE
178 bitvec_write_field(dest, wp,0x0,2); // Page Mode
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400179
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400180 bitvec_write_field(dest, wp,0x0,1); // switch PERSIST_LEVEL: off
Ivan Kluchnikov0b450c12012-05-24 22:47:12 +0400181 bitvec_write_field(dest, wp,0x0,1); // switch TFI : on
182 bitvec_write_field(dest, wp,0x0,1); // switch UPLINK TFI : on
183 bitvec_write_field(dest, wp,tfi-1,5); // TFI
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400184
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400185 bitvec_write_field(dest, wp,0x0,1); // Message escape
186 bitvec_write_field(dest, wp,0x0,2); // Medium Access Method: Dynamic Allocation
187 bitvec_write_field(dest, wp,0x0,1); // RLC acknowledged mode
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400188
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400189 bitvec_write_field(dest, wp,0x0,1); // the network establishes no new downlink TBF for the mobile station
190 bitvec_write_field(dest, wp,0x1,8); // timeslot 7
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400191
Ivan Kluchnikov0b450c12012-05-24 22:47:12 +0400192 bitvec_write_field(dest, wp,0x1,1); // switch TIMING_ADVANCE_VALUE = on
193 bitvec_write_field(dest, wp,ta,6); // TIMING_ADVANCE_VALUE
194 bitvec_write_field(dest, wp,0x0,1); // switch TIMING_ADVANCE_INDEX = off
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400195
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400196 bitvec_write_field(dest, wp,0x0,1); // switch POWER CONTROL = off
197 bitvec_write_field(dest, wp,0x1,1); // Frequency Parameters information elements = present
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400198
Ivan Kluchnikov0b450c12012-05-24 22:47:12 +0400199 bitvec_write_field(dest, wp,tsc,3); // Training Sequence Code (TSC) = 2
200 bitvec_write_field(dest, wp,0x0,2); // ARFCN = present
201 bitvec_write_field(dest, wp,599,10); // ARFCN
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400202
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400203 bitvec_write_field(dest, wp,0x1,1); // switch TFI : on
204 bitvec_write_field(dest, wp,tfi,5);// TFI
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400205
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400206 bitvec_write_field(dest, wp,0x1,1); // Power Control Parameters IE = present
207 bitvec_write_field(dest, wp,0x0,4); // ALPHA power control parameter
208 bitvec_write_field(dest, wp,0x0,1); // switch GAMMA_TN0 = off
209 bitvec_write_field(dest, wp,0x0,1); // switch GAMMA_TN1 = off
210 bitvec_write_field(dest, wp,0x0,1); // switch GAMMA_TN2 = off
211 bitvec_write_field(dest, wp,0x0,1); // switch GAMMA_TN3 = off
212 bitvec_write_field(dest, wp,0x0,1); // switch GAMMA_TN4 = off
213 bitvec_write_field(dest, wp,0x0,1); // switch GAMMA_TN5 = off
214 bitvec_write_field(dest, wp,0x0,1); // switch GAMMA_TN6 = off
215 bitvec_write_field(dest, wp,0x1,1); // switch GAMMA_TN7 = on
216 bitvec_write_field(dest, wp,0x0,5); // GAMMA_TN7
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400217
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400218 bitvec_write_field(dest, wp,0x0,1); // TBF Starting TIME IE not present
219 bitvec_write_field(dest, wp,0x0,1); // Measurement Mapping struct not present
Ivan Kluchnikov0b450c12012-05-24 22:47:12 +0400220 bitvec_write_field(dest, wp,0x0,1);
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400221}
222
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400223void write_packet_uplink_assignment(bitvec * dest, uint8_t tfi, uint32_t tlli)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400224{
225 // TODO We should use our implementation of encode RLC/MAC Control messages.
226 unsigned wp = 0;
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400227 bitvec_write_field(dest, wp,0x1,2); // Payload Type
228 bitvec_write_field(dest, wp,0x0,2); // Uplink block with TDMA framenumber
229 bitvec_write_field(dest, wp,0x1,1); // Suppl/Polling Bit
230 bitvec_write_field(dest, wp,0x1,3); // Uplink state flag
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400231
232
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400233 bitvec_write_field(dest, wp,0xa,6); // MESSAGE TYPE
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400234
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400235 bitvec_write_field(dest, wp,0x0,2); // Page Mode
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400236
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400237 bitvec_write_field(dest, wp,0x0,1); // switch PERSIST_LEVEL: off
238 bitvec_write_field(dest, wp,0x2,2); // switch TLLI : on
239 bitvec_write_field(dest, wp,tlli,32); // TLLI
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400240
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400241 bitvec_write_field(dest, wp,0x0,1); // Message escape
242 bitvec_write_field(dest, wp,0x0,2); // CHANNEL_CODING_COMMAND
243 bitvec_write_field(dest, wp,0x0,1); // TLLI_BLOCK_CHANNEL_CODING
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400244
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400245 bitvec_write_field(dest, wp,0x1,1); // switch TIMING_ADVANCE_VALUE = on
246 bitvec_write_field(dest, wp,0x0,6); // TIMING_ADVANCE_VALUE
247 bitvec_write_field(dest, wp,0x0,1); // switch TIMING_ADVANCE_INDEX = off
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400248
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400249 bitvec_write_field(dest, wp,0x0,1); // Frequency Parameters = off
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400250
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400251 bitvec_write_field(dest, wp,0x1,2); // Dynamic Allocation = off
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400252
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400253 bitvec_write_field(dest, wp,0x0,1); // Dynamic Allocation
254 bitvec_write_field(dest, wp,0x0,1); // P0 = off
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400255
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400256 bitvec_write_field(dest, wp,0x1,1); // USF_GRANULARITY
257 bitvec_write_field(dest, wp,0x1,1); // switch TFI : on
258 bitvec_write_field(dest, wp,tfi,5);// TFI
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400259
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400260 bitvec_write_field(dest, wp,0x0,1); //
261 bitvec_write_field(dest, wp,0x0,1); // TBF Starting Time = off
262 bitvec_write_field(dest, wp,0x0,1); // Timeslot Allocation
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400263
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400264 bitvec_write_field(dest, wp,0x0,5); // USF_TN 0 - 4
265 bitvec_write_field(dest, wp,0x1,1); // USF_TN 5
266 bitvec_write_field(dest, wp,0x1,3); // USF_TN 5
267 bitvec_write_field(dest, wp,0x0,2); // USF_TN 6 - 7
268// bitvec_write_field(dest, wp,0x0,1); // Measurement Mapping struct not present
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400269}
270
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400271
272// GSM 04.08 9.1.18 Immediate assignment
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400273int write_immediate_assignment(bitvec * dest, uint8_t downlink, uint8_t ra, uint32_t fn,
Andreas Eversberg0aed6542012-06-23 10:33:16 +0200274 uint8_t ta, uint16_t arfcn, uint8_t ts, uint8_t tsc, uint8_t tfi = 0, uint32_t tlli = 0)
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400275{
276 unsigned wp = 0;
277
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400278 bitvec_write_field(dest, wp,0x0,4); // Skip Indicator
279 bitvec_write_field(dest, wp,0x6,4); // Protocol Discriminator
280 bitvec_write_field(dest, wp,0x3F,8); // Immediate Assignment Message Type
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400281
282 // 10.5.2.25b Dedicated mode or TBF
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400283 bitvec_write_field(dest, wp,0x0,1); // spare
284 bitvec_write_field(dest, wp,0x0,1); // TMA : Two-message assignment: No meaning
285 bitvec_write_field(dest, wp,downlink,1); // Downlink : Downlink assignment to mobile in packet idle mode
286 bitvec_write_field(dest, wp,0x1,1); // T/D : TBF or dedicated mode: this message assigns a Temporary Block Flow (TBF).
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400287
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400288 bitvec_write_field(dest, wp,0x0,4); // Page Mode
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400289
290 // GSM 04.08 10.5.2.25a Packet Channel Description
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400291 bitvec_write_field(dest, wp,0x1,5); // Channel type
Andreas Eversberg0aed6542012-06-23 10:33:16 +0200292 bitvec_write_field(dest, wp,ts,3); // TN
293 bitvec_write_field(dest, wp,tsc,3); // TSC
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400294 bitvec_write_field(dest, wp,0x0,3); // non-hopping RF channel configuraion
Andreas Eversberg0aed6542012-06-23 10:33:16 +0200295 bitvec_write_field(dest, wp,arfcn,10); // ARFCN
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400296
297 //10.5.2.30 Request Reference
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400298 bitvec_write_field(dest, wp,ra,8); // RA
299 bitvec_write_field(dest, wp,(fn / (26 * 51)) % 32,5); // T1'
300 bitvec_write_field(dest, wp,fn % 51,6); // T3
301 bitvec_write_field(dest, wp,fn % 26,5); // T2
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400302
303 // 10.5.2.40 Timing Advance
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400304 bitvec_write_field(dest, wp,0x0,2); // spare
305 bitvec_write_field(dest, wp,ta,6); // Timing Advance value
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400306
307 // No mobile allocation in non-hopping systems.
308 // A zero-length LV. Just write L=0.
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400309 bitvec_write_field(dest, wp,0,8);
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400310
311 if (downlink)
312 {
313 // GSM 04.08 10.5.2.16 IA Rest Octets
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400314 bitvec_write_field(dest, wp, 3, 2); // "HH"
315 bitvec_write_field(dest, wp, 1, 2); // "01" Packet Downlink Assignment
316 bitvec_write_field(dest, wp,tlli,32); // TLLI
317 bitvec_write_field(dest, wp,0x1,1); // switch TFI : on
318 bitvec_write_field(dest, wp,tfi,5); // TFI
319 bitvec_write_field(dest, wp,0x0,1); // RLC acknowledged mode
320 bitvec_write_field(dest, wp,0x0,1); // ALPHA = present
321 bitvec_write_field(dest, wp,0x0,5); // GAMMA power control parameter
322 bitvec_write_field(dest, wp,0x0,1); // Polling Bit
323 bitvec_write_field(dest, wp,0x1,1); // TA_VALID ???
324 bitvec_write_field(dest, wp,0x1,1); // switch TIMING_ADVANCE_INDEX = on
325 bitvec_write_field(dest, wp,0x0,4); // TIMING_ADVANCE_INDEX
326 bitvec_write_field(dest, wp,0x0,1); // TBF Starting TIME present
327 bitvec_write_field(dest, wp,0x0,1); // P0 not present
328 bitvec_write_field(dest, wp,0x1,1); // P0 not present
329 bitvec_write_field(dest, wp,0xb,4);
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400330 }
331 else
332 {
333 // GMS 04.08 10.5.2.37b 10.5.2.16
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400334 bitvec_write_field(dest, wp, 3, 2); // "HH"
335 bitvec_write_field(dest, wp, 0, 2); // "0" Packet Uplink Assignment
336 bitvec_write_field(dest, wp, 1, 1); // Block Allocation : Not Single Block Allocation
337 bitvec_write_field(dest, wp, tfi, 5); // TFI_ASSIGNMENT Temporary Flow Identity
338 bitvec_write_field(dest, wp, 0, 1); // POLLING
339 bitvec_write_field(dest, wp, 0, 1); // ALLOCATION_TYPE: dynamic
340 bitvec_write_field(dest, wp, 1, 3); // USF
341 bitvec_write_field(dest, wp, 1, 1); // USF_GRANULARITY
342 bitvec_write_field(dest, wp, 0 , 1); // "0" power control: Not Present
343 bitvec_write_field(dest, wp, 0, 2); // CHANNEL_CODING_COMMAND
344 bitvec_write_field(dest, wp, 1, 1); // TLLI_BLOCK_CHANNEL_CODING
345 bitvec_write_field(dest, wp, 1 , 1); // "1" Alpha : Present
346 bitvec_write_field(dest, wp, 0, 4); // Alpha
347 bitvec_write_field(dest, wp, 0, 5); // Gamma
348 bitvec_write_field(dest, wp, 0, 1); // TIMING_ADVANCE_INDEX_FLAG
349 bitvec_write_field(dest, wp, 0, 1); // TBF_STARTING_TIME_FLAG
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400350 }
351
352 if (wp%8)
353 return wp/8+1;
354 else
355 return wp/8;
356}
357
358
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400359void write_ia_rest_octets_downlink_assignment(bitvec * dest, uint8_t tfi, uint32_t tlli)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400360{
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400361 // GSM 04.08 10.5.2.16
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400362 unsigned wp = 0;
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400363 bitvec_write_field(dest, wp, 3, 2); // "HH"
364 bitvec_write_field(dest, wp, 1, 2); // "01" Packet Downlink Assignment
365 bitvec_write_field(dest, wp,tlli,32); // TLLI
366 bitvec_write_field(dest, wp,0x1,1); // switch TFI : on
367 bitvec_write_field(dest, wp,tfi,5); // TFI
368 bitvec_write_field(dest, wp,0x0,1); // RLC acknowledged mode
369 bitvec_write_field(dest, wp,0x0,1); // ALPHA = present
370 bitvec_write_field(dest, wp,0x0,5); // GAMMA power control parameter
371 bitvec_write_field(dest, wp,0x0,1); // Polling Bit
372 bitvec_write_field(dest, wp,0x1,1); // TA_VALID ???
373 bitvec_write_field(dest, wp,0x1,1); // switch TIMING_ADVANCE_INDEX = on
374 bitvec_write_field(dest, wp,0x0,4); // TIMING_ADVANCE_INDEX
375 bitvec_write_field(dest, wp,0x0,1); // TBF Starting TIME present
376 bitvec_write_field(dest, wp,0x0,1); // P0 not present
377 bitvec_write_field(dest, wp,0x1,1); // P0 not present
378 bitvec_write_field(dest, wp,0xb,4);
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400379}
380
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400381void write_packet_uplink_ack(bitvec * dest, uint8_t tfi, uint32_t tlli, unsigned cv, unsigned bsn)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400382{
383 // TODO We should use our implementation of encode RLC/MAC Control messages.
384 unsigned wp = 0;
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400385 bitvec_write_field(dest, wp,0x1,2); // payload
386 bitvec_write_field(dest, wp,0x0,2); // Uplink block with TDMA framenumber
387 if (cv == 0) bitvec_write_field(dest, wp,0x1,1); // Suppl/Polling Bit
388 else bitvec_write_field(dest, wp,0x0,1); //Suppl/Polling Bit
389 bitvec_write_field(dest, wp,0x1,3); // Uplink state flag
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400390
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400391 //bitvec_write_field(dest, wp,0x0,1); // Reduced block sequence number
392 //bitvec_write_field(dest, wp,BSN+6,5); // Radio transaction identifier
393 //bitvec_write_field(dest, wp,0x1,1); // Final segment
394 //bitvec_write_field(dest, wp,0x1,1); // Address control
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400395
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400396 //bitvec_write_field(dest, wp,0x0,2); // Power reduction: 0
397 //bitvec_write_field(dest, wp,TFI,5); // Temporary flow identifier
398 //bitvec_write_field(dest, wp,0x1,1); // Direction
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400399
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400400 bitvec_write_field(dest, wp,0x09,6); // MESSAGE TYPE
401 bitvec_write_field(dest, wp,0x0,2); // Page Mode
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400402
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400403 bitvec_write_field(dest, wp,0x0,2);
404 bitvec_write_field(dest, wp,tfi,5); // Uplink TFI
405 bitvec_write_field(dest, wp,0x0,1);
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400406
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400407 bitvec_write_field(dest, wp,0x0,2); // CS1
408 if (cv == 0) bitvec_write_field(dest, wp,0x1,1); // FINAL_ACK_INDICATION
409 else bitvec_write_field(dest, wp,0x0,1); // FINAL_ACK_INDICATION
410 bitvec_write_field(dest, wp,bsn + 1,7); // STARTING_SEQUENCE_NUMBER
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400411 // RECEIVE_BLOCK_BITMAP
412 for (unsigned i=0; i<8; i++) {
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400413 bitvec_write_field(dest, wp,0xff,8);
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400414 }
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400415 bitvec_write_field(dest, wp,0x1,1); // CONTENTION_RESOLUTION_TLLI = present
416 bitvec_write_field(dest, wp,tlli,8*4);
417 bitvec_write_field(dest, wp,0x00,4); //spare
Ivan Kluchnikov0b450c12012-05-24 22:47:12 +0400418 bitvec_write_field(dest, wp,0x5,4); //0101
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400419}
420
421void gprs_rlcmac_tx_ul_ack(uint8_t tfi, uint32_t tlli, RlcMacUplinkDataBlock_t * ul_data_block)
422{
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400423 bitvec *packet_uplink_ack_vec = bitvec_alloc(23);
424 bitvec_unhex(packet_uplink_ack_vec, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
425 write_packet_uplink_ack(packet_uplink_ack_vec, tfi, tlli, ul_data_block->CV, ul_data_block->BSN);
Ivan Kluchnikova9f1ff22012-05-24 22:25:06 +0400426 LOGP(DRLCMAC, LOGL_NOTICE, "TX: [PCU -> BTS] TFI: %u TLLI: 0x%08x Packet Uplink Ack\n", tfi, tlli);
Ivan Kluchnikov192e9c12012-04-12 15:27:39 +0400427 RlcMacDownlink_t * packet_uplink_ack = (RlcMacDownlink_t *)malloc(sizeof(RlcMacDownlink_t));
Ivan Kluchnikova9f1ff22012-05-24 22:25:06 +0400428 LOGP(DRLCMAC, LOGL_NOTICE, "+++++++++++++++++++++++++ TX : Packet Uplink Ack +++++++++++++++++++++++++\n");
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400429 decode_gsm_rlcmac_downlink(packet_uplink_ack_vec, packet_uplink_ack);
Ivan Kluchnikova9f1ff22012-05-24 22:25:06 +0400430 LOGPC(DRLCMAC, LOGL_NOTICE, "\n");
431 LOGP(DRLCMAC, LOGL_NOTICE, "------------------------- TX : Packet Uplink Ack -------------------------\n");
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400432 free(packet_uplink_ack);
Andreas Eversberg0aed6542012-06-23 10:33:16 +0200433 gprs_rlcmac_enqueue_block(packet_uplink_ack_vec, 23);
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400434 bitvec_free(packet_uplink_ack_vec);
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400435}
436
437void gprs_rlcmac_data_block_parse(gprs_rlcmac_tbf* tbf, RlcMacUplinkDataBlock_t * ul_data_block)
438{
Ivan Kluchnikovbceb3fb2012-06-05 16:56:27 +0400439 // 1. Count the number of octets in header and number of LLC PDU in uplink data block.
440 unsigned data_block_hdr_len = 3; // uplink data block header length: 3 mandatory octets
441 unsigned llc_pdu_num = 0; // number of LLC PDU in data block
442
443
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400444 if (ul_data_block->E_1 == 0) // Extension octet follows immediately
445 {
Ivan Kluchnikovbceb3fb2012-06-05 16:56:27 +0400446 unsigned i = -1;
447 do
Ivan Kluchnikovb2b81002012-06-04 21:57:02 +0400448 {
Ivan Kluchnikovbceb3fb2012-06-05 16:56:27 +0400449 i++;
450 data_block_hdr_len += 1;
451 llc_pdu_num++;
Ivan Kluchnikov2f69acd2012-06-12 12:42:16 +0400452
453 // Singular case, TS 44.060 10.4.14
454 if (ul_data_block->LENGTH_INDICATOR[i] == 0)
455 {
456 break;
457 }
458
Ivan Kluchnikovbceb3fb2012-06-05 16:56:27 +0400459 // New LLC PDU starts after the current LLC PDU and continues until
460 // the end of the RLC information field, no more extension octets.
461 if ((ul_data_block->M[i] == 1)&&(ul_data_block->E[i] == 1))
Ivan Kluchnikovb2b81002012-06-04 21:57:02 +0400462 {
Ivan Kluchnikovbceb3fb2012-06-05 16:56:27 +0400463 llc_pdu_num++;
Ivan Kluchnikovb2b81002012-06-04 21:57:02 +0400464 }
Ivan Kluchnikovbceb3fb2012-06-05 16:56:27 +0400465 } while(ul_data_block->E[i] == 0); // there is another extension octet, which delimits the new LLC PDU
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400466 }
467 else
468 {
Ivan Kluchnikovbceb3fb2012-06-05 16:56:27 +0400469 llc_pdu_num++;
470 }
471 if(ul_data_block->TI == 1) // TLLI field is present
472 {
473 tbf->tlli = ul_data_block->TLLI;
474 data_block_hdr_len += 4; // TLLI length : 4 octets
475 if (ul_data_block->PI == 1) // PFI is present if TI field indicates presence of TLLI
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400476 {
Ivan Kluchnikovbceb3fb2012-06-05 16:56:27 +0400477 data_block_hdr_len += 1; // PFI length : 1 octet
478 }
479 }
480
481 // 2. Extract all LLC PDU from uplink data block and send them to SGSN.
482 unsigned llc_pdu_len = 0;
483 unsigned data_octet_num = 0;
484
485 for (unsigned num = 0; num < llc_pdu_num; num ++)
486 {
487 if (ul_data_block->E_1 == 0) // Extension octet follows immediately
488 {
Ivan Kluchnikov2f69acd2012-06-12 12:42:16 +0400489 // Singular case, TS 44.060 10.4.14
490 if (ul_data_block->LENGTH_INDICATOR[num] == 0)
491 {
492 llc_pdu_len = UL_RLC_DATA_BLOCK_LEN - data_block_hdr_len;
493 }
494 else
495 {
496 llc_pdu_len = ul_data_block->LENGTH_INDICATOR[num];
497 }
Ivan Kluchnikovbceb3fb2012-06-05 16:56:27 +0400498 }
499 else
500 {
501 llc_pdu_len = UL_RLC_DATA_BLOCK_LEN - data_block_hdr_len;
502 }
503
504 for (unsigned i = tbf->data_index; i < tbf->data_index + llc_pdu_len; i++)
505 {
506 tbf->rlc_data[i] = ul_data_block->RLC_DATA[data_octet_num];
507 data_octet_num++;
508 }
509 tbf->data_index += llc_pdu_len;
510
511 if (ul_data_block->E_1 == 0) // Extension octet follows immediately
512 {
513 // New LLC PDU starts after the current LLC PDU
514 if (ul_data_block->M[num] == 1)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400515 {
Ivan Kluchnikovbceb3fb2012-06-05 16:56:27 +0400516 gprs_rlcmac_tx_ul_ud(tbf);
517 tbf->data_index = 0;
518 // New LLC PDU continues until the end of the RLC information field, no more extension octets.
519 if ((ul_data_block->E[num] == 1))
520 {
521 llc_pdu_len = UL_RLC_DATA_BLOCK_LEN - data_block_hdr_len - data_octet_num;
522 for (unsigned i = tbf->data_index; i < tbf->data_index + llc_pdu_len; i++)
523 {
524 tbf->rlc_data[i] = ul_data_block->RLC_DATA[data_octet_num];
525 data_octet_num++;
526 }
527 tbf->data_index += llc_pdu_len;
528 num++;
529 }
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400530 }
531 }
532 }
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400533}
534
535/* Received Uplink RLC data block. */
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400536int gprs_rlcmac_rcv_data_block(bitvec *rlc_block)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400537{
538 struct gprs_rlcmac_tbf *tbf;
539
Ivan Kluchnikova9f1ff22012-05-24 22:25:06 +0400540 LOGP(DRLCMAC, LOGL_NOTICE, "RX: [PCU <- BTS] Uplink Data Block\n");
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400541 RlcMacUplinkDataBlock_t * ul_data_block = (RlcMacUplinkDataBlock_t *)malloc(sizeof(RlcMacUplinkDataBlock_t));
Ivan Kluchnikova9f1ff22012-05-24 22:25:06 +0400542 LOGP(DRLCMAC, LOGL_NOTICE, "+++++++++++++++++++++++++ RX : Uplink Data Block +++++++++++++++++++++++++\n");
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400543 decode_gsm_rlcmac_uplink_data(rlc_block, ul_data_block);
Ivan Kluchnikova9f1ff22012-05-24 22:25:06 +0400544 LOGP(DRLCMAC, LOGL_NOTICE, "------------------------- RX : Uplink Data Block -------------------------\n");
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400545 tbf = tbf_by_tfi(ul_data_block->TFI);
546 if (!tbf) {
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400547 return 0;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400548 }
Ivan Kluchnikovb2b81002012-06-04 21:57:02 +0400549
550 if (ul_data_block->TI == 1)
551 {
552 tbf->tlli = ul_data_block->TLLI;
553 }
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400554
555 switch (tbf->state) {
556 case GPRS_RLCMAC_WAIT_DATA_SEQ_START:
557 if (ul_data_block->BSN == 0) {
558 tbf->data_index = 0;
559 gprs_rlcmac_data_block_parse(tbf, ul_data_block);
560 gprs_rlcmac_tx_ul_ack(tbf->tfi, tbf->tlli, ul_data_block);
Ivan Kluchnikov9c795ab2012-05-24 23:12:59 +0400561 if (ul_data_block->CV == 0) {
562 // Recieved last Data Block in this sequence.
Ivan Kluchnikov63477112012-06-12 18:14:49 +0400563 tbf->state = GPRS_RLCMAC_WAIT_NEXT_DATA_SEQ;
Ivan Kluchnikov9c795ab2012-05-24 23:12:59 +0400564 gprs_rlcmac_tx_ul_ud(tbf);
565 } else {
566 tbf->bsn = ul_data_block->BSN;
567 tbf->state = GPRS_RLCMAC_WAIT_NEXT_DATA_BLOCK;
568 }
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400569 }
570 break;
571 case GPRS_RLCMAC_WAIT_NEXT_DATA_BLOCK:
572 if (tbf->bsn == (ul_data_block->BSN - 1)) {
573 gprs_rlcmac_data_block_parse(tbf, ul_data_block);
574 gprs_rlcmac_tx_ul_ack(tbf->tfi, tbf->tlli, ul_data_block);
575 if (ul_data_block->CV == 0) {
576 // Recieved last Data Block in this sequence.
Ivan Kluchnikov63477112012-06-12 18:14:49 +0400577 tbf->state = GPRS_RLCMAC_WAIT_NEXT_DATA_SEQ;
Ivan Kluchnikov9c795ab2012-05-24 23:12:59 +0400578 gprs_rlcmac_tx_ul_ud(tbf);
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400579 } else {
580 tbf->bsn = ul_data_block->BSN;
581 tbf->state = GPRS_RLCMAC_WAIT_NEXT_DATA_BLOCK;
582 }
583 } else {
584 // Recieved Data Block with unexpected BSN.
585 // We should try to find nesessary Data Block.
586 tbf->state = GPRS_RLCMAC_WAIT_NEXT_DATA_BLOCK;
587 }
588 break;
589 case GPRS_RLCMAC_WAIT_NEXT_DATA_SEQ:
590 // Now we just ignore all Data Blocks and wait next Uplink TBF
591 break;
592 }
593
594 free(ul_data_block);
595 return 1;
596}
597
598/* Received Uplink RLC control block. */
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400599int gprs_rlcmac_rcv_control_block(bitvec *rlc_block)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400600{
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400601 uint8_t tfi = 0;
602 uint32_t tlli = 0;
603 struct gprs_rlcmac_tbf *tbf;
Andreas Eversberg0aed6542012-06-23 10:33:16 +0200604// struct gprs_rlcmac_tbf *ul_tbf;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400605
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400606 RlcMacUplink_t * ul_control_block = (RlcMacUplink_t *)malloc(sizeof(RlcMacUplink_t));
Ivan Kluchnikova9f1ff22012-05-24 22:25:06 +0400607 LOGP(DRLCMAC, LOGL_NOTICE, "+++++++++++++++++++++++++ RX : Uplink Control Block +++++++++++++++++++++++++\n");
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400608 decode_gsm_rlcmac_uplink(rlc_block, ul_control_block);
Ivan Kluchnikova9f1ff22012-05-24 22:25:06 +0400609 LOGPC(DRLCMAC, LOGL_NOTICE, "\n");
610 LOGP(DRLCMAC, LOGL_NOTICE, "------------------------- RX : Uplink Control Block -------------------------\n");
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400611 switch (ul_control_block->u.MESSAGE_TYPE) {
612 case MT_PACKET_CONTROL_ACK:
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400613 tlli = ul_control_block->u.Packet_Control_Acknowledgement.TLLI;
614 tbf = tbf_by_tlli(tlli);
615 if (!tbf) {
616 return 0;
617 }
Ivan Kluchnikov9c795ab2012-05-24 23:12:59 +0400618 LOGP(DRLCMAC, LOGL_NOTICE, "RX: [PCU <- BTS] TFI: %u TLLI: 0x%08x Packet Control Ack\n", tbf->tfi, tbf->tlli);
619 LOGP(DRLCMAC, LOGL_NOTICE, "TBF: [UPLINK] END TFI: %u TLLI: 0x%08x \n", tbf->tfi, tbf->tlli);
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400620 tbf_free(tbf);
621 break;
622 case MT_PACKET_DOWNLINK_ACK_NACK:
623 tfi = ul_control_block->u.Packet_Downlink_Ack_Nack.DOWNLINK_TFI;
624 tbf = tbf_by_tfi(tfi);
625 if (!tbf) {
626 return 0;
627 }
Ivan Kluchnikov9c795ab2012-05-24 23:12:59 +0400628 LOGP(DRLCMAC, LOGL_NOTICE, "RX: [PCU <- BTS] TFI: %u TLLI: 0x%08x Packet Downlink Ack/Nack\n", tbf->tfi, tbf->tlli);
629 tlli = tbf->tlli;
630 LOGP(DRLCMAC, LOGL_NOTICE, "TBF: [DOWNLINK] END TFI: %u TLLI: 0x%08x \n", tbf->tfi, tbf->tlli);
631 tbf_free(tbf);
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400632 break;
633 }
634 free(ul_control_block);
635 return 1;
636}
637
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400638void gprs_rlcmac_rcv_block(bitvec *rlc_block)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400639{
640 unsigned readIndex = 0;
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400641 unsigned payload = bitvec_read_field(rlc_block, readIndex, 2);
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400642
643 switch (payload) {
644 case GPRS_RLCMAC_DATA_BLOCK:
645 gprs_rlcmac_rcv_data_block(rlc_block);
646 break;
647 case GPRS_RLCMAC_CONTROL_BLOCK:
648 gprs_rlcmac_rcv_control_block(rlc_block);
649 break;
650 case GPRS_RLCMAC_CONTROL_BLOCK_OPT:
Ivan Kluchnikov856221f2012-06-15 09:31:29 +0400651 LOGP(DRLCMAC, LOGL_NOTICE, "GPRS_RLCMAC_CONTROL_BLOCK_OPT block payload is not supported.\n");
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400652 default:
Ivan Kluchnikov856221f2012-06-15 09:31:29 +0400653 LOGP(DRLCMAC, LOGL_NOTICE, "Unknown RLCMAC block payload.\n");
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400654 }
655}
656
Andreas Eversberg0aed6542012-06-23 10:33:16 +0200657struct msgb *gen_dummy_msg(void)
658{
659 struct msgb *msg = msgb_alloc(23, "rlcmac_dl_idle");
660 // RLC/MAC filler with USF=1
661 bitvec *filler = bitvec_alloc(23);
662 bitvec_unhex(filler, "41942b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
663 bitvec_pack(filler, msgb_put(msg, 23));
664 bitvec_free(filler);
665 return msg;
666}
667
668void gprs_rlcmac_rcv_rts_block(uint8_t trx, uint8_t ts, uint16_t arfcn,
669 uint32_t fn, uint8_t block_nr)
670{
671 struct msgb *msg;
672
673 set_current_fn(fn);
674 msg = msgb_dequeue(&block_queue);
675 if (!msg)
676 msg = gen_dummy_msg();
677 pcu_l1if_tx_pdtch(msg, trx, ts, arfcn, fn, block_nr);
678}
679
680int select_pdch(uint8_t *_trx, uint8_t *_ts)
681{
682 uint8_t trx, ts;
683
684 for (trx = 0; trx < 8; trx++) {
685 for (ts = 0; ts < 8; ts++) {
686 if (pcu_l1if_bts.trx[trx].ts[ts].enable) {
687 *_trx = trx;
688 *_ts = ts;
689 return 0;
690 }
691 }
692 }
693
694 return -EBUSY;
695}
696
697int gprs_rlcmac_rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta)
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400698{
699 struct gprs_rlcmac_tbf *tbf;
Andreas Eversberg0aed6542012-06-23 10:33:16 +0200700 uint8_t trx, ts;
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400701
Andreas Eversberg0aed6542012-06-23 10:33:16 +0200702 if (select_pdch(&trx, &ts)) {
703 LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n");
704 /* FIXME: send reject */
705 return -EBUSY;
706 }
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400707 // Create new TBF
708 int tfi = tfi_alloc();
709 if (tfi < 0) {
710 return tfi;
711 }
Andreas Eversberg0aed6542012-06-23 10:33:16 +0200712 tbf = tbf_alloc(tfi, trx, ts);
713 if (qta < 0)
714 qta = 0;
715 if (qta > 252)
716 qta = 252;
717 tbf->ta = qta >> 2;
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400718 tbf->direction = GPRS_RLCMAC_UL_TBF;
719 tbf->state = GPRS_RLCMAC_WAIT_DATA_SEQ_START;
Ivan Kluchnikova9f1ff22012-05-24 22:25:06 +0400720 LOGP(DRLCMAC, LOGL_NOTICE, "TBF: [UPLINK] START TFI: %u\n", tbf->tfi);
Andreas Eversberg0aed6542012-06-23 10:33:16 +0200721 LOGP(DRLCMAC, LOGL_NOTICE, "RX: [PCU <- BTS] TFI: %u RACH qbit-ta=%d ra=%d, Fn=%d (%d,%d,%d)\n", tbf->tfi, qta, ra, Fn, (Fn / (26 * 51)) % 32, Fn % 51, Fn % 26);
Ivan Kluchnikova9f1ff22012-05-24 22:25:06 +0400722 LOGP(DRLCMAC, LOGL_NOTICE, "TX: [PCU -> BTS] TFI: %u Packet Immidiate Assignment\n", tbf->tfi);
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400723 bitvec *immediate_assignment = bitvec_alloc(23);
724 bitvec_unhex(immediate_assignment, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
Andreas Eversberg0aed6542012-06-23 10:33:16 +0200725 int len = write_immediate_assignment(immediate_assignment, 0, ra, Fn, tbf->ta, tbf->arfcn, tbf->ts, tbf->tsc, tbf->tfi);
726 pcu_l1if_tx_agch(immediate_assignment, len);
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400727 bitvec_free(immediate_assignment);
Andreas Eversberg0aed6542012-06-23 10:33:16 +0200728
729 return 0;
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400730}
731
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400732// Send RLC data to OpenBTS.
Ivan Kluchnikovc320d862012-03-18 15:04:48 +0400733void gprs_rlcmac_tx_dl_data_block(uint32_t tlli, uint8_t tfi, uint8_t *pdu, int start_index, int end_index, uint8_t bsn, uint8_t fbi)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400734{
735 int spare_len = 0;
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400736 bitvec *data_block_vector = bitvec_alloc(BLOCK_LEN);
737 bitvec_unhex(data_block_vector, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400738 RlcMacDownlinkDataBlock_t * data_block = (RlcMacDownlinkDataBlock_t *)malloc(sizeof(RlcMacDownlinkDataBlock_t));
739 data_block->PAYLOAD_TYPE = 0;
740 data_block->RRBP = 0;
741 data_block->SP = 1;
742 data_block->USF = 1;
743 data_block->PR = 0;
Ivan Kluchnikovc320d862012-03-18 15:04:48 +0400744 data_block->TFI = tfi;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400745 data_block->FBI = fbi;
746 data_block->BSN = bsn;
Ivan Kluchnikove3594232012-06-07 01:12:29 +0400747
748 // Last RLC data block of current LLC PDU
749 if (fbi == 1)
750 {
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400751 data_block->E_1 = 0;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400752 data_block->M[0] = 0;
753 data_block->E[0] = 1;
Ivan Kluchnikove3594232012-06-07 01:12:29 +0400754 // Singular case, TS 44.060 10.4.14
755 if ((end_index - start_index) == (BLOCK_LEN - 3))
756 {
757 data_block->FBI = 0;
758 data_block->LENGTH_INDICATOR[0] = 0;
759 spare_len = 0;
760 end_index--;
761 }
762 else
763 {
764 data_block->LENGTH_INDICATOR[0] = end_index-start_index;
765 spare_len = BLOCK_LEN - 4 - data_block->LENGTH_INDICATOR[0];
766 }
767 }
768 else
769 {
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400770 data_block->E_1 = 1;
771 }
Ivan Kluchnikove3594232012-06-07 01:12:29 +0400772
773 int data_oct_num = 0;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400774 int i = 0;
Ivan Kluchnikove3594232012-06-07 01:12:29 +0400775 // Pack LLC PDU into RLC data field
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400776 for(i = start_index; i < end_index; i++) {
Ivan Kluchnikove3594232012-06-07 01:12:29 +0400777 data_block->RLC_DATA[data_oct_num] = pdu[i];
778 data_oct_num++;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400779 }
Ivan Kluchnikove3594232012-06-07 01:12:29 +0400780 // Fill spare bits
781 for(i = data_oct_num; i < data_oct_num + spare_len; i++) {
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400782 data_block->RLC_DATA[i] = 0x2b;
783 }
Ivan Kluchnikova9f1ff22012-05-24 22:25:06 +0400784 LOGP(DRLCMAC, LOGL_NOTICE, "TX: [PCU -> BTS] Downlink Data Block\n");
785 LOGP(DRLCMAC, LOGL_NOTICE, "+++++++++++++++++++++++++ TX : Downlink Data Block +++++++++++++++++++++++++\n");
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400786 encode_gsm_rlcmac_downlink_data(data_block_vector, data_block);
Ivan Kluchnikova9f1ff22012-05-24 22:25:06 +0400787 LOGP(DRLCMAC, LOGL_NOTICE, "------------------------- TX : Downlink Data Block -------------------------\n");
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400788 free(data_block);
Andreas Eversberg0aed6542012-06-23 10:33:16 +0200789 gprs_rlcmac_enqueue_block(data_block_vector, BLOCK_LEN);
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400790 bitvec_free(data_block_vector);
Ivan Kluchnikove3594232012-06-07 01:12:29 +0400791
792 // Singular case, TS 44.060 10.4.14
793 if ((fbi == 1)&&((end_index + 1 - start_index) == (BLOCK_LEN - 3)))
794 {
795 gprs_rlcmac_tx_dl_data_block(tlli, tfi, pdu, end_index, end_index+1, bsn+1, fbi);
796 }
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400797}
798
799int gprs_rlcmac_segment_llc_pdu(struct gprs_rlcmac_tbf *tbf)
800{
801 int fbi = 0;
Ivan Kluchnikove3594232012-06-07 01:12:29 +0400802 int bsn = 0;
803 int num_blocks = 0; // number of RLC data blocks necessary for LLC PDU transmission
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400804
Ivan Kluchnikove3594232012-06-07 01:12:29 +0400805
806 // LLC PDU fits into one RLC data block with optional LI field.
807 if (tbf->data_index < BLOCK_LEN - 4)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400808 {
Ivan Kluchnikove3594232012-06-07 01:12:29 +0400809 fbi = 1;
810 gprs_rlcmac_tx_dl_data_block(tbf->tlli, tbf->tfi, tbf->rlc_data, 0, tbf->data_index, bsn, fbi);
811 }
812 // Necessary several RLC data blocks for transmit LLC PDU.
813 else
814 {
815 // length of RLC data field in block (no optional octets)
816 int block_data_len = BLOCK_LEN - 3;
817
818 // number of blocks with 20 octets length RLC data field
819 num_blocks = tbf->data_index/block_data_len;
820
821 // rest of LLC PDU, which doesn't fit into data blocks with 20 octets RLC data field
822 int rest_len = tbf->data_index%BLOCK_DATA_LEN;
823 if (rest_len > 0)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400824 {
Ivan Kluchnikove3594232012-06-07 01:12:29 +0400825 // add one block for transmission rest of LLC PDU
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400826 num_blocks++;
827 }
Ivan Kluchnikove3594232012-06-07 01:12:29 +0400828
829 int start_index = 0;
830 int end_index = 0;
831
832 // Transmit all RLC data blocks of current LLC PDU to MS
833 for (bsn = 0; bsn < num_blocks; bsn++)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400834 {
Ivan Kluchnikove3594232012-06-07 01:12:29 +0400835 if (bsn == num_blocks-1)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400836 {
837 if (rest_len > 0)
838 {
839 block_data_len = rest_len;
840 }
841 fbi = 1;
842 }
843 end_index = start_index + block_data_len;
Ivan Kluchnikove3594232012-06-07 01:12:29 +0400844 gprs_rlcmac_tx_dl_data_block(tbf->tlli, tbf->tfi, tbf->rlc_data, start_index, end_index, bsn, fbi);
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400845 start_index += block_data_len;
846 }
847 }
Andreas Eversberg0aed6542012-06-23 10:33:16 +0200848
849 return 0;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400850}
851
852/* Send Uplink unit-data to SGSN. */
853void gprs_rlcmac_tx_ul_ud(gprs_rlcmac_tbf *tbf)
854{
855 const uint8_t qos_profile = QOS_PROFILE;
856 struct msgb *llc_pdu;
857 unsigned msg_len = NS_HDR_LEN + BSSGP_HDR_LEN + tbf->data_index;
858
Ivan Kluchnikovb2b81002012-06-04 21:57:02 +0400859 LOGP(DBSSGP, LOGL_NOTICE, "TX: [PCU -> SGSN ] TFI: %u TLLI: 0x%08x DataLen: %u", tbf->tfi, tbf->tlli, tbf->data_index);
860 //LOGP(DBSSGP, LOGL_NOTICE, " Data = ");
861 //for (unsigned i = 0; i < tbf->data_index; i++)
862 // LOGPC(DBSSGP, LOGL_NOTICE, "%02x ", tbf->rlc_data[i]);
Ivan Kluchnikovc320d862012-03-18 15:04:48 +0400863
864 bctx->cell_id = CELL_ID;
865 bctx->nsei = NSEI;
866 bctx->ra_id.mnc = MNC;
867 bctx->ra_id.mcc = MCC;
868 bctx->ra_id.lac = PCU_LAC;
869 bctx->ra_id.rac = PCU_RAC;
870 bctx->bvci = BVCI;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400871
872 llc_pdu = msgb_alloc_headroom(msg_len, msg_len,"llc_pdu");
873 msgb_tvlv_push(llc_pdu, BSSGP_IE_LLC_PDU, sizeof(uint8_t)*tbf->data_index, tbf->rlc_data);
874 bssgp_tx_ul_ud(bctx, tbf->tlli, &qos_profile, llc_pdu);
875}
876
Ivan Kluchnikovc320d862012-03-18 15:04:48 +0400877void gprs_rlcmac_downlink_assignment(gprs_rlcmac_tbf *tbf)
878{
Ivan Kluchnikova9f1ff22012-05-24 22:25:06 +0400879 LOGP(DRLCMAC, LOGL_NOTICE, "TX: [PCU -> BTS] TFI: %u TLLI: 0x%08x Immidiate Assignment (CCCH)\n", tbf->tfi, tbf->tlli);
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400880 bitvec *immediate_assignment = bitvec_alloc(23);
881 bitvec_unhex(immediate_assignment, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
Andreas Eversberg0aed6542012-06-23 10:33:16 +0200882 int len = write_immediate_assignment(immediate_assignment, 1, 125, get_current_fn(), tbf->ta, tbf->arfcn, tbf->ts, tbf->tsc, tbf->tfi, tbf->tlli);
883 pcu_l1if_tx_agch(immediate_assignment, len);
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400884 bitvec_free(immediate_assignment);
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +0400885 tbf_gsm_timer_start(tbf, 0, 120);
Ivan Kluchnikovc320d862012-03-18 15:04:48 +0400886}
Ivan Kluchnikov9c795ab2012-05-24 23:12:59 +0400887
888void gprs_rlcmac_packet_downlink_assignment(gprs_rlcmac_tbf *tbf)
889{
890 LOGP(DRLCMAC, LOGL_NOTICE, "TX: [PCU -> BTS] TFI: %u TLLI: 0x%08x Packet DL Assignment\n", tbf->tfi, tbf->tlli);
891 bitvec *packet_downlink_assignment_vec = bitvec_alloc(23);
892 bitvec_unhex(packet_downlink_assignment_vec, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
Andreas Eversberg0aed6542012-06-23 10:33:16 +0200893 write_packet_downlink_assignment(packet_downlink_assignment_vec, tbf->tfi, tbf->tlli, tbf->ts, tbf->ta, tbf->tsc);
Ivan Kluchnikov9c795ab2012-05-24 23:12:59 +0400894 RlcMacDownlink_t * packet_downlink_assignment = (RlcMacDownlink_t *)malloc(sizeof(RlcMacDownlink_t));
895 LOGP(DRLCMAC, LOGL_NOTICE, "+++++++++++++++++++++++++ TX : Packet Downlink Assignment +++++++++++++++++++++++++\n");
896 decode_gsm_rlcmac_downlink(packet_downlink_assignment_vec, packet_downlink_assignment);
897 LOGPC(DRLCMAC, LOGL_NOTICE, "\n");
898 LOGP(DRLCMAC, LOGL_NOTICE, "------------------------- TX : Packet Downlink Assignment -------------------------\n");
899 free(packet_downlink_assignment);
Andreas Eversberg0aed6542012-06-23 10:33:16 +0200900 gprs_rlcmac_enqueue_block(packet_downlink_assignment_vec, 23);
Ivan Kluchnikov9c795ab2012-05-24 23:12:59 +0400901 bitvec_free(packet_downlink_assignment_vec);
902 tbf_gsm_timer_start(tbf, 0, 120);
903}