blob: a9f4d13446bf155610b6c4e107df9cda114821ae [file] [log] [blame]
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04001/* gprs_rlcmac.cpp
2 *
3 * Copyright (C) 2012 Ivan Klyuchnikov
Andreas Eversberg5dac2f02012-06-27 15:52:04 +02004 * Copyright (C) 2012 Andreas Eversberg <jolly@eversberg.eu>
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21#include <gprs_bssgp_pcu.h>
22#include <pcu_l1_if.h>
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +040023#include <gprs_rlcmac.h>
Ivan Kluchnikov5310d452012-04-17 22:00:31 +040024#include <gsmL1prim.h>
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +040025
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +040026LLIST_HEAD(gprs_rlcmac_tbfs);
27void *rlcmac_tall_ctx;
28
Andreas Eversberg5dac2f02012-06-27 15:52:04 +020029/* FIXME: spread ressources on multiple TRX */
30int tfi_alloc(uint8_t *_trx, uint8_t *_ts)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +040031{
Andreas Eversberg5dac2f02012-06-27 15:52:04 +020032 struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
33 struct gprs_rlcmac_pdch *pdch;
34 uint8_t trx, ts, tfi;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +040035
Andreas Eversberg5dac2f02012-06-27 15:52:04 +020036 for (trx = 0; trx < 8; trx++) {
37 for (ts = 0; ts < 8; ts++) {
38 pdch = &bts->trx[trx].pdch[ts];
39 if (!pdch->enable)
40 continue;
41 break;
42 }
43 if (ts < 8)
44 break;
45 }
46 if (trx == 8) {
47 LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH available.\n");
48 return -EINVAL;
49 }
50
51
52 LOGP(DRLCMAC, LOGL_DEBUG, "Searching for first unallocated TFI: "
53 "TRX=%d TS=%d\n", trx, ts);
54 for (tfi = 0; tfi < 32; tfi++) {
55 if (!pdch->tbf[tfi])
56 break;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +040057 }
58
Andreas Eversberg5dac2f02012-06-27 15:52:04 +020059 if (tfi < 32) {
60 LOGP(DRLCMAC, LOGL_DEBUG, " Found TFI=%d.\n", tfi);
61 *_trx = trx;
62 *_ts = ts;
63 return tfi;
64 }
65 LOGP(DRLCMAC, LOGL_NOTICE, "No TFI available.\n");
66
67 return -1;
68}
69
70int find_free_usf(uint8_t trx, uint8_t ts)
71{
72 struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
73 struct gprs_rlcmac_pdch *pdch;
74 struct gprs_rlcmac_tbf *tbf;
75 uint8_t usf_map = 0;
76 uint8_t tfi, usf;
77
78 if (trx >= 8 || ts >= 8)
79 return -EINVAL;
80 pdch = &bts->trx[trx].pdch[ts];
81
82 /* make map of used USF */
83 for (tfi = 0; tfi < 32; tfi++) {
84 tbf = pdch->tbf[tfi];
85 if (!tbf)
86 continue;
87 if (tbf->direction != GPRS_RLCMAC_UL_TBF)
88 continue;
89 usf_map |= (1 << tbf->dir.ul.usf);
90 }
91
92 /* look for USF, don't use USF=7 */
93 for (usf = 0; usf < 7; usf++) {
94 if (!(usf_map & (1 << usf))) {
95 LOGP(DRLCMAC, LOGL_DEBUG, " Found USF=%d.\n", usf);
96 return usf;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +040097 }
98 }
Andreas Eversberg5dac2f02012-06-27 15:52:04 +020099 LOGP(DRLCMAC, LOGL_NOTICE, "No USF available.\n");
100
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400101 return -1;
102}
103
104/* lookup TBF Entity (by TFI) */
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200105#warning FIXME: use pdch instance by trx and ts, because tfi is local
Andreas Eversberge6228b32012-07-03 13:36:03 +0200106struct gprs_rlcmac_tbf *tbf_by_tfi(uint8_t tfi, int direction)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400107{
108 struct gprs_rlcmac_tbf *tbf;
109
110 llist_for_each_entry(tbf, &gprs_rlcmac_tbfs, list) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200111 if (tbf->state != GPRS_RLCMAC_RELEASING
112 && tbf->tfi == tfi
113 && tbf->direction == direction)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400114 return tbf;
115 }
116 return NULL;
117}
118
Andreas Eversberge6228b32012-07-03 13:36:03 +0200119/* search for active downlink or uplink tbf */
120struct gprs_rlcmac_tbf *tbf_by_tlli(uint32_t tlli, int direction)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400121{
122 struct gprs_rlcmac_tbf *tbf;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400123 llist_for_each_entry(tbf, &gprs_rlcmac_tbfs, list) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200124 if (tbf->state != GPRS_RLCMAC_RELEASING
125 && tbf->tlli == tlli
126 && tbf->direction == direction)
127 return tbf;
128 }
129 return NULL;
130}
131
132#warning FIXME: use pdch instance by trx and ts, because polling is local
133struct gprs_rlcmac_tbf *tbf_by_poll_fn(uint32_t fn)
134{
135 struct gprs_rlcmac_tbf *tbf;
136 llist_for_each_entry(tbf, &gprs_rlcmac_tbfs, list) {
137 if (tbf->state != GPRS_RLCMAC_RELEASING
138 && tbf->poll_state == GPRS_RLCMAC_POLL_SCHED
139 && tbf->poll_fn == fn)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400140 return tbf;
141 }
142 return NULL;
143}
144
Andreas Eversberg0aed6542012-06-23 10:33:16 +0200145struct gprs_rlcmac_tbf *tbf_alloc(uint8_t tfi, uint8_t trx, uint8_t ts)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400146{
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200147 struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
148 struct gprs_rlcmac_pdch *pdch;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400149 struct gprs_rlcmac_tbf *tbf;
150
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200151 LOGP(DRLCMAC, LOGL_INFO, "********** TBF starts here **********\n");
152 LOGP(DRLCMAC, LOGL_INFO, "Allocating TBF with TFI=%d.\n", tfi);
153
154 if (trx >= 8 || ts >= 8 || tfi >= 32)
155 return NULL;
156 pdch = &bts->trx[trx].pdch[ts];
157
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400158 tbf = talloc_zero(rlcmac_tall_ctx, struct gprs_rlcmac_tbf);
159 if (!tbf)
160 return NULL;
161
162 tbf->tfi = tfi;
Andreas Eversberg0aed6542012-06-23 10:33:16 +0200163 tbf->trx = trx;
164 tbf->ts = ts;
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200165 tbf->arfcn = bts->trx[trx].arfcn;
166 tbf->tsc = bts->trx[trx].pdch[ts].tsc;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200167 tbf->pdch = pdch;
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200168 tbf->ws = 64;
169 tbf->sns = 128;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200170 INIT_LLIST_HEAD(&tbf->llc_queue);
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400171 llist_add(&tbf->list, &gprs_rlcmac_tbfs);
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200172 pdch->tbf[tfi] = tbf;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400173
174 return tbf;
175}
176
Andreas Eversberg0aed6542012-06-23 10:33:16 +0200177void tbf_free(struct gprs_rlcmac_tbf *tbf)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400178{
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200179 struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
180 struct gprs_rlcmac_pdch *pdch;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200181 struct msgb *msg;
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200182
Andreas Eversberge6228b32012-07-03 13:36:03 +0200183 LOGP(DRLCMAC, LOGL_INFO, "Free TBF=%d with TLLI=0x%08x.\n", tbf->tfi,
184 tbf->tlli);
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200185 tbf_timer_stop(tbf);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200186 while ((msg = msgb_dequeue(&tbf->llc_queue)))
187 msgb_free(msg);
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200188 pdch = &bts->trx[tbf->trx].pdch[tbf->ts];
189 pdch->tbf[tbf->tfi] = NULL;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400190 llist_del(&tbf->list);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200191 LOGP(DRLCMAC, LOGL_INFO, "********** TBF ends here **********\n");
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400192 talloc_free(tbf);
193}
194
Andreas Eversberge6228b32012-07-03 13:36:03 +0200195const char *tbf_state_name[] = {
196 "NULL",
197 "ASSIGN",
198 "FLOW",
199 "FINISHED",
200 "WAIT RELEASE",
201 "RELEASING",
202};
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +0400203
Andreas Eversberge6228b32012-07-03 13:36:03 +0200204void tbf_new_state(struct gprs_rlcmac_tbf *tbf,
205 enum gprs_rlcmac_tbf_state state)
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +0400206{
Andreas Eversberge6228b32012-07-03 13:36:03 +0200207 LOGP(DRLCMAC, LOGL_INFO, "TBF=%d changes state from %s to %s\n",
208 tbf->tfi, tbf_state_name[tbf->state], tbf_state_name[state]);
209 tbf->state = state;
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +0400210}
211
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200212void tbf_timer_start(struct gprs_rlcmac_tbf *tbf, unsigned int T,
Andreas Eversberge6228b32012-07-03 13:36:03 +0200213 unsigned int seconds, unsigned int microseconds)
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +0400214{
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200215 if (!osmo_timer_pending(&tbf->timer))
Andreas Eversberge6228b32012-07-03 13:36:03 +0200216 LOGP(DRLCMAC, LOGL_DEBUG, "Starting TBF=%d timer %u.\n",
217 tbf->tfi, T);
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200218 else
Andreas Eversberge6228b32012-07-03 13:36:03 +0200219 LOGP(DRLCMAC, LOGL_DEBUG, "Restarting TBF=%d timer %u while "
220 "old timer %u pending \n", tbf->tfi, T, tbf->T);
Ivan Kluchnikov856221f2012-06-15 09:31:29 +0400221
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +0400222 tbf->T = T;
223 tbf->num_T_exp = 0;
224
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200225 /* Tunning timers can be safely re-scheduled. */
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +0400226 tbf->timer.data = tbf;
227 tbf->timer.cb = &tbf_timer_cb;
228
Andreas Eversberge6228b32012-07-03 13:36:03 +0200229 osmo_timer_schedule(&tbf->timer, seconds, microseconds);
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +0400230}
231
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200232void tbf_timer_stop(struct gprs_rlcmac_tbf *tbf)
233{
234 if (osmo_timer_pending(&tbf->timer)) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200235 LOGP(DRLCMAC, LOGL_DEBUG, "Stopping TBF=%d timer %u.\n",
236 tbf->tfi, tbf->T);
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200237 osmo_timer_del(&tbf->timer);
238 }
239}
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +0400240
Andreas Eversberge6228b32012-07-03 13:36:03 +0200241#if 0
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +0400242static void tbf_gsm_timer_cb(void *_tbf)
243{
244 struct gprs_rlcmac_tbf *tbf = (struct gprs_rlcmac_tbf *)_tbf;
245
246 tbf->num_fT_exp++;
247
248 switch (tbf->fT) {
249 case 0:
Andreas Eversberge6228b32012-07-03 13:36:03 +0200250hier alles überdenken
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +0400251 // This is timer for delay RLC/MAC data sending after Downlink Immediate Assignment on CCCH.
252 gprs_rlcmac_segment_llc_pdu(tbf);
Ivan Kluchnikova9f1ff22012-05-24 22:25:06 +0400253 LOGP(DRLCMAC, LOGL_NOTICE, "TBF: [DOWNLINK] END TFI: %u TLLI: 0x%08x \n", tbf->tfi, tbf->tlli);
Ivan Kluchnikov9c795ab2012-05-24 23:12:59 +0400254 tbf_free(tbf);
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +0400255 break;
256 default:
Ivan Kluchnikov856221f2012-06-15 09:31:29 +0400257 LOGP(DRLCMAC, LOGL_NOTICE, "Timer expired in unknown mode: %u \n", tbf->fT);
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +0400258 }
259}
260
261static void tbf_gsm_timer_start(struct gprs_rlcmac_tbf *tbf, unsigned int fT,
262 int frames)
263{
264 if (osmo_gsm_timer_pending(&tbf->gsm_timer))
Ivan Kluchnikov856221f2012-06-15 09:31:29 +0400265 LOGP(DRLCMAC, LOGL_NOTICE, "Starting TBF timer %u while old timer %u pending \n", fT, tbf->fT);
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +0400266 tbf->fT = fT;
267 tbf->num_fT_exp = 0;
268
269 /* FIXME: we should do this only once ? */
270 tbf->gsm_timer.data = tbf;
271 tbf->gsm_timer.cb = &tbf_gsm_timer_cb;
272
273 osmo_gsm_timer_schedule(&tbf->gsm_timer, frames);
274}
275
Andreas Eversberge6228b32012-07-03 13:36:03 +0200276eine stop-funktion, auch im tbf_free aufrufen
277
278#endif
279
280#if 0
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200281void gprs_rlcmac_enqueue_block(bitvec *block, int len)
Andreas Eversberg0aed6542012-06-23 10:33:16 +0200282{
283 struct msgb *msg = msgb_alloc(len, "rlcmac_dl");
284 bitvec_pack(block, msgb_put(msg, len));
285 msgb_enqueue(&block_queue, msg);
286}
Andreas Eversberge6228b32012-07-03 13:36:03 +0200287#endif
Andreas Eversberg0aed6542012-06-23 10:33:16 +0200288
Andreas Eversberge6228b32012-07-03 13:36:03 +0200289/* received RLC/MAC block from L1 */
290int gprs_rlcmac_rcv_block(uint8_t *data, uint8_t len, uint32_t fn)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400291{
Andreas Eversberge6228b32012-07-03 13:36:03 +0200292 unsigned payload = data[0] >> 6;
293 bitvec *block;
294 int rc = 0;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400295
Andreas Eversberge6228b32012-07-03 13:36:03 +0200296 switch (payload) {
297 case GPRS_RLCMAC_DATA_BLOCK:
298 rc = gprs_rlcmac_rcv_data_block_acknowledged(data, len);
299 break;
300 case GPRS_RLCMAC_CONTROL_BLOCK:
301 block = bitvec_alloc(len);
302 if (!block)
303 return -ENOMEM;
304 bitvec_unpack(block, data);
305 rc = gprs_rlcmac_rcv_control_block(block, fn);
306 bitvec_free(block);
307 break;
308 case GPRS_RLCMAC_CONTROL_BLOCK_OPT:
309 LOGP(DRLCMAC, LOGL_NOTICE, "GPRS_RLCMAC_CONTROL_BLOCK_OPT block payload is not supported.\n");
310 default:
311 LOGP(DRLCMAC, LOGL_NOTICE, "Unknown RLCMAC block payload.\n");
312 rc = -EINVAL;
313 }
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400314
Andreas Eversberge6228b32012-07-03 13:36:03 +0200315 return rc;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400316}
317
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400318// GSM 04.08 9.1.18 Immediate assignment
Andreas Eversberge6228b32012-07-03 13:36:03 +0200319int write_immediate_assignment(bitvec * dest, uint8_t downlink, uint8_t ra,
320 uint32_t fn, uint8_t ta, uint16_t arfcn, uint8_t ts, uint8_t tsc,
321 uint8_t tfi, uint8_t usf, uint32_t tlli,
322 uint8_t polling, uint32_t poll_fn)
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400323{
324 unsigned wp = 0;
325
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400326 bitvec_write_field(dest, wp,0x0,4); // Skip Indicator
327 bitvec_write_field(dest, wp,0x6,4); // Protocol Discriminator
328 bitvec_write_field(dest, wp,0x3F,8); // Immediate Assignment Message Type
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400329
330 // 10.5.2.25b Dedicated mode or TBF
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400331 bitvec_write_field(dest, wp,0x0,1); // spare
332 bitvec_write_field(dest, wp,0x0,1); // TMA : Two-message assignment: No meaning
333 bitvec_write_field(dest, wp,downlink,1); // Downlink : Downlink assignment to mobile in packet idle mode
334 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 +0400335
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400336 bitvec_write_field(dest, wp,0x0,4); // Page Mode
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400337
338 // GSM 04.08 10.5.2.25a Packet Channel Description
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400339 bitvec_write_field(dest, wp,0x1,5); // Channel type
Andreas Eversberg0aed6542012-06-23 10:33:16 +0200340 bitvec_write_field(dest, wp,ts,3); // TN
341 bitvec_write_field(dest, wp,tsc,3); // TSC
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400342 bitvec_write_field(dest, wp,0x0,3); // non-hopping RF channel configuraion
Andreas Eversberg0aed6542012-06-23 10:33:16 +0200343 bitvec_write_field(dest, wp,arfcn,10); // ARFCN
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400344
345 //10.5.2.30 Request Reference
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400346 bitvec_write_field(dest, wp,ra,8); // RA
347 bitvec_write_field(dest, wp,(fn / (26 * 51)) % 32,5); // T1'
348 bitvec_write_field(dest, wp,fn % 51,6); // T3
349 bitvec_write_field(dest, wp,fn % 26,5); // T2
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400350
351 // 10.5.2.40 Timing Advance
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400352 bitvec_write_field(dest, wp,0x0,2); // spare
353 bitvec_write_field(dest, wp,ta,6); // Timing Advance value
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400354
355 // No mobile allocation in non-hopping systems.
356 // A zero-length LV. Just write L=0.
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400357 bitvec_write_field(dest, wp,0,8);
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400358
359 if (downlink)
360 {
361 // GSM 04.08 10.5.2.16 IA Rest Octets
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400362 bitvec_write_field(dest, wp, 3, 2); // "HH"
363 bitvec_write_field(dest, wp, 1, 2); // "01" Packet Downlink Assignment
364 bitvec_write_field(dest, wp,tlli,32); // TLLI
365 bitvec_write_field(dest, wp,0x1,1); // switch TFI : on
366 bitvec_write_field(dest, wp,tfi,5); // TFI
367 bitvec_write_field(dest, wp,0x0,1); // RLC acknowledged mode
Andreas Eversberge6228b32012-07-03 13:36:03 +0200368 bitvec_write_field(dest, wp,0x0,1); // ALPHA = not present
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400369 bitvec_write_field(dest, wp,0x0,5); // GAMMA power control parameter
Andreas Eversberge6228b32012-07-03 13:36:03 +0200370 bitvec_write_field(dest, wp,polling,1); // Polling Bit
371 bitvec_write_field(dest, wp,!polling,1); // TA_VALID ???
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400372 bitvec_write_field(dest, wp,0x1,1); // switch TIMING_ADVANCE_INDEX = on
373 bitvec_write_field(dest, wp,0x0,4); // TIMING_ADVANCE_INDEX
Andreas Eversberge6228b32012-07-03 13:36:03 +0200374 if (polling) {
375 bitvec_write_field(dest, wp,0x1,1); // TBF Starting TIME present
376 bitvec_write_field(dest, wp,(poll_fn / (26 * 51)) % 32,5); // T1'
377 bitvec_write_field(dest, wp,poll_fn % 51,6); // T3
378 bitvec_write_field(dest, wp,poll_fn % 26,5); // T2
379 } else {
380 bitvec_write_field(dest, wp,0x0,1); // TBF Starting TIME present
381 }
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400382 bitvec_write_field(dest, wp,0x0,1); // P0 not present
Andreas Eversberge6228b32012-07-03 13:36:03 +0200383// bitvec_write_field(dest, wp,0x1,1); // P0 not present
384// bitvec_write_field(dest, wp,0xb,4);
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400385 }
386 else
387 {
388 // GMS 04.08 10.5.2.37b 10.5.2.16
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400389 bitvec_write_field(dest, wp, 3, 2); // "HH"
390 bitvec_write_field(dest, wp, 0, 2); // "0" Packet Uplink Assignment
391 bitvec_write_field(dest, wp, 1, 1); // Block Allocation : Not Single Block Allocation
392 bitvec_write_field(dest, wp, tfi, 5); // TFI_ASSIGNMENT Temporary Flow Identity
393 bitvec_write_field(dest, wp, 0, 1); // POLLING
394 bitvec_write_field(dest, wp, 0, 1); // ALLOCATION_TYPE: dynamic
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200395 bitvec_write_field(dest, wp, usf, 3); // USF
Andreas Eversberg05534082012-06-24 11:46:49 +0200396 bitvec_write_field(dest, wp, 0, 1); // USF_GRANULARITY
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400397 bitvec_write_field(dest, wp, 0 , 1); // "0" power control: Not Present
398 bitvec_write_field(dest, wp, 0, 2); // CHANNEL_CODING_COMMAND
Andreas Eversberg05534082012-06-24 11:46:49 +0200399 bitvec_write_field(dest, wp, 0, 1); // TLLI_BLOCK_CHANNEL_CODING
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +0400400 bitvec_write_field(dest, wp, 1 , 1); // "1" Alpha : Present
401 bitvec_write_field(dest, wp, 0, 4); // Alpha
402 bitvec_write_field(dest, wp, 0, 5); // Gamma
403 bitvec_write_field(dest, wp, 0, 1); // TIMING_ADVANCE_INDEX_FLAG
404 bitvec_write_field(dest, wp, 0, 1); // TBF_STARTING_TIME_FLAG
Ivan Kluchnikov5310d452012-04-17 22:00:31 +0400405 }
406
407 if (wp%8)
408 return wp/8+1;
409 else
410 return wp/8;
411}
412
Andreas Eversberge6228b32012-07-03 13:36:03 +0200413/* generate uplink assignment */
414void write_packet_uplink_assignment(bitvec * dest, uint8_t old_tfi,
415 uint8_t old_downlink, uint32_t tlli, uint8_t use_tlli, uint8_t new_tfi,
416 uint8_t usf, uint16_t arfcn, uint8_t tn, uint8_t ta, uint8_t tsc,
417 uint8_t poll)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400418{
Andreas Eversberge6228b32012-07-03 13:36:03 +0200419 // TODO We should use our implementation of encode RLC/MAC Control messages.
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400420 unsigned wp = 0;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200421 int i;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400422
Andreas Eversberge6228b32012-07-03 13:36:03 +0200423 bitvec_write_field(dest, wp,0x1,2); // Payload Type
424 bitvec_write_field(dest, wp,0x0,2); // Uplink block with TDMA framenumber (N+13)
425 bitvec_write_field(dest, wp,poll,1); // Suppl/Polling Bit
426 bitvec_write_field(dest, wp,0x0,3); // Uplink state flag
427 bitvec_write_field(dest, wp,0xa,6); // MESSAGE TYPE
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400428
Andreas Eversberge6228b32012-07-03 13:36:03 +0200429 bitvec_write_field(dest, wp,0x0,2); // Page Mode
Ivan Kluchnikovbceb3fb2012-06-05 16:56:27 +0400430
Andreas Eversberge6228b32012-07-03 13:36:03 +0200431 bitvec_write_field(dest, wp,0x0,1); // switch PERSIST_LEVEL: off
432 if (use_tlli) {
433 bitvec_write_field(dest, wp,0x2,2); // switch TLLI : on
434 bitvec_write_field(dest, wp,tlli,32); // TLLI
435 } else {
436 bitvec_write_field(dest, wp,0x0,1); // switch TFI : on
437 bitvec_write_field(dest, wp,old_downlink,1); // 0=UPLINK TFI, 1=DL TFI
438 bitvec_write_field(dest, wp,old_tfi,5); // TFI
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400439 }
Ivan Kluchnikovb2b81002012-06-04 21:57:02 +0400440
Andreas Eversberge6228b32012-07-03 13:36:03 +0200441 bitvec_write_field(dest, wp,0x0,1); // Message escape
442 bitvec_write_field(dest, wp,0x0,2); // CHANNEL_CODING_COMMAND
443 bitvec_write_field(dest, wp,0x0,1); // TLLI_BLOCK_CHANNEL_CODING
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400444
Andreas Eversberge6228b32012-07-03 13:36:03 +0200445 bitvec_write_field(dest, wp,0x1,1); // switch TIMING_ADVANCE_VALUE = on
446 bitvec_write_field(dest, wp,ta,6); // TIMING_ADVANCE_VALUE
447 bitvec_write_field(dest, wp,0x0,1); // switch TIMING_ADVANCE_INDEX = off
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400448
Andreas Eversberge6228b32012-07-03 13:36:03 +0200449#if 1
450 bitvec_write_field(dest, wp,0x1,1); // Frequency Parameters information elements = present
451 bitvec_write_field(dest, wp,tsc,3); // Training Sequence Code (TSC) = 2
452 bitvec_write_field(dest, wp,0x0,2); // ARFCN = present
453 bitvec_write_field(dest, wp,arfcn,10); // ARFCN
454#else
455 bitvec_write_field(dest, wp,0x0,1); // Frequency Parameters = off
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200456#endif
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400457
Andreas Eversberge6228b32012-07-03 13:36:03 +0200458 bitvec_write_field(dest, wp,0x1,2); // Dynamic Allocation
Ivan Kluchnikove3594232012-06-07 01:12:29 +0400459
Andreas Eversberge6228b32012-07-03 13:36:03 +0200460 bitvec_write_field(dest, wp,0x0,1); // Extended Dynamic Allocation = off
461 bitvec_write_field(dest, wp,0x0,1); // P0 = off
Ivan Kluchnikove3594232012-06-07 01:12:29 +0400462
Andreas Eversberge6228b32012-07-03 13:36:03 +0200463 bitvec_write_field(dest, wp,0x0,1); // USF_GRANULARITY
464 bitvec_write_field(dest, wp,0x1,1); // switch TFI : on
465 bitvec_write_field(dest, wp,new_tfi,5);// TFI
466
467 bitvec_write_field(dest, wp,0x0,1); //
468 bitvec_write_field(dest, wp,0x0,1); // TBF Starting Time = off
469 bitvec_write_field(dest, wp,0x0,1); // Timeslot Allocation
470
471 for (i = 0; i < 8; i++) {
472 if (tn == i) {
473 bitvec_write_field(dest, wp,0x1,1); // USF_TN(i): on
474 bitvec_write_field(dest, wp,usf,3); // USF_TN(i)
475 } else
476 bitvec_write_field(dest, wp,0x0,1); // USF_TN(i): off
Ivan Kluchnikove3594232012-06-07 01:12:29 +0400477 }
Andreas Eversberge6228b32012-07-03 13:36:03 +0200478// bitvec_write_field(dest, wp,0x0,1); // Measurement Mapping struct not present
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400479}
480
Andreas Eversberge6228b32012-07-03 13:36:03 +0200481/* generate downlink assignment */
482void write_packet_downlink_assignment(bitvec * dest, uint8_t old_tfi,
483 uint8_t old_downlink, uint8_t new_tfi, uint16_t arfcn,
484 uint8_t tn, uint8_t ta, uint8_t tsc, uint8_t poll)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400485{
Andreas Eversberge6228b32012-07-03 13:36:03 +0200486 // TODO We should use our implementation of encode RLC/MAC Control messages.
487 unsigned wp = 0;
488 int i;
489 bitvec_write_field(dest, wp,0x1,2); // Payload Type
490 bitvec_write_field(dest, wp,0x0,2); // Uplink block with TDMA framenumber (FN+13)
491 bitvec_write_field(dest, wp,poll,1); // Suppl/Polling Bit
492 bitvec_write_field(dest, wp,0x0,3); // Uplink state flag
493 bitvec_write_field(dest, wp,0x2,6); // MESSAGE TYPE
494 bitvec_write_field(dest, wp,0x0,2); // Page Mode
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400495
Andreas Eversberge6228b32012-07-03 13:36:03 +0200496 bitvec_write_field(dest, wp,0x0,1); // switch PERSIST_LEVEL: off
497 bitvec_write_field(dest, wp,0x0,1); // switch TFI : on
498 bitvec_write_field(dest, wp,old_downlink,1); // 0=UPLINK TFI, 1=DL TFI
499 bitvec_write_field(dest, wp,old_tfi,5); // TFI
Ivan Kluchnikove3594232012-06-07 01:12:29 +0400500
Andreas Eversberge6228b32012-07-03 13:36:03 +0200501 bitvec_write_field(dest, wp,0x0,1); // Message escape
502 bitvec_write_field(dest, wp,0x0,2); // Medium Access Method: Dynamic Allocation
503 bitvec_write_field(dest, wp,0x0,1); // RLC acknowledged mode
504
505 bitvec_write_field(dest, wp,old_downlink,1); // the network establishes no new downlink TBF for the mobile station
506 bitvec_write_field(dest, wp,0x80 >> tn,8); // timeslot(s)
507
508 bitvec_write_field(dest, wp,0x1,1); // switch TIMING_ADVANCE_VALUE = on
509 bitvec_write_field(dest, wp,ta,6); // TIMING_ADVANCE_VALUE
510 bitvec_write_field(dest, wp,0x0,1); // switch TIMING_ADVANCE_INDEX = off
511
512 bitvec_write_field(dest, wp,0x0,1); // switch POWER CONTROL = off
513 bitvec_write_field(dest, wp,0x1,1); // Frequency Parameters information elements = present
514
515 bitvec_write_field(dest, wp,tsc,3); // Training Sequence Code (TSC) = 2
516 bitvec_write_field(dest, wp,0x0,2); // ARFCN = present
517 bitvec_write_field(dest, wp,arfcn,10); // ARFCN
518
519 bitvec_write_field(dest, wp,0x1,1); // switch TFI : on
520 bitvec_write_field(dest, wp,new_tfi,5);// TFI
521
522 bitvec_write_field(dest, wp,0x1,1); // Power Control Parameters IE = present
523 bitvec_write_field(dest, wp,0x0,4); // ALPHA power control parameter
524 for (i = 0; i < 8; i++)
525 bitvec_write_field(dest, wp,(tn == i),1); // switch GAMMA_TN[i] = on or off
526 bitvec_write_field(dest, wp,0x0,5); // GAMMA_TN[tn]
527
528 bitvec_write_field(dest, wp,0x0,1); // TBF Starting TIME IE not present
529 bitvec_write_field(dest, wp,0x0,1); // Measurement Mapping struct not present
530 bitvec_write_field(dest, wp,0x0,1);
531}
532
533/* generate uplink ack */
534void write_packet_uplink_ack(bitvec * dest, struct gprs_rlcmac_tbf *tbf,
535 uint8_t final)
536{
537 char show_v_n[65];
538
539 // TODO We should use our implementation of encode RLC/MAC Control messages.
540 unsigned wp = 0;
541 uint16_t i, bbn;
542 uint16_t mod_sns_half = (tbf->sns >> 1) - 1;
543 char bit;
544
545 LOGP(DRLCMACUL, LOGL_DEBUG, "Sending Ack/Nack for TBF=%d "
546 "(final=%d)\n", tbf->tfi, final);
547
548 bitvec_write_field(dest, wp,0x1,2); // payload
549 bitvec_write_field(dest, wp,0x0,2); // Uplink block with TDMA framenumber (N+13)
550 bitvec_write_field(dest, wp,final,1); // Suppl/Polling Bit
551 bitvec_write_field(dest, wp,0x0,3); // Uplink state flag
552
553 //bitvec_write_field(dest, wp,0x0,1); // Reduced block sequence number
554 //bitvec_write_field(dest, wp,BSN+6,5); // Radio transaction identifier
555 //bitvec_write_field(dest, wp,0x1,1); // Final segment
556 //bitvec_write_field(dest, wp,0x1,1); // Address control
557
558 //bitvec_write_field(dest, wp,0x0,2); // Power reduction: 0
559 //bitvec_write_field(dest, wp,TFI,5); // Temporary flow identifier
560 //bitvec_write_field(dest, wp,0x1,1); // Direction
561
562 bitvec_write_field(dest, wp,0x09,6); // MESSAGE TYPE
563 bitvec_write_field(dest, wp,0x0,2); // Page Mode
564
565 bitvec_write_field(dest, wp,0x0,2);
566 bitvec_write_field(dest, wp,tbf->tfi,5); // Uplink TFI
567 bitvec_write_field(dest, wp,0x0,1);
568
569 bitvec_write_field(dest, wp,0x0,2); // CS1
570 bitvec_write_field(dest, wp,final,1); // FINAL_ACK_INDICATION
571 bitvec_write_field(dest, wp,tbf->dir.ul.v_r,7); // STARTING_SEQUENCE_NUMBER
572 // RECEIVE_BLOCK_BITMAP
573 for (i = 0, bbn = (tbf->dir.ul.v_r - 64) & mod_sns_half; i < 64;
574 i++, bbn = (bbn + 1) & mod_sns_half) {
575 bit = tbf->dir.ul.v_n[bbn];
576 if (bit == 0)
577 bit = ' ';
578 show_v_n[i] = bit;
579 bitvec_write_field(dest, wp,(bit == 'R'),1);
Ivan Kluchnikove3594232012-06-07 01:12:29 +0400580 }
Andreas Eversberge6228b32012-07-03 13:36:03 +0200581 show_v_n[64] = '\0';
582 LOGP(DRLCMACUL, LOGL_DEBUG, "- V(N): \"%s\" R=Received "
583 "N=Not-Received\n", show_v_n);
584 bitvec_write_field(dest, wp,0x1,1); // CONTENTION_RESOLUTION_TLLI = present
585 bitvec_write_field(dest, wp,tbf->tlli,8*4);
586 bitvec_write_field(dest, wp,0x00,4); //spare
587 bitvec_write_field(dest, wp,0x5,4); //0101
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400588}
589
590/* Send Uplink unit-data to SGSN. */
591void gprs_rlcmac_tx_ul_ud(gprs_rlcmac_tbf *tbf)
592{
593 const uint8_t qos_profile = QOS_PROFILE;
594 struct msgb *llc_pdu;
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200595 unsigned msg_len = NS_HDR_LEN + BSSGP_HDR_LEN + tbf->llc_index;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400596
Andreas Eversberge6228b32012-07-03 13:36:03 +0200597 LOGP(DBSSGP, LOGL_NOTICE, "TX: [PCU -> SGSN ] TFI: %u TLLI: 0x%08x DataLen: %u\n", tbf->tfi, tbf->tlli, tbf->llc_index);
Ivan Kluchnikovb2b81002012-06-04 21:57:02 +0400598 //LOGP(DBSSGP, LOGL_NOTICE, " Data = ");
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200599 //for (unsigned i = 0; i < tbf->llc_index; i++)
600 // LOGPC(DBSSGP, LOGL_NOTICE, "%02x ", tbf->llc_frame[i]);
Ivan Kluchnikovc320d862012-03-18 15:04:48 +0400601
602 bctx->cell_id = CELL_ID;
603 bctx->nsei = NSEI;
604 bctx->ra_id.mnc = MNC;
605 bctx->ra_id.mcc = MCC;
606 bctx->ra_id.lac = PCU_LAC;
607 bctx->ra_id.rac = PCU_RAC;
608 bctx->bvci = BVCI;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400609
610 llc_pdu = msgb_alloc_headroom(msg_len, msg_len,"llc_pdu");
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200611 msgb_tvlv_push(llc_pdu, BSSGP_IE_LLC_PDU, sizeof(uint8_t)*tbf->llc_index, tbf->llc_frame);
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400612 bssgp_tx_ul_ud(bctx, tbf->tlli, &qos_profile, llc_pdu);
613}
614