blob: f20fd2f3eb997105e8c295790e334ae2c968a646 [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;
27
28int tfi_alloc()
29{
30 struct gprs_rlcmac_tbf *tbf;
31 uint32_t tfi_map = 0;
32 uint32_t tfi_ind = 0;
33 uint32_t mask = 1;
34 uint8_t i;
35
36 llist_for_each_entry(tbf, &gprs_rlcmac_tbfs, list) {
37 tfi_ind = 1 << tbf->tfi;
38 tfi_map = tfi_map|tfi_ind;
39 }
40
41 for (i = 0; i < 32; i++) {
42 if(((tfi_map >> i) & mask) == 0) {
43 return i;
44 }
45 }
46 return -1;
47}
48
49/* lookup TBF Entity (by TFI) */
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +040050static struct gprs_rlcmac_tbf *tbf_by_tfi(uint8_t tfi, gprs_rlcmac_tbf_direction dir)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +040051{
52 struct gprs_rlcmac_tbf *tbf;
53
54 llist_for_each_entry(tbf, &gprs_rlcmac_tbfs, list) {
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +040055 if ((tbf->tfi == tfi)&&(tbf->direction == dir))
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +040056 return tbf;
57 }
58 return NULL;
59}
60
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +040061static struct gprs_rlcmac_tbf *tbf_by_tlli(uint32_t tlli, gprs_rlcmac_tbf_direction dir)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +040062{
63 struct gprs_rlcmac_tbf *tbf;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +040064 llist_for_each_entry(tbf, &gprs_rlcmac_tbfs, list) {
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +040065 if ((tbf->tlli == tlli)&&(tbf->direction == dir))
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +040066 return tbf;
67 }
68 return NULL;
69}
70
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +040071static void tbf_free(struct gprs_rlcmac_tbf *tbf)
72{
73 llist_del(&tbf->list);
74 talloc_free(tbf);
75}
76
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +040077/* Lookup LLC PDU in TBF list of LLC PDUs by number. */
78static struct tbf_llc_pdu *tbf_llc_pdu_by_num(struct llist_head llc_pdus, uint8_t num)
79{
80 struct tbf_llc_pdu *llc_pdu;
81
82 llist_for_each_entry(llc_pdu, &llc_pdus, list) {
83 if (llc_pdu->num == num)
84 return llc_pdu;
85 }
86 return NULL;
87}
88
89/* Add new LLC PDU to the TBF list of LLC PDUs. */
90int tbf_add_llc_pdu(struct gprs_rlcmac_tbf *tbf, uint8_t *data, uint16_t llc_pdu_len)
91{
92 struct tbf_llc_pdu *llc_pdu;
93
94 llc_pdu = talloc_zero(rlcmac_tall_ctx, struct tbf_llc_pdu);
95 if (!llc_pdu)
96 return 0;
97
98 llc_pdu->num = tbf->llc_pdu_list_len;
99 llc_pdu->len = llc_pdu_len;
100
101 LOGP(DBSSGP, LOGL_NOTICE, "LLC PDU = ");
102 for (unsigned i = 0; i < llc_pdu_len; i++)
103 {
104 llc_pdu->data[i] = data[i];
105 LOGPC(DBSSGP, LOGL_NOTICE, "%02x", llc_pdu->data[i]);
106 }
107 LOGP(DBSSGP, LOGL_NOTICE, "\n");
108
109 llist_add(&llc_pdu->list, &tbf->llc_pdus);
110 tbf->llc_pdu_list_len++;
111 return 1;
112}
113
114struct gprs_rlcmac_tbf *tbf_alloc(gprs_rlcmac_tbf_direction dir, uint32_t tlli)
115{
116 struct gprs_rlcmac_tbf *exist_tbf;
117 struct gprs_rlcmac_tbf *tbf;
118 uint8_t tfi;
119
120 // Downlink TDF allocation
121 if (dir == GPRS_RLCMAC_DL_TBF)
122 {
123 // Try to find already exist DL TBF
124 exist_tbf = tbf_by_tlli(tlli, GPRS_RLCMAC_DL_TBF);
125 if (exist_tbf)
126 {
127 // if DL TBF is in establish or data transfer state,
128 // send additional LLC PDU during current DL TBF.
129 if (exist_tbf->stage != TBF_RELEASE)
130 {
131 if (exist_tbf->state != FINISH_DATA_TRANSFER)
132 {
133 return exist_tbf;
134 }
135 }
136 }
137
138 //Try to find already exist UL TBF
139 exist_tbf = tbf_by_tlli(tlli, GPRS_RLCMAC_UL_TBF);
140 if (exist_tbf)
141 {
142 // if UL TBF is in data transfer state,
143 // establish new DL TBF during current UL TBF.
144 if (exist_tbf->stage == TBF_DATA_TRANSFER && !(exist_tbf->next_tbf))
145 {
146 tbf = talloc_zero(rlcmac_tall_ctx, struct gprs_rlcmac_tbf);
147 if (tbf)
148 {
149 // Create new TBF
150 tfi = tfi_alloc();
151 if (tfi < 0) {
152 return NULL;
153 }
154 tbf->tfi = tfi;
155 tbf->llc_pdus = LLIST_HEAD_INIT(tbf->llc_pdus);
156 tbf->llc_pdu_list_len = 0;
157 tbf->direction = GPRS_RLCMAC_DL_TBF;
158 tbf->stage = TBF_ESTABLISH;
159 tbf->state = WAIT_ESTABLISH;
160 tbf->tlli = tlli;
161 llist_add(&tbf->list, &gprs_rlcmac_tbfs);
162 exist_tbf->next_tbf = tbf;
163 return tbf;
164 }
165 else
166 {
167 return NULL;
168 }
169 }
170 }
171
172 // No UL and DL TBFs for current TLLI are found.
173 if (!exist_tbf)
174 {
175 tbf = talloc_zero(rlcmac_tall_ctx, struct gprs_rlcmac_tbf);
176 if (tbf)
177 {
178 // Create new TBF
179 tfi = tfi_alloc();
180 if (tfi < 0) {
181 return NULL;
182 }
183 tbf->tfi = tfi;
184 tbf->llc_pdus = LLIST_HEAD_INIT(tbf->llc_pdus);
185 tbf->llc_pdu_list_len = 0;
186 tbf->direction = GPRS_RLCMAC_DL_TBF;
187 tbf->stage = TBF_ESTABLISH;
188 tbf->state = CCCH_ESTABLISH;
189 tbf->tlli = tlli;
190 llist_add(&tbf->list, &gprs_rlcmac_tbfs);
191 return tbf;
192 }
193 else
194 {
195 return NULL;
196 }
197 }
198 }
199 else
200 {
201 // Uplink TBF allocation
202 tbf = talloc_zero(rlcmac_tall_ctx, struct gprs_rlcmac_tbf);
203 if (tbf)
204 {
205 // Create new TBF
206 tfi = tfi_alloc();
207 if (tfi < 0) {
208 return NULL;
209 }
210 tbf->tfi = tfi;
211 tbf->llc_pdus = LLIST_HEAD_INIT(tbf->llc_pdus);
212 tbf->llc_pdu_list_len = 0;
213 tbf->direction = GPRS_RLCMAC_UL_TBF;
214 tbf->stage = TBF_ESTABLISH;
215 tbf->state = WAIT_ESTABLISH;
216 tbf->next_tbf = NULL;
217 llist_add(&tbf->list, &gprs_rlcmac_tbfs);
218 return tbf;
219 }
220 else
221 {
222 return NULL;
223 }
224 }
225}
226
227/* Management of uplink TBF establishment. */
228int tbf_ul_establish(struct gprs_rlcmac_tbf *tbf, uint8_t ra, uint32_t Fn, uint16_t ta)
229{
230 if (tbf->direction != GPRS_RLCMAC_UL_TBF)
231 {
232 return -1;
233 }
234
235 if (tbf->stage == TBF_ESTABLISH)
236 {
237 switch (tbf->state) {
238 case WAIT_ESTABLISH:
239 {
240 LOGP(DRLCMAC, LOGL_NOTICE, "TBF: [UPLINK] START TFI: %u\n", tbf->tfi);
241 LOGP(DRLCMAC, LOGL_NOTICE, "RX: [PCU <- BTS] TFI: %u RACH\n", tbf->tfi);
242 LOGP(DRLCMAC, LOGL_NOTICE, "TX: [PCU -> BTS] TFI: %u Packet Immidiate Assignment\n", tbf->tfi);
243 bitvec *immediate_assignment = bitvec_alloc(23);
244 bitvec_unhex(immediate_assignment, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
245 int len = write_immediate_assignment(immediate_assignment, 0, ra, Fn, ta, tbf->tfi);
246 pcu_l1if_tx(immediate_assignment, GsmL1_Sapi_Agch, len);
247 bitvec_free(immediate_assignment);
248 tbf->state = FINISH_ESTABLISH;
249 }
250 break;
251 default:
252 LOGP(DRLCMAC, LOGL_NOTICE, "TBF: [UPLINK] TFI: %u Unexpected TBF state = %u for stage = %u \n",
253 tbf->tfi, tbf->state, tbf->stage);
254 break;
255 }
256 }
257 else
258 {
259 return -1;
260 }
261
262 return 1;
263}
264
265/* Management of downlink TBF establishment. */
266int tbf_dl_establish(struct gprs_rlcmac_tbf *tbf, uint8_t *imsi)
267{
268 if (tbf->direction != GPRS_RLCMAC_DL_TBF)
269 {
270 return -1;
271 }
272
273 if (tbf->stage == TBF_ESTABLISH)
274 {
275 switch (tbf->state) {
276 case WAIT_ESTABLISH:
277 // Wait while UL TBF establishes DL TBF.
278 LOGP(DRLCMAC, LOGL_NOTICE, "TBF: [DOWNLINK] TFI: Wait DL TBF establishment by UL TBF", tbf->tfi);
279 break;
280 case CCCH_ESTABLISH:
281 if (imsi)
282 {
283 // Downlink TBF Establishment on CCCH ( Paging procedure )
284 // TODO: Implement paging procedure on CCCH.
285 LOGP(DRLCMAC, LOGL_NOTICE, "TBF: [DOWNLINK] TFI: Paging procedure on CCCH : Not implemented yet", tbf->tfi);
286 }
287 else
288 {
289 // Downlink TBF Establishment on CCCH ( Immediate Assignment )
290 gprs_rlcmac_downlink_assignment(tbf);
291 }
292 tbf->state = FINISH_ESTABLISH;
293 break;
294 case PACCH_ESTABLISH:
295 // Downlink TBF Establishment on PACCH ( Packet Immediate Assignment )
296 gprs_rlcmac_packet_downlink_assignment(tbf);
297 tbf->state = FINISH_ESTABLISH;
298 break;
299 default:
300 LOGP(DRLCMAC, LOGL_NOTICE, "TBF: [DOWNLINK] TFI: %u Unexpected TBF state = %u for stage = %u \n",
301 tbf->tfi, tbf->state, tbf->stage);
302 break;
303 }
304 }
305 return 1;
306}
307
308/* Management of uplink TBF data transfer. */
309int tbf_ul_data_transfer(struct gprs_rlcmac_tbf *tbf, RlcMacUplinkDataBlock_t * ul_data_block)
310{
311 if ((tbf->stage == TBF_RELEASE)||(tbf->direction != GPRS_RLCMAC_UL_TBF))
312 {
313 return -1;
314 }
315
316 if (tbf->stage == TBF_ESTABLISH)
317 {
318 tbf->stage = TBF_DATA_TRANSFER;
319 tbf->state = WAIT_DATA_TRANSFER;
320 }
321
322 if (ul_data_block->TI == 1)
323 {
324 tbf->tlli = ul_data_block->TLLI;
325 // TODO: Kill all other UL TBFs with this TLLI.
326 }
327
328 switch (tbf->state) {
329 case WAIT_DATA_TRANSFER:
330 if (ul_data_block->BSN == 0)
331 {
332 tbf->data_index = 0;
333 gprs_rlcmac_data_block_parse(tbf, ul_data_block);
334 gprs_rlcmac_tx_ul_ack(tbf->tfi, tbf->tlli, ul_data_block);
335 if (ul_data_block->CV == 0)
336 {
337 // Recieved last Data Block in this sequence.
338 tbf->state = FINISH_DATA_TRANSFER;
339 gprs_rlcmac_tx_ul_ud(tbf);
340 }
341 else
342 {
343 tbf->bsn = ul_data_block->BSN;
344 tbf->state = DATA_TRANSFER;
345 }
346 }
347 break;
348 case DATA_TRANSFER:
349 if (tbf->bsn == (ul_data_block->BSN - 1))
350 {
351 gprs_rlcmac_data_block_parse(tbf, ul_data_block);
352 gprs_rlcmac_tx_ul_ack(tbf->tfi, tbf->tlli, ul_data_block);
353 if (ul_data_block->CV == 0)
354 {
355 // Recieved last Data Block in this sequence.
356 tbf->state = FINISH_DATA_TRANSFER;
357 gprs_rlcmac_tx_ul_ud(tbf);
358 }
359 else
360 {
361 tbf->bsn = ul_data_block->BSN;
362 }
363 }
364 break;
365 case FINISH_DATA_TRANSFER:
366 // Now we just ignore all Data Blocks and wait release of TBF.
367 break;
368 default:
369 LOGP(DRLCMAC, LOGL_NOTICE, "TBF: [UPLINK] TFI: %u Unexpected TBF state = %u for stage = %u \n",
370 tbf->tfi, tbf->state, tbf->stage);
371 break;
372 }
373
374 if ((tbf->state == FINISH_DATA_TRANSFER) && (tbf->next_tbf))
375 {
376 // Establish DL TBF, if it is required.
377 if ((tbf->next_tbf)->state == WAIT_ESTABLISH)
378 {
379 (tbf->next_tbf)->state = PACCH_ESTABLISH;
380 tbf_dl_establish(tbf->next_tbf);
381 }
382 }
383
384 return 1;
385}
386
387/* Management of downlink TBF data transfer. */
388int tbf_dl_data_transfer(struct gprs_rlcmac_tbf *tbf, uint8_t *llc_pdu, uint16_t llc_pdu_len)
389{
390 if ((tbf->stage == TBF_RELEASE) || (tbf->direction != GPRS_RLCMAC_DL_TBF))
391 {
392 return -1;
393 }
394
395 if (llc_pdu_len > 0)
396 {
397 tbf_add_llc_pdu(tbf, llc_pdu, llc_pdu_len);
398 }
399
400 if (tbf->stage == TBF_ESTABLISH)
401 {
402 if (tbf->state == FINISH_ESTABLISH)
403 {
404 tbf->stage = TBF_DATA_TRANSFER;
405 tbf->state = DATA_TRANSFER;
406 }
407 }
408
409 if (tbf->stage == TBF_DATA_TRANSFER)
410 {
411 switch (tbf->state) {
412 case DATA_TRANSFER:
413 gprs_rlcmac_tx_llc_pdus(tbf);
414 tbf->state = FINISH_DATA_TRANSFER;
415 break;
416 default:
417 LOGP(DRLCMAC, LOGL_NOTICE, "TBF: [DOWNLINK] TFI: %u Unexpected TBF state = %u for stage = %u \n",
418 tbf->tfi, tbf->state, tbf->stage);
419 break;
420 }
421 }
422
423 return 1;
424}
425
426/* Management of uplink TBF release. */
427int tbf_ul_release(struct gprs_rlcmac_tbf *tbf)
428{
429 if (tbf->direction != GPRS_RLCMAC_UL_TBF)
430 {
431 return -1;
432 }
433
434 if (tbf->next_tbf)
435 {
436 // UL TBF data transfer is finished, start DL TBF data transfer.
437 tbf_dl_data_transfer(tbf->next_tbf);
438 }
439 tbf->stage = TBF_RELEASE;
440 tbf->state = RELEASE;
441 LOGP(DRLCMAC, LOGL_NOTICE, "TBF: [UPLINK] END TFI: %u TLLI: 0x%08x \n", tbf->tfi, tbf->tlli);
442 tbf_free(tbf);
443 return 1;
444}
445
446/* Management of downlink TBF release. */
447int tbf_dl_release(struct gprs_rlcmac_tbf *tbf)
448{
449 if (tbf->direction != GPRS_RLCMAC_DL_TBF)
450 {
451 return -1;
452 }
453
454 tbf->stage = TBF_RELEASE;
455 tbf->state = RELEASE;
456 LOGP(DRLCMAC, LOGL_NOTICE, "TBF: [DOWNLINK] END TFI: %u TLLI: 0x%08x \n", tbf->tfi, tbf->tlli);
457 tbf_free(tbf);
458 return 1;
459}
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +0400460
461static void tbf_timer_cb(void *_tbf)
462{
463 struct gprs_rlcmac_tbf *tbf = (struct gprs_rlcmac_tbf *)_tbf;
464
465 tbf->num_T_exp++;
466
467 switch (tbf->T) {
468 case 1111:
469 // TODO: We should add timers for TBF.
470 break;
471 default:
Ivan Kluchnikov856221f2012-06-15 09:31:29 +0400472 LOGP(DRLCMAC, LOGL_NOTICE, "Timer expired in unknown mode: %u \n", tbf->T);
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +0400473 }
474}
475
476static void tbf_timer_start(struct gprs_rlcmac_tbf *tbf, unsigned int T,
477 unsigned int seconds)
478{
479 if (osmo_timer_pending(&tbf->timer))
Ivan Kluchnikov856221f2012-06-15 09:31:29 +0400480 LOGP(DRLCMAC, LOGL_NOTICE, "Starting TBF timer %u while old timer %u pending \n", T, tbf->T);
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +0400481 tbf->T = T;
482 tbf->num_T_exp = 0;
483
484 /* FIXME: we should do this only once ? */
485 tbf->timer.data = tbf;
486 tbf->timer.cb = &tbf_timer_cb;
487
488 osmo_timer_schedule(&tbf->timer, seconds, 0);
489}
490
491
492static void tbf_gsm_timer_cb(void *_tbf)
493{
494 struct gprs_rlcmac_tbf *tbf = (struct gprs_rlcmac_tbf *)_tbf;
495
496 tbf->num_fT_exp++;
497
498 switch (tbf->fT) {
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +0400499 case 2:
500 tbf_dl_data_transfer(tbf);
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +0400501 break;
502 default:
Ivan Kluchnikov856221f2012-06-15 09:31:29 +0400503 LOGP(DRLCMAC, LOGL_NOTICE, "Timer expired in unknown mode: %u \n", tbf->fT);
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +0400504 }
505}
506
507static void tbf_gsm_timer_start(struct gprs_rlcmac_tbf *tbf, unsigned int fT,
508 int frames)
509{
510 if (osmo_gsm_timer_pending(&tbf->gsm_timer))
Ivan Kluchnikov856221f2012-06-15 09:31:29 +0400511 LOGP(DRLCMAC, LOGL_NOTICE, "Starting TBF timer %u while old timer %u pending \n", fT, tbf->fT);
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +0400512 tbf->fT = fT;
513 tbf->num_fT_exp = 0;
514
515 /* FIXME: we should do this only once ? */
516 tbf->gsm_timer.data = tbf;
517 tbf->gsm_timer.cb = &tbf_gsm_timer_cb;
518
519 osmo_gsm_timer_schedule(&tbf->gsm_timer, frames);
520}
521
Ivan Kluchnikov0b450c12012-05-24 22:47:12 +0400522void 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 +0400523{
524 // TODO We should use our implementation of encode RLC/MAC Control messages.
525 unsigned wp = 0;
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400526 bitvec_write_field(dest, wp,0x1,2); // Payload Type
527 bitvec_write_field(dest, wp,0x0,2); // Uplink block with TDMA framenumber
528 bitvec_write_field(dest, wp,0x1,1); // Suppl/Polling Bit
529 bitvec_write_field(dest, wp,0x1,3); // Uplink state flag
530 bitvec_write_field(dest, wp,0x2,6); // MESSAGE TYPE
531 bitvec_write_field(dest, wp,0x0,2); // Page Mode
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400532
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400533 bitvec_write_field(dest, wp,0x0,1); // switch PERSIST_LEVEL: off
Ivan Kluchnikov0b450c12012-05-24 22:47:12 +0400534 bitvec_write_field(dest, wp,0x0,1); // switch TFI : on
535 bitvec_write_field(dest, wp,0x0,1); // switch UPLINK TFI : on
536 bitvec_write_field(dest, wp,tfi-1,5); // TFI
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400537
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400538 bitvec_write_field(dest, wp,0x0,1); // Message escape
539 bitvec_write_field(dest, wp,0x0,2); // Medium Access Method: Dynamic Allocation
540 bitvec_write_field(dest, wp,0x0,1); // RLC acknowledged mode
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400541
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400542 bitvec_write_field(dest, wp,0x0,1); // the network establishes no new downlink TBF for the mobile station
543 bitvec_write_field(dest, wp,0x1,8); // timeslot 7
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400544
Ivan Kluchnikov0b450c12012-05-24 22:47:12 +0400545 bitvec_write_field(dest, wp,0x1,1); // switch TIMING_ADVANCE_VALUE = on
546 bitvec_write_field(dest, wp,ta,6); // TIMING_ADVANCE_VALUE
547 bitvec_write_field(dest, wp,0x0,1); // switch TIMING_ADVANCE_INDEX = off
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400548
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400549 bitvec_write_field(dest, wp,0x0,1); // switch POWER CONTROL = off
550 bitvec_write_field(dest, wp,0x1,1); // Frequency Parameters information elements = present
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400551
Ivan Kluchnikov0b450c12012-05-24 22:47:12 +0400552 bitvec_write_field(dest, wp,tsc,3); // Training Sequence Code (TSC) = 2
553 bitvec_write_field(dest, wp,0x0,2); // ARFCN = present
554 bitvec_write_field(dest, wp,599,10); // ARFCN
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400555
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400556 bitvec_write_field(dest, wp,0x1,1); // switch TFI : on
557 bitvec_write_field(dest, wp,tfi,5);// TFI
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400558
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400559 bitvec_write_field(dest, wp,0x1,1); // Power Control Parameters IE = present
560 bitvec_write_field(dest, wp,0x0,4); // ALPHA power control parameter
561 bitvec_write_field(dest, wp,0x0,1); // switch GAMMA_TN0 = off
562 bitvec_write_field(dest, wp,0x0,1); // switch GAMMA_TN1 = off
563 bitvec_write_field(dest, wp,0x0,1); // switch GAMMA_TN2 = off
564 bitvec_write_field(dest, wp,0x0,1); // switch GAMMA_TN3 = off
565 bitvec_write_field(dest, wp,0x0,1); // switch GAMMA_TN4 = off
566 bitvec_write_field(dest, wp,0x0,1); // switch GAMMA_TN5 = off
567 bitvec_write_field(dest, wp,0x0,1); // switch GAMMA_TN6 = off
568 bitvec_write_field(dest, wp,0x1,1); // switch GAMMA_TN7 = on
569 bitvec_write_field(dest, wp,0x0,5); // GAMMA_TN7
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400570
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400571 bitvec_write_field(dest, wp,0x0,1); // TBF Starting TIME IE not present
572 bitvec_write_field(dest, wp,0x0,1); // Measurement Mapping struct not present
Ivan Kluchnikov0b450c12012-05-24 22:47:12 +0400573 bitvec_write_field(dest, wp,0x0,1);
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400574}
575
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400576void write_packet_uplink_assignment(bitvec * dest, uint8_t tfi, uint32_t tlli)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400577{
578 // TODO We should use our implementation of encode RLC/MAC Control messages.
579 unsigned wp = 0;
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400580 bitvec_write_field(dest, wp,0x1,2); // Payload Type
581 bitvec_write_field(dest, wp,0x0,2); // Uplink block with TDMA framenumber
582 bitvec_write_field(dest, wp,0x1,1); // Suppl/Polling Bit
583 bitvec_write_field(dest, wp,0x1,3); // Uplink state flag
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400584
585
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400586 bitvec_write_field(dest, wp,0xa,6); // MESSAGE TYPE
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400587
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400588 bitvec_write_field(dest, wp,0x0,2); // Page Mode
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400589
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400590 bitvec_write_field(dest, wp,0x0,1); // switch PERSIST_LEVEL: off
591 bitvec_write_field(dest, wp,0x2,2); // switch TLLI : on
592 bitvec_write_field(dest, wp,tlli,32); // TLLI
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400593
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400594 bitvec_write_field(dest, wp,0x0,1); // Message escape
595 bitvec_write_field(dest, wp,0x0,2); // CHANNEL_CODING_COMMAND
596 bitvec_write_field(dest, wp,0x0,1); // TLLI_BLOCK_CHANNEL_CODING
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400597
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400598 bitvec_write_field(dest, wp,0x1,1); // switch TIMING_ADVANCE_VALUE = on
599 bitvec_write_field(dest, wp,0x0,6); // TIMING_ADVANCE_VALUE
600 bitvec_write_field(dest, wp,0x0,1); // switch TIMING_ADVANCE_INDEX = off
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400601
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400602 bitvec_write_field(dest, wp,0x0,1); // Frequency Parameters = off
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400603
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400604 bitvec_write_field(dest, wp,0x1,2); // Dynamic Allocation = off
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400605
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400606 bitvec_write_field(dest, wp,0x0,1); // Dynamic Allocation
607 bitvec_write_field(dest, wp,0x0,1); // P0 = off
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400608
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400609 bitvec_write_field(dest, wp,0x1,1); // USF_GRANULARITY
610 bitvec_write_field(dest, wp,0x1,1); // switch TFI : on
611 bitvec_write_field(dest, wp,tfi,5);// TFI
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400612
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400613 bitvec_write_field(dest, wp,0x0,1); //
614 bitvec_write_field(dest, wp,0x0,1); // TBF Starting Time = off
615 bitvec_write_field(dest, wp,0x0,1); // Timeslot Allocation
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400616
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400617 bitvec_write_field(dest, wp,0x0,5); // USF_TN 0 - 4
618 bitvec_write_field(dest, wp,0x1,1); // USF_TN 5
619 bitvec_write_field(dest, wp,0x1,3); // USF_TN 5
620 bitvec_write_field(dest, wp,0x0,2); // USF_TN 6 - 7
621// bitvec_write_field(dest, wp,0x0,1); // Measurement Mapping struct not present
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400622}
623
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400624// GSM 04.08 9.1.18 Immediate assignment
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400625int write_immediate_assignment(bitvec * dest, uint8_t downlink, uint8_t ra, uint32_t fn,
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +0400626 uint8_t ta, uint8_t tfi, uint32_t tlli)
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400627{
628 unsigned wp = 0;
629
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400630 bitvec_write_field(dest, wp,0x0,4); // Skip Indicator
631 bitvec_write_field(dest, wp,0x6,4); // Protocol Discriminator
632 bitvec_write_field(dest, wp,0x3F,8); // Immediate Assignment Message Type
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400633
634 // 10.5.2.25b Dedicated mode or TBF
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400635 bitvec_write_field(dest, wp,0x0,1); // spare
636 bitvec_write_field(dest, wp,0x0,1); // TMA : Two-message assignment: No meaning
637 bitvec_write_field(dest, wp,downlink,1); // Downlink : Downlink assignment to mobile in packet idle mode
638 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 +0400639
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400640 bitvec_write_field(dest, wp,0x0,4); // Page Mode
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400641
642 // GSM 04.08 10.5.2.25a Packet Channel Description
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400643 bitvec_write_field(dest, wp,0x1,5); // Channel type
644 bitvec_write_field(dest, wp,(l1fh->fl1h)->channel_info.tn,3); // TN
645 bitvec_write_field(dest, wp,(l1fh->fl1h)->channel_info.tsc,3); // TSC
646 bitvec_write_field(dest, wp,0x0,3); // non-hopping RF channel configuraion
647 bitvec_write_field(dest, wp,(l1fh->fl1h)->channel_info.arfcn,10); // ARFCN
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400648
649 //10.5.2.30 Request Reference
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400650 bitvec_write_field(dest, wp,ra,8); // RA
651 bitvec_write_field(dest, wp,(fn / (26 * 51)) % 32,5); // T1'
652 bitvec_write_field(dest, wp,fn % 51,6); // T3
653 bitvec_write_field(dest, wp,fn % 26,5); // T2
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400654
655 // 10.5.2.40 Timing Advance
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400656 bitvec_write_field(dest, wp,0x0,2); // spare
657 bitvec_write_field(dest, wp,ta,6); // Timing Advance value
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400658
659 // No mobile allocation in non-hopping systems.
660 // A zero-length LV. Just write L=0.
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400661 bitvec_write_field(dest, wp,0,8);
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400662
663 if (downlink)
664 {
665 // GSM 04.08 10.5.2.16 IA Rest Octets
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400666 bitvec_write_field(dest, wp, 3, 2); // "HH"
667 bitvec_write_field(dest, wp, 1, 2); // "01" Packet Downlink Assignment
668 bitvec_write_field(dest, wp,tlli,32); // TLLI
669 bitvec_write_field(dest, wp,0x1,1); // switch TFI : on
670 bitvec_write_field(dest, wp,tfi,5); // TFI
671 bitvec_write_field(dest, wp,0x0,1); // RLC acknowledged mode
672 bitvec_write_field(dest, wp,0x0,1); // ALPHA = present
673 bitvec_write_field(dest, wp,0x0,5); // GAMMA power control parameter
674 bitvec_write_field(dest, wp,0x0,1); // Polling Bit
675 bitvec_write_field(dest, wp,0x1,1); // TA_VALID ???
676 bitvec_write_field(dest, wp,0x1,1); // switch TIMING_ADVANCE_INDEX = on
677 bitvec_write_field(dest, wp,0x0,4); // TIMING_ADVANCE_INDEX
678 bitvec_write_field(dest, wp,0x0,1); // TBF Starting TIME present
679 bitvec_write_field(dest, wp,0x0,1); // P0 not present
680 bitvec_write_field(dest, wp,0x1,1); // P0 not present
681 bitvec_write_field(dest, wp,0xb,4);
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400682 }
683 else
684 {
685 // GMS 04.08 10.5.2.37b 10.5.2.16
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400686 bitvec_write_field(dest, wp, 3, 2); // "HH"
687 bitvec_write_field(dest, wp, 0, 2); // "0" Packet Uplink Assignment
688 bitvec_write_field(dest, wp, 1, 1); // Block Allocation : Not Single Block Allocation
689 bitvec_write_field(dest, wp, tfi, 5); // TFI_ASSIGNMENT Temporary Flow Identity
690 bitvec_write_field(dest, wp, 0, 1); // POLLING
691 bitvec_write_field(dest, wp, 0, 1); // ALLOCATION_TYPE: dynamic
692 bitvec_write_field(dest, wp, 1, 3); // USF
693 bitvec_write_field(dest, wp, 1, 1); // USF_GRANULARITY
694 bitvec_write_field(dest, wp, 0 , 1); // "0" power control: Not Present
695 bitvec_write_field(dest, wp, 0, 2); // CHANNEL_CODING_COMMAND
696 bitvec_write_field(dest, wp, 1, 1); // TLLI_BLOCK_CHANNEL_CODING
697 bitvec_write_field(dest, wp, 1 , 1); // "1" Alpha : Present
698 bitvec_write_field(dest, wp, 0, 4); // Alpha
699 bitvec_write_field(dest, wp, 0, 5); // Gamma
700 bitvec_write_field(dest, wp, 0, 1); // TIMING_ADVANCE_INDEX_FLAG
701 bitvec_write_field(dest, wp, 0, 1); // TBF_STARTING_TIME_FLAG
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400702 }
703
704 if (wp%8)
705 return wp/8+1;
706 else
707 return wp/8;
708}
709
710
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400711void write_ia_rest_octets_downlink_assignment(bitvec * dest, uint8_t tfi, uint32_t tlli)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400712{
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400713 // GSM 04.08 10.5.2.16
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400714 unsigned wp = 0;
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400715 bitvec_write_field(dest, wp, 3, 2); // "HH"
716 bitvec_write_field(dest, wp, 1, 2); // "01" Packet Downlink Assignment
717 bitvec_write_field(dest, wp,tlli,32); // TLLI
718 bitvec_write_field(dest, wp,0x1,1); // switch TFI : on
719 bitvec_write_field(dest, wp,tfi,5); // TFI
720 bitvec_write_field(dest, wp,0x0,1); // RLC acknowledged mode
721 bitvec_write_field(dest, wp,0x0,1); // ALPHA = present
722 bitvec_write_field(dest, wp,0x0,5); // GAMMA power control parameter
723 bitvec_write_field(dest, wp,0x0,1); // Polling Bit
724 bitvec_write_field(dest, wp,0x1,1); // TA_VALID ???
725 bitvec_write_field(dest, wp,0x1,1); // switch TIMING_ADVANCE_INDEX = on
726 bitvec_write_field(dest, wp,0x0,4); // TIMING_ADVANCE_INDEX
727 bitvec_write_field(dest, wp,0x0,1); // TBF Starting TIME present
728 bitvec_write_field(dest, wp,0x0,1); // P0 not present
729 bitvec_write_field(dest, wp,0x1,1); // P0 not present
730 bitvec_write_field(dest, wp,0xb,4);
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400731}
732
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400733void write_packet_uplink_ack(bitvec * dest, uint8_t tfi, uint32_t tlli, unsigned cv, unsigned bsn)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400734{
735 // TODO We should use our implementation of encode RLC/MAC Control messages.
736 unsigned wp = 0;
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400737 bitvec_write_field(dest, wp,0x1,2); // payload
738 bitvec_write_field(dest, wp,0x0,2); // Uplink block with TDMA framenumber
739 if (cv == 0) bitvec_write_field(dest, wp,0x1,1); // Suppl/Polling Bit
740 else bitvec_write_field(dest, wp,0x0,1); //Suppl/Polling Bit
741 bitvec_write_field(dest, wp,0x1,3); // Uplink state flag
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400742
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400743 //bitvec_write_field(dest, wp,0x0,1); // Reduced block sequence number
744 //bitvec_write_field(dest, wp,BSN+6,5); // Radio transaction identifier
745 //bitvec_write_field(dest, wp,0x1,1); // Final segment
746 //bitvec_write_field(dest, wp,0x1,1); // Address control
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400747
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400748 //bitvec_write_field(dest, wp,0x0,2); // Power reduction: 0
749 //bitvec_write_field(dest, wp,TFI,5); // Temporary flow identifier
750 //bitvec_write_field(dest, wp,0x1,1); // Direction
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400751
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400752 bitvec_write_field(dest, wp,0x09,6); // MESSAGE TYPE
753 bitvec_write_field(dest, wp,0x0,2); // Page Mode
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400754
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400755 bitvec_write_field(dest, wp,0x0,2);
756 bitvec_write_field(dest, wp,tfi,5); // Uplink TFI
757 bitvec_write_field(dest, wp,0x0,1);
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400758
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400759 bitvec_write_field(dest, wp,0x0,2); // CS1
760 if (cv == 0) bitvec_write_field(dest, wp,0x1,1); // FINAL_ACK_INDICATION
761 else bitvec_write_field(dest, wp,0x0,1); // FINAL_ACK_INDICATION
762 bitvec_write_field(dest, wp,bsn + 1,7); // STARTING_SEQUENCE_NUMBER
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400763 // RECEIVE_BLOCK_BITMAP
764 for (unsigned i=0; i<8; i++) {
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400765 bitvec_write_field(dest, wp,0xff,8);
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400766 }
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400767 bitvec_write_field(dest, wp,0x1,1); // CONTENTION_RESOLUTION_TLLI = present
768 bitvec_write_field(dest, wp,tlli,8*4);
769 bitvec_write_field(dest, wp,0x00,4); //spare
Ivan Kluchnikov0b450c12012-05-24 22:47:12 +0400770 bitvec_write_field(dest, wp,0x5,4); //0101
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400771}
772
773void gprs_rlcmac_tx_ul_ack(uint8_t tfi, uint32_t tlli, RlcMacUplinkDataBlock_t * ul_data_block)
774{
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400775 bitvec *packet_uplink_ack_vec = bitvec_alloc(23);
776 bitvec_unhex(packet_uplink_ack_vec, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
777 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 +0400778 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 +0400779 RlcMacDownlink_t * packet_uplink_ack = (RlcMacDownlink_t *)malloc(sizeof(RlcMacDownlink_t));
Ivan Kluchnikova9f1ff22012-05-24 22:25:06 +0400780 LOGP(DRLCMAC, LOGL_NOTICE, "+++++++++++++++++++++++++ TX : Packet Uplink Ack +++++++++++++++++++++++++\n");
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400781 decode_gsm_rlcmac_downlink(packet_uplink_ack_vec, packet_uplink_ack);
Ivan Kluchnikova9f1ff22012-05-24 22:25:06 +0400782 LOGPC(DRLCMAC, LOGL_NOTICE, "\n");
783 LOGP(DRLCMAC, LOGL_NOTICE, "------------------------- TX : Packet Uplink Ack -------------------------\n");
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400784 free(packet_uplink_ack);
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400785 pcu_l1if_tx(packet_uplink_ack_vec, GsmL1_Sapi_Pacch);
786 bitvec_free(packet_uplink_ack_vec);
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400787}
788
789void gprs_rlcmac_data_block_parse(gprs_rlcmac_tbf* tbf, RlcMacUplinkDataBlock_t * ul_data_block)
790{
Ivan Kluchnikovbceb3fb2012-06-05 16:56:27 +0400791 // 1. Count the number of octets in header and number of LLC PDU in uplink data block.
792 unsigned data_block_hdr_len = 3; // uplink data block header length: 3 mandatory octets
793 unsigned llc_pdu_num = 0; // number of LLC PDU in data block
794
795
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400796 if (ul_data_block->E_1 == 0) // Extension octet follows immediately
797 {
Ivan Kluchnikovbceb3fb2012-06-05 16:56:27 +0400798 unsigned i = -1;
799 do
Ivan Kluchnikovb2b81002012-06-04 21:57:02 +0400800 {
Ivan Kluchnikovbceb3fb2012-06-05 16:56:27 +0400801 i++;
802 data_block_hdr_len += 1;
803 llc_pdu_num++;
Ivan Kluchnikov2f69acd2012-06-12 12:42:16 +0400804
805 // Singular case, TS 44.060 10.4.14
806 if (ul_data_block->LENGTH_INDICATOR[i] == 0)
807 {
808 break;
809 }
810
Ivan Kluchnikovbceb3fb2012-06-05 16:56:27 +0400811 // New LLC PDU starts after the current LLC PDU and continues until
812 // the end of the RLC information field, no more extension octets.
813 if ((ul_data_block->M[i] == 1)&&(ul_data_block->E[i] == 1))
Ivan Kluchnikovb2b81002012-06-04 21:57:02 +0400814 {
Ivan Kluchnikovbceb3fb2012-06-05 16:56:27 +0400815 llc_pdu_num++;
Ivan Kluchnikovb2b81002012-06-04 21:57:02 +0400816 }
Ivan Kluchnikovbceb3fb2012-06-05 16:56:27 +0400817 } 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 +0400818 }
819 else
820 {
Ivan Kluchnikovbceb3fb2012-06-05 16:56:27 +0400821 llc_pdu_num++;
822 }
823 if(ul_data_block->TI == 1) // TLLI field is present
824 {
825 tbf->tlli = ul_data_block->TLLI;
826 data_block_hdr_len += 4; // TLLI length : 4 octets
827 if (ul_data_block->PI == 1) // PFI is present if TI field indicates presence of TLLI
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400828 {
Ivan Kluchnikovbceb3fb2012-06-05 16:56:27 +0400829 data_block_hdr_len += 1; // PFI length : 1 octet
830 }
831 }
832
833 // 2. Extract all LLC PDU from uplink data block and send them to SGSN.
834 unsigned llc_pdu_len = 0;
835 unsigned data_octet_num = 0;
836
837 for (unsigned num = 0; num < llc_pdu_num; num ++)
838 {
839 if (ul_data_block->E_1 == 0) // Extension octet follows immediately
840 {
Ivan Kluchnikov2f69acd2012-06-12 12:42:16 +0400841 // Singular case, TS 44.060 10.4.14
842 if (ul_data_block->LENGTH_INDICATOR[num] == 0)
843 {
844 llc_pdu_len = UL_RLC_DATA_BLOCK_LEN - data_block_hdr_len;
845 }
846 else
847 {
848 llc_pdu_len = ul_data_block->LENGTH_INDICATOR[num];
849 }
Ivan Kluchnikovbceb3fb2012-06-05 16:56:27 +0400850 }
851 else
852 {
853 llc_pdu_len = UL_RLC_DATA_BLOCK_LEN - data_block_hdr_len;
854 }
855
856 for (unsigned i = tbf->data_index; i < tbf->data_index + llc_pdu_len; i++)
857 {
858 tbf->rlc_data[i] = ul_data_block->RLC_DATA[data_octet_num];
859 data_octet_num++;
860 }
861 tbf->data_index += llc_pdu_len;
862
863 if (ul_data_block->E_1 == 0) // Extension octet follows immediately
864 {
865 // New LLC PDU starts after the current LLC PDU
866 if (ul_data_block->M[num] == 1)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400867 {
Ivan Kluchnikovbceb3fb2012-06-05 16:56:27 +0400868 gprs_rlcmac_tx_ul_ud(tbf);
869 tbf->data_index = 0;
870 // New LLC PDU continues until the end of the RLC information field, no more extension octets.
871 if ((ul_data_block->E[num] == 1))
872 {
873 llc_pdu_len = UL_RLC_DATA_BLOCK_LEN - data_block_hdr_len - data_octet_num;
874 for (unsigned i = tbf->data_index; i < tbf->data_index + llc_pdu_len; i++)
875 {
876 tbf->rlc_data[i] = ul_data_block->RLC_DATA[data_octet_num];
877 data_octet_num++;
878 }
879 tbf->data_index += llc_pdu_len;
880 num++;
881 }
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400882 }
883 }
884 }
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400885}
886
887/* Received Uplink RLC data block. */
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400888int gprs_rlcmac_rcv_data_block(bitvec *rlc_block)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400889{
890 struct gprs_rlcmac_tbf *tbf;
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +0400891 int rc = 0;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400892
Ivan Kluchnikova9f1ff22012-05-24 22:25:06 +0400893 LOGP(DRLCMAC, LOGL_NOTICE, "RX: [PCU <- BTS] Uplink Data Block\n");
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400894 RlcMacUplinkDataBlock_t * ul_data_block = (RlcMacUplinkDataBlock_t *)malloc(sizeof(RlcMacUplinkDataBlock_t));
Ivan Kluchnikova9f1ff22012-05-24 22:25:06 +0400895 LOGP(DRLCMAC, LOGL_NOTICE, "+++++++++++++++++++++++++ RX : Uplink Data Block +++++++++++++++++++++++++\n");
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400896 decode_gsm_rlcmac_uplink_data(rlc_block, ul_data_block);
Ivan Kluchnikova9f1ff22012-05-24 22:25:06 +0400897 LOGP(DRLCMAC, LOGL_NOTICE, "------------------------- RX : Uplink Data Block -------------------------\n");
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +0400898
899 tbf = tbf_by_tfi(ul_data_block->TFI, GPRS_RLCMAC_UL_TBF);
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400900 if (!tbf) {
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +0400901 return -1;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400902 }
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +0400903
904 rc = tbf_ul_data_transfer(tbf, ul_data_block);
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400905 free(ul_data_block);
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +0400906 return rc;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400907}
908
909/* Received Uplink RLC control block. */
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400910int gprs_rlcmac_rcv_control_block(bitvec *rlc_block)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400911{
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400912 uint8_t tfi = 0;
913 uint32_t tlli = 0;
914 struct gprs_rlcmac_tbf *tbf;
915
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400916 RlcMacUplink_t * ul_control_block = (RlcMacUplink_t *)malloc(sizeof(RlcMacUplink_t));
Ivan Kluchnikova9f1ff22012-05-24 22:25:06 +0400917 LOGP(DRLCMAC, LOGL_NOTICE, "+++++++++++++++++++++++++ RX : Uplink Control Block +++++++++++++++++++++++++\n");
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400918 decode_gsm_rlcmac_uplink(rlc_block, ul_control_block);
Ivan Kluchnikova9f1ff22012-05-24 22:25:06 +0400919 LOGPC(DRLCMAC, LOGL_NOTICE, "\n");
920 LOGP(DRLCMAC, LOGL_NOTICE, "------------------------- RX : Uplink Control Block -------------------------\n");
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400921 switch (ul_control_block->u.MESSAGE_TYPE) {
922 case MT_PACKET_CONTROL_ACK:
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400923 tlli = ul_control_block->u.Packet_Control_Acknowledgement.TLLI;
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +0400924 tbf = tbf_by_tlli(tlli, GPRS_RLCMAC_UL_TBF);
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400925 if (!tbf) {
926 return 0;
927 }
Ivan Kluchnikov9c795ab2012-05-24 23:12:59 +0400928 LOGP(DRLCMAC, LOGL_NOTICE, "RX: [PCU <- BTS] TFI: %u TLLI: 0x%08x Packet Control Ack\n", tbf->tfi, tbf->tlli);
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +0400929 tbf_ul_release(tbf);
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400930 break;
931 case MT_PACKET_DOWNLINK_ACK_NACK:
932 tfi = ul_control_block->u.Packet_Downlink_Ack_Nack.DOWNLINK_TFI;
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +0400933 tbf = tbf_by_tfi(tfi, GPRS_RLCMAC_DL_TBF);
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400934 if (!tbf) {
935 return 0;
936 }
Ivan Kluchnikov9c795ab2012-05-24 23:12:59 +0400937 LOGP(DRLCMAC, LOGL_NOTICE, "RX: [PCU <- BTS] TFI: %u TLLI: 0x%08x Packet Downlink Ack/Nack\n", tbf->tfi, tbf->tlli);
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +0400938 tbf_dl_release(tbf);
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400939 break;
940 }
941 free(ul_control_block);
942 return 1;
943}
944
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400945void gprs_rlcmac_rcv_block(bitvec *rlc_block)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400946{
947 unsigned readIndex = 0;
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400948 unsigned payload = bitvec_read_field(rlc_block, readIndex, 2);
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400949
950 switch (payload) {
951 case GPRS_RLCMAC_DATA_BLOCK:
952 gprs_rlcmac_rcv_data_block(rlc_block);
953 break;
954 case GPRS_RLCMAC_CONTROL_BLOCK:
955 gprs_rlcmac_rcv_control_block(rlc_block);
956 break;
957 case GPRS_RLCMAC_CONTROL_BLOCK_OPT:
Ivan Kluchnikov856221f2012-06-15 09:31:29 +0400958 LOGP(DRLCMAC, LOGL_NOTICE, "GPRS_RLCMAC_CONTROL_BLOCK_OPT block payload is not supported.\n");
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400959 default:
Ivan Kluchnikov856221f2012-06-15 09:31:29 +0400960 LOGP(DRLCMAC, LOGL_NOTICE, "Unknown RLCMAC block payload.\n");
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400961 }
962}
963
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400964int gprs_rlcmac_rcv_rach(uint8_t ra, uint32_t Fn, uint16_t ta)
965{
966 struct gprs_rlcmac_tbf *tbf;
967
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +0400968 static uint8_t prev_ra = 0;
969
970 if (prev_ra == ra)
971 {
972 return -1;
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400973 }
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +0400974
975 tbf = tbf_alloc(GPRS_RLCMAC_UL_TBF);
976
977 return tbf_ul_establish(tbf, ra, Fn, ta);
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400978}
979
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +0400980int gprs_rlcmac_tx_llc_pdus(struct gprs_rlcmac_tbf *tbf)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400981{
982 int fbi = 0;
Ivan Kluchnikove3594232012-06-07 01:12:29 +0400983 int bsn = 0;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400984
Ivan Kluchnikove3594232012-06-07 01:12:29 +0400985
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +0400986 if (tbf->llc_pdu_list_len == 0)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400987 {
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +0400988 return -1;
Ivan Kluchnikove3594232012-06-07 01:12:29 +0400989 }
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +0400990
991 bitvec *data_block_vector = bitvec_alloc(BLOCK_LEN);
992 bitvec_unhex(data_block_vector, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
993 RlcMacDownlinkDataBlock_t * data_block = (RlcMacDownlinkDataBlock_t *)malloc(sizeof(RlcMacDownlinkDataBlock_t));
994
995 struct tbf_llc_pdu *llc_pdu;
996
997 int data_block_ready = 0;
998 unsigned data_oct_num = 0;
999 int llc_pdu_index;
1000 for (unsigned i = 0; i < tbf->llc_pdu_list_len; i++)
Ivan Kluchnikove3594232012-06-07 01:12:29 +04001001 {
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +04001002 llc_pdu = tbf_llc_pdu_by_num(tbf->llc_pdus, i);
1003 if (!llc_pdu)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04001004 {
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +04001005 return -1;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04001006 }
Ivan Kluchnikove3594232012-06-07 01:12:29 +04001007
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +04001008 llc_pdu_index = 0;
Ivan Kluchnikove3594232012-06-07 01:12:29 +04001009
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +04001010 do
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04001011 {
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +04001012 data_block->PAYLOAD_TYPE = 0;
1013 data_block->RRBP = 0;
1014 data_block->SP = 1;
1015 data_block->USF = 1;
1016 data_block->PR = 0;
1017 data_block->TFI = tbf->tfi;
1018 data_block->BSN = bsn;
1019
1020 // Write LLC PDU to Data Block
1021 int j;
1022 for(j = llc_pdu_index; j < llc_pdu->len; j++)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04001023 {
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +04001024 data_block->RLC_DATA[data_oct_num] = llc_pdu->data[j];
1025 data_oct_num++;
1026 llc_pdu_index++;
1027 // RLC data field is completely filled.
1028 if (data_oct_num == BLOCK_LEN - 3)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04001029 {
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +04001030 fbi = 0;
1031 data_block->E_1 = 1;
1032 data_block_ready = 1;
1033 break;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04001034 }
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04001035 }
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +04001036 if(!data_block_ready)
1037 {
1038 data_block->E_1 = 0;
1039 data_block->LENGTH_INDICATOR[0] = data_oct_num;
1040 if ((i+1) == tbf->llc_pdu_list_len)
1041 {
1042 // Current LLC PDU is last in TBF.
1043 data_block->M[0] = 0;
1044 data_block->E[0] = 1;
1045 fbi = 1;
1046 for(unsigned k = data_oct_num; k < BLOCK_LEN - 4; k++)
1047 {
1048 data_block->RLC_DATA[k] = 0x2b;
1049 }
1050 data_block_ready = 1;
1051 }
1052 else
1053 {
1054 // More LLC PDUs should be transmited in this TBF.
1055 data_block->M[0] = 1;
1056 data_block->E[0] = 1;
1057 data_block_ready = 1;
1058 break;
1059 }
1060 }
1061
1062 data_block->FBI = fbi;
1063
1064 if(data_block_ready)
1065 {
1066 LOGP(DRLCMAC, LOGL_NOTICE, "TX: [PCU -> BTS] Downlink Data Block\n");
1067 LOGP(DRLCMAC, LOGL_NOTICE, "+++++++++++++++++++++++++ TX : Downlink Data Block +++++++++++++++++++++++++\n");
1068 encode_gsm_rlcmac_downlink_data(data_block_vector, data_block);
1069 LOGP(DRLCMAC, LOGL_NOTICE, "------------------------- TX : Downlink Data Block -------------------------\n");
1070 pcu_l1if_tx(data_block_vector, GsmL1_Sapi_Pdtch);
1071 bitvec_unhex(data_block_vector, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
1072 bsn++;
1073 data_block_ready = 0;
1074 data_oct_num = 0;
1075 }
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04001076 }
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +04001077 while(llc_pdu->len != llc_pdu_index);
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04001078 }
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04001079}
1080
1081/* Send Uplink unit-data to SGSN. */
1082void gprs_rlcmac_tx_ul_ud(gprs_rlcmac_tbf *tbf)
1083{
1084 const uint8_t qos_profile = QOS_PROFILE;
1085 struct msgb *llc_pdu;
1086 unsigned msg_len = NS_HDR_LEN + BSSGP_HDR_LEN + tbf->data_index;
1087
Ivan Kluchnikovb2b81002012-06-04 21:57:02 +04001088 LOGP(DBSSGP, LOGL_NOTICE, "TX: [PCU -> SGSN ] TFI: %u TLLI: 0x%08x DataLen: %u", tbf->tfi, tbf->tlli, tbf->data_index);
1089 //LOGP(DBSSGP, LOGL_NOTICE, " Data = ");
1090 //for (unsigned i = 0; i < tbf->data_index; i++)
1091 // LOGPC(DBSSGP, LOGL_NOTICE, "%02x ", tbf->rlc_data[i]);
Ivan Kluchnikovc320d862012-03-18 15:04:48 +04001092
1093 bctx->cell_id = CELL_ID;
1094 bctx->nsei = NSEI;
1095 bctx->ra_id.mnc = MNC;
1096 bctx->ra_id.mcc = MCC;
1097 bctx->ra_id.lac = PCU_LAC;
1098 bctx->ra_id.rac = PCU_RAC;
1099 bctx->bvci = BVCI;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04001100
1101 llc_pdu = msgb_alloc_headroom(msg_len, msg_len,"llc_pdu");
1102 msgb_tvlv_push(llc_pdu, BSSGP_IE_LLC_PDU, sizeof(uint8_t)*tbf->data_index, tbf->rlc_data);
1103 bssgp_tx_ul_ud(bctx, tbf->tlli, &qos_profile, llc_pdu);
1104}
1105
Ivan Kluchnikovc320d862012-03-18 15:04:48 +04001106void gprs_rlcmac_downlink_assignment(gprs_rlcmac_tbf *tbf)
1107{
Ivan Kluchnikova9f1ff22012-05-24 22:25:06 +04001108 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 +04001109 bitvec *immediate_assignment = bitvec_alloc(23);
1110 bitvec_unhex(immediate_assignment, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
1111 int len = write_immediate_assignment(immediate_assignment, 1, 125, get_current_fn(), (l1fh->fl1h)->channel_info.ta, tbf->tfi, tbf->tlli);
1112 pcu_l1if_tx(immediate_assignment, GsmL1_Sapi_Agch, len);
1113 bitvec_free(immediate_assignment);
Ivan Kluchnikovc320d862012-03-18 15:04:48 +04001114}
Ivan Kluchnikov9c795ab2012-05-24 23:12:59 +04001115
1116void gprs_rlcmac_packet_downlink_assignment(gprs_rlcmac_tbf *tbf)
1117{
1118 LOGP(DRLCMAC, LOGL_NOTICE, "TX: [PCU -> BTS] TFI: %u TLLI: 0x%08x Packet DL Assignment\n", tbf->tfi, tbf->tlli);
1119 bitvec *packet_downlink_assignment_vec = bitvec_alloc(23);
1120 bitvec_unhex(packet_downlink_assignment_vec, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
1121 write_packet_downlink_assignment(packet_downlink_assignment_vec, tbf->tfi, tbf->tlli, (l1fh->fl1h)->channel_info.tn,
1122 (l1fh->fl1h)->channel_info.ta, (l1fh->fl1h)->channel_info.tsc);
1123 RlcMacDownlink_t * packet_downlink_assignment = (RlcMacDownlink_t *)malloc(sizeof(RlcMacDownlink_t));
1124 LOGP(DRLCMAC, LOGL_NOTICE, "+++++++++++++++++++++++++ TX : Packet Downlink Assignment +++++++++++++++++++++++++\n");
1125 decode_gsm_rlcmac_downlink(packet_downlink_assignment_vec, packet_downlink_assignment);
1126 LOGPC(DRLCMAC, LOGL_NOTICE, "\n");
1127 LOGP(DRLCMAC, LOGL_NOTICE, "------------------------- TX : Packet Downlink Assignment -------------------------\n");
1128 free(packet_downlink_assignment);
1129 pcu_l1if_tx(packet_downlink_assignment_vec, GsmL1_Sapi_Pacch);
1130 bitvec_free(packet_downlink_assignment_vec);
Ivan Kluchnikov9c795ab2012-05-24 23:12:59 +04001131}