blob: 913ae48de8c53acb5d59396e97e9cc818e47c1d4 [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>
Holger Hans Peter Freytherd6bd91e2013-08-24 21:16:55 +02005 * Copyright (C) 2013 by Holger Hans Peter Freyther
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04006 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#include <gprs_bssgp_pcu.h>
23#include <pcu_l1_if.h>
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +040024#include <gprs_rlcmac.h>
25
Andreas Eversberg53f47252012-07-15 07:10:10 +020026/* 3GPP TS 05.02 Annex B.1 */
27
28#define MS_NA 255 /* N/A */
29#define MS_A 254 /* 1 with hopping, 0 without */
30#define MS_B 253 /* 1 with hopping, 0 without (change Rx to Tx)*/
31#define MS_C 252 /* 1 with hopping, 0 without (change Tx to Rx)*/
32
33struct gprs_ms_multislot_class {
34 uint8_t rx, tx, sum; /* Maximum Number of Slots: RX, Tx, Sum Rx+Tx */
35 uint8_t ta, tb, ra, rb; /* Minimum Number of Slots */
36 uint8_t type; /* Type of Mobile */
37};
38
39struct gprs_ms_multislot_class gprs_ms_multislot_class[32] = {
40/* M-S Class Rx Tx Sum Tta Ttb Tra Trb Type */
41/* N/A */ { MS_NA,MS_NA, MS_NA, MS_NA, MS_NA, MS_NA, MS_NA, MS_NA },
42/* 1 */ { 1, 1, 2, 3, 2, 4, 2, 1 },
43/* 2 */ { 2, 1, 3, 3, 2, 3, 1, 1 },
44/* 3 */ { 2, 2, 3, 3, 2, 3, 1, 1 },
45/* 4 */ { 3, 1, 4, 3, 1, 3, 1, 1 },
46/* 5 */ { 2, 2, 4, 3, 1, 3, 1, 1 },
47/* 6 */ { 3, 2, 4, 3, 1, 3, 1, 1 },
48/* 7 */ { 3, 3, 4, 3, 1, 3, 1, 1 },
49/* 8 */ { 4, 1, 5, 3, 1, 2, 1, 1 },
50/* 9 */ { 3, 2, 5, 3, 1, 2, 1, 1 },
51/* 10 */ { 4, 2, 5, 3, 1, 2, 1, 1 },
52/* 11 */ { 4, 3, 5, 3, 1, 2, 1, 1 },
53/* 12 */ { 4, 4, 5, 2, 1, 2, 1, 1 },
54/* 13 */ { 3, 3, MS_NA, MS_NA, MS_A, 3, MS_A, 2 },
55/* 14 */ { 4, 4, MS_NA, MS_NA, MS_A, 3, MS_A, 2 },
56/* 15 */ { 5, 5, MS_NA, MS_NA, MS_A, 3, MS_A, 2 },
57/* 16 */ { 6, 6, MS_NA, MS_NA, MS_A, 2, MS_A, 2 },
58/* 17 */ { 7, 7, MS_NA, MS_NA, MS_A, 1, 0, 2 },
59/* 18 */ { 8, 8, MS_NA, MS_NA, 0, 0, 0, 2 },
60/* 19 */ { 6, 2, MS_NA, 3, MS_B, 2, MS_C, 1 },
61/* 20 */ { 6, 3, MS_NA, 3, MS_B, 2, MS_C, 1 },
62/* 21 */ { 6, 4, MS_NA, 3, MS_B, 2, MS_C, 1 },
63/* 22 */ { 6, 4, MS_NA, 2, MS_B, 2, MS_C, 1 },
64/* 23 */ { 6, 6, MS_NA, 2, MS_B, 2, MS_C, 1 },
65/* 24 */ { 8, 2, MS_NA, 3, MS_B, 2, MS_C, 1 },
66/* 25 */ { 8, 3, MS_NA, 3, MS_B, 2, MS_C, 1 },
67/* 26 */ { 8, 4, MS_NA, 3, MS_B, 2, MS_C, 1 },
68/* 27 */ { 8, 4, MS_NA, 2, MS_B, 2, MS_C, 1 },
69/* 28 */ { 8, 6, MS_NA, 2, MS_B, 2, MS_C, 1 },
70/* 29 */ { 8, 8, MS_NA, 2, MS_B, 2, MS_C, 1 },
71/* N/A */ { MS_NA,MS_NA, MS_NA, MS_NA, MS_NA, MS_NA, MS_NA, MS_NA },
72/* N/A */ { MS_NA,MS_NA, MS_NA, MS_NA, MS_NA, MS_NA, MS_NA, MS_NA },
73};
74
Andreas Eversberg3b1332c2012-10-03 14:20:53 +020075struct gprs_rlcmac_cs gprs_rlcmac_cs[] = {
76/* frame length data block max payload */
77 { 0, 0, 0 },
78 { 23, 23, 20 }, /* CS-1 */
79 { 34, 33, 30 }, /* CS-2 */
80 { 40, 39, 36 }, /* CS-3 */
81 { 54, 53, 50 }, /* CS-4 */
82};
83
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +020084LLIST_HEAD(gprs_rlcmac_ul_tbfs);
85LLIST_HEAD(gprs_rlcmac_dl_tbfs);
Andreas Eversberg2b914642012-07-19 13:06:26 +020086llist_head *gprs_rlcmac_tbfs_lists[] = {
87 &gprs_rlcmac_ul_tbfs,
88 &gprs_rlcmac_dl_tbfs,
89 NULL
90};
Andreas Eversberg6681bb82012-07-25 08:48:44 +020091extern void *tall_pcu_ctx;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +040092
Andreas Eversbergb83e2a72012-10-07 15:26:00 +020093#ifdef DEBUG_DIAGRAM
94struct timeval diagram_time = {0,0};
95struct timeval diagram_last_tv = {0,0};
96
97void debug_diagram(int diag, const char *format, ...)
98{
99 va_list ap;
100 char debug[128];
101 char line[1024];
102 struct gprs_rlcmac_tbf *tbf, *tbf_a[16];
103 int max_diag = -1, i;
104 uint64_t diff = 0;
105
106 va_start(ap, format);
107 vsnprintf(debug, sizeof(debug) - 1, format, ap);
108 debug[19] = ' ';
109 debug[20] = '\0';
110 va_end(ap);
111
112 memset(tbf_a, 0, sizeof(tbf_a));
113 llist_for_each_entry(tbf, &gprs_rlcmac_ul_tbfs, list) {
114 if (tbf->diag < 16) {
115 if (tbf->diag > max_diag)
116 max_diag = tbf->diag;
117 tbf_a[tbf->diag] = tbf;
118 }
119 }
120 llist_for_each_entry(tbf, &gprs_rlcmac_dl_tbfs, list) {
121 if (tbf->diag < 16) {
122 if (tbf->diag > max_diag)
123 max_diag = tbf->diag;
124 tbf_a[tbf->diag] = tbf;
125 }
126 }
127
128 if (diagram_last_tv.tv_sec) {
129 diff = (uint64_t)(diagram_time.tv_sec -
130 diagram_last_tv.tv_sec) * 1000;
131 diff += diagram_time.tv_usec / 1000;
132 diff -= diagram_last_tv.tv_usec / 1000;
133 }
134 memcpy(&diagram_last_tv, &diagram_time, sizeof(struct timeval));
135
136 if (diff > 0) {
137 if (diff > 99999)
138 strcpy(line, " ... : ");
139 else
140 sprintf(line, "%3d.%03d: ", (int)(diff / 1000),
141 (int)(diff % 1000));
142 for (i = 0; i <= max_diag; i++) {
143 if (tbf_a[i] == NULL) {
144 strcat(line, " ");
145 continue;
146 }
147 if (tbf_a[i]->diag_new) {
148 strcat(line, " | ");
149 continue;
150 }
151 strcat(line, " ");
152 }
153 puts(line);
154 }
155 strcpy(line, " : ");
156 for (i = 0; i <= max_diag; i++) {
157 if (tbf_a[i] == NULL) {
158 strcat(line, " ");
159 continue;
160 }
161 if (tbf_a[i]->diag != diag) {
162 strcat(line, " | ");
163 continue;
164 }
165 if (strlen(debug) < 19) {
166 strcat(line, " ");
167 memcpy(line + strlen(line) - 11 - strlen(debug) / 2,
168 debug, strlen(debug));
169 } else
170 strcat(line, debug);
171 tbf_a[i]->diag_new = 1;
172 }
173 puts(line);
174}
175#endif
176
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200177/* FIXME: spread ressources over multiple TRX. Also add option to use same
178 * TRX in case of existing TBF for TLLI in the other direction. */
Andreas Eversberg02d7cd22013-01-15 08:59:34 +0100179/* search for free TFI and return TFI, TRX */
Holger Hans Peter Freytherd6bd91e2013-08-24 21:16:55 +0200180int tfi_find_free(struct gprs_rlcmac_bts *bts, enum gprs_rlcmac_tbf_direction dir,
Holger Hans Peter Freytherb67a8a32013-07-28 18:55:14 +0200181 uint8_t *_trx, int8_t use_trx)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400182{
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200183 struct gprs_rlcmac_pdch *pdch;
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200184 struct gprs_rlcmac_tbf **tbfp;
185 uint8_t trx_from, trx_to, trx, ts, tfi;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400186
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200187 if (use_trx >= 0 && use_trx < 8)
188 trx_from = trx_to = use_trx;
189 else {
190 trx_from = 0;
191 trx_to = 7;
192 }
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200193
194 /* on TRX find first enabled TS */
195 for (trx = trx_from; trx <= trx_to; trx++) {
Andreas Eversberg02d7cd22013-01-15 08:59:34 +0100196 for (ts = 0; ts < 8; ts++) {
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200197 pdch = &bts->trx[trx].pdch[ts];
198 if (!pdch->enable)
199 continue;
200 break;
201 }
202 if (ts < 8)
203 break;
204 }
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200205 if (trx > trx_to) {
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200206 LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH available.\n");
207 return -EINVAL;
208 }
209
210
211 LOGP(DRLCMAC, LOGL_DEBUG, "Searching for first unallocated TFI: "
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200212 "TRX=%d first TS=%d\n", trx, ts);
213 if (dir == GPRS_RLCMAC_UL_TBF)
Andreas Eversbergadb2f182012-08-07 17:06:08 +0200214 tbfp = bts->trx[trx].ul_tbf;
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200215 else
Andreas Eversbergadb2f182012-08-07 17:06:08 +0200216 tbfp = bts->trx[trx].dl_tbf;
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200217 for (tfi = 0; tfi < 32; tfi++) {
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200218 if (!tbfp[tfi])
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200219 break;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400220 }
221
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200222 if (tfi < 32) {
223 LOGP(DRLCMAC, LOGL_DEBUG, " Found TFI=%d.\n", tfi);
224 *_trx = trx;
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200225 return tfi;
226 }
227 LOGP(DRLCMAC, LOGL_NOTICE, "No TFI available.\n");
228
229 return -1;
230}
231
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200232static inline int8_t find_free_usf(struct gprs_rlcmac_pdch *pdch, uint8_t ts)
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200233{
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200234 struct gprs_rlcmac_tbf *tbf;
235 uint8_t usf_map = 0;
236 uint8_t tfi, usf;
237
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200238 /* make map of used USF */
239 for (tfi = 0; tfi < 32; tfi++) {
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200240 tbf = pdch->ul_tbf[tfi];
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200241 if (!tbf)
242 continue;
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200243 usf_map |= (1 << tbf->dir.ul.usf[ts]);
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200244 }
245
246 /* look for USF, don't use USF=7 */
247 for (usf = 0; usf < 7; usf++) {
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200248 if (!(usf_map & (1 << usf)))
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200249 return usf;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400250 }
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200251
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400252 return -1;
253}
254
255/* lookup TBF Entity (by TFI) */
Holger Hans Peter Freytherb67a8a32013-07-28 18:55:14 +0200256struct gprs_rlcmac_tbf *tbf_by_tfi(struct gprs_rlcmac_bts *bts,
257 uint8_t tfi, uint8_t trx, enum gprs_rlcmac_tbf_direction dir)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400258{
259 struct gprs_rlcmac_tbf *tbf;
260
Andreas Eversbergadb2f182012-08-07 17:06:08 +0200261 if (tfi >= 32 || trx >= 8)
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200262 return NULL;
263
264 if (dir == GPRS_RLCMAC_UL_TBF)
Andreas Eversbergadb2f182012-08-07 17:06:08 +0200265 tbf = bts->trx[trx].ul_tbf[tfi];
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200266 else
Andreas Eversbergadb2f182012-08-07 17:06:08 +0200267 tbf = bts->trx[trx].dl_tbf[tfi];
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200268 if (!tbf)
269 return NULL;
270
271 if (tbf->state != GPRS_RLCMAC_RELEASING)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400272 return tbf;
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200273
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400274 return NULL;
275}
276
Andreas Eversberge6228b32012-07-03 13:36:03 +0200277/* search for active downlink or uplink tbf */
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200278struct gprs_rlcmac_tbf *tbf_by_tlli(uint32_t tlli,
279 enum gprs_rlcmac_tbf_direction dir)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400280{
281 struct gprs_rlcmac_tbf *tbf;
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200282 if (dir == GPRS_RLCMAC_UL_TBF) {
283 llist_for_each_entry(tbf, &gprs_rlcmac_ul_tbfs, list) {
284 if (tbf->state != GPRS_RLCMAC_RELEASING
Andreas Eversberga9b94072012-07-15 19:30:41 +0200285 && tbf->tlli == tlli && tbf->tlli_valid)
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200286 return tbf;
287 }
288 } else {
289 llist_for_each_entry(tbf, &gprs_rlcmac_dl_tbfs, list) {
290 if (tbf->state != GPRS_RLCMAC_RELEASING
291 && tbf->tlli == tlli)
292 return tbf;
293 }
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400294 }
295 return NULL;
296}
297
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200298struct gprs_rlcmac_tbf *tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t ts)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400299{
Andreas Eversberge6228b32012-07-03 13:36:03 +0200300 struct gprs_rlcmac_tbf *tbf;
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200301
302 /* only one TBF can poll on specific TS/FN, because scheduler can only
303 * schedule one downlink control block (with polling) at a FN per TS */
Andreas Eversberg592e04a2012-07-15 06:25:37 +0200304 llist_for_each_entry(tbf, &gprs_rlcmac_ul_tbfs, list) {
305 if (tbf->state != GPRS_RLCMAC_RELEASING
Andreas Eversberge6228b32012-07-03 13:36:03 +0200306 && tbf->poll_state == GPRS_RLCMAC_POLL_SCHED
Andreas Eversberg592e04a2012-07-15 06:25:37 +0200307 && tbf->poll_fn == fn && tbf->trx == trx
308 && tbf->control_ts == ts)
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200309 return tbf;
Andreas Eversberg592e04a2012-07-15 06:25:37 +0200310 }
311 llist_for_each_entry(tbf, &gprs_rlcmac_dl_tbfs, list) {
312 if (tbf->state != GPRS_RLCMAC_RELEASING
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200313 && tbf->poll_state == GPRS_RLCMAC_POLL_SCHED
Andreas Eversberg592e04a2012-07-15 06:25:37 +0200314 && tbf->poll_fn == fn && tbf->trx == trx
315 && tbf->control_ts == ts)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400316 return tbf;
317 }
318 return NULL;
319}
320
Holger Hans Peter Freytherb67a8a32013-07-28 18:55:14 +0200321struct gprs_rlcmac_tbf *tbf_alloc(struct gprs_rlcmac_bts *bts,
322 struct gprs_rlcmac_tbf *old_tbf, enum gprs_rlcmac_tbf_direction dir,
323 uint8_t tfi, uint8_t trx,
Andreas Eversberg02d7cd22013-01-15 08:59:34 +0100324 uint8_t ms_class, uint8_t single_slot)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400325{
326 struct gprs_rlcmac_tbf *tbf;
Andreas Eversbergf298fa82012-07-13 14:50:57 +0200327 int rc;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400328
Andreas Eversbergb83e2a72012-10-07 15:26:00 +0200329#ifdef DEBUG_DIAGRAM
330 /* hunt for first free number in diagram */
331 int diagram_num;
332 for (diagram_num = 0; ; diagram_num++) {
333 llist_for_each_entry(tbf, &gprs_rlcmac_ul_tbfs, list) {
334 if (tbf->diag == diagram_num)
335 goto next_diagram;
336 }
337 llist_for_each_entry(tbf, &gprs_rlcmac_dl_tbfs, list) {
338 if (tbf->diag == diagram_num)
339 goto next_diagram;
340 }
341 break;
342next_diagram:
343 continue;
344 }
345#endif
346
Andreas Eversberg0e403092012-07-06 11:04:57 +0200347 LOGP(DRLCMAC, LOGL_DEBUG, "********** TBF starts here **********\n");
Andreas Eversbergf298fa82012-07-13 14:50:57 +0200348 LOGP(DRLCMAC, LOGL_INFO, "Allocating %s TBF: TFI=%d TRX=%d "
349 "MS_CLASS=%d\n", (dir == GPRS_RLCMAC_UL_TBF) ? "UL" : "DL",
350 tfi, trx, ms_class);
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200351
Andreas Eversberg02d7cd22013-01-15 08:59:34 +0100352 if (trx >= 8 || tfi >= 32)
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200353 return NULL;
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200354
Andreas Eversberg6681bb82012-07-25 08:48:44 +0200355 tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_tbf);
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400356 if (!tbf)
357 return NULL;
358
Andreas Eversbergb83e2a72012-10-07 15:26:00 +0200359#ifdef DEBUG_DIAGRAM
360 tbf->diag = diagram_num;
361#endif
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200362 tbf->direction = dir;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400363 tbf->tfi = tfi;
Andreas Eversberg0aed6542012-06-23 10:33:16 +0200364 tbf->trx = trx;
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200365 tbf->arfcn = bts->trx[trx].arfcn;
Andreas Eversbergf298fa82012-07-13 14:50:57 +0200366 tbf->ms_class = ms_class;
367 tbf->ws = 64;
368 tbf->sns = 128;
Andreas Eversbergf01929b2012-10-08 12:40:49 +0200369 /* select algorithm */
Holger Hans Peter Freytherb67a8a32013-07-28 18:55:14 +0200370 rc = bts->alloc_algorithm(bts, old_tbf, tbf, bts->alloc_algorithm_curst,
Andreas Eversbergf01929b2012-10-08 12:40:49 +0200371 single_slot);
Andreas Eversberg592e04a2012-07-15 06:25:37 +0200372 /* if no ressource */
373 if (rc < 0) {
374 talloc_free(tbf);
375 return NULL;
376 }
377 /* assign control ts */
378 tbf->control_ts = 0xff;
379 rc = tbf_assign_control_ts(tbf);
Andreas Eversbergf298fa82012-07-13 14:50:57 +0200380 /* if no ressource */
381 if (rc < 0) {
382 talloc_free(tbf);
383 return NULL;
384 }
385
Andreas Eversbergb3ded4c2012-07-24 10:47:24 +0200386 /* set timestamp */
Andreas Eversberg050ace22013-03-16 16:22:02 +0100387 gettimeofday(&tbf->meas.dl_bw_tv, NULL);
388 gettimeofday(&tbf->meas.rssi_tv, NULL);
389 gettimeofday(&tbf->meas.dl_loss_tv, NULL);
Andreas Eversbergb3ded4c2012-07-24 10:47:24 +0200390
Andreas Eversbergf298fa82012-07-13 14:50:57 +0200391 INIT_LLIST_HEAD(&tbf->llc_queue);
392 if (dir == GPRS_RLCMAC_UL_TBF)
393 llist_add(&tbf->list, &gprs_rlcmac_ul_tbfs);
394 else
395 llist_add(&tbf->list, &gprs_rlcmac_dl_tbfs);
396
Andreas Eversbergb83e2a72012-10-07 15:26:00 +0200397 debug_diagram(tbf->diag, "+-----------------+");
398 debug_diagram(tbf->diag, "|NEW %s TBF TFI=%2d|",
399 (dir == GPRS_RLCMAC_UL_TBF) ? "UL" : "DL", tfi);
400 debug_diagram(tbf->diag, "+-----------------+");
401
Andreas Eversbergf298fa82012-07-13 14:50:57 +0200402 return tbf;
403}
404
Andreas Eversberg592e04a2012-07-15 06:25:37 +0200405/* Slot Allocation: Algorithm A
406 *
407 * Assign single slot for uplink and downlink
408 */
Holger Hans Peter Freytherb67a8a32013-07-28 18:55:14 +0200409int alloc_algorithm_a(struct gprs_rlcmac_bts *bts,
410 struct gprs_rlcmac_tbf *old_tbf,
Andreas Eversbergf01929b2012-10-08 12:40:49 +0200411 struct gprs_rlcmac_tbf *tbf, uint32_t cust, uint8_t single)
Andreas Eversbergf298fa82012-07-13 14:50:57 +0200412{
Andreas Eversbergf298fa82012-07-13 14:50:57 +0200413 struct gprs_rlcmac_pdch *pdch;
Andreas Eversberg02d7cd22013-01-15 08:59:34 +0100414 uint8_t ts;
Andreas Eversbergf298fa82012-07-13 14:50:57 +0200415 int8_t usf; /* must be signed */
416
Andreas Eversberg592e04a2012-07-15 06:25:37 +0200417 LOGP(DRLCMAC, LOGL_DEBUG, "Slot Allocation (Algorithm A) for class "
418 "%d\n", tbf->ms_class);
419
Andreas Eversberg02d7cd22013-01-15 08:59:34 +0100420 for (ts = 0; ts < 8; ts++) {
421 pdch = &bts->trx[tbf->trx].pdch[ts];
422 if (!pdch->enable) {
423 LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, because "
424 "not enabled\n", ts);
425 continue;
426 }
427 break;
Andreas Eversbergf298fa82012-07-13 14:50:57 +0200428 }
Andreas Eversberg02d7cd22013-01-15 08:59:34 +0100429 if (ts == 8)
430 return -EINVAL;
431
Andreas Eversbergf298fa82012-07-13 14:50:57 +0200432 tbf->tsc = pdch->tsc;
433 if (tbf->direction == GPRS_RLCMAC_UL_TBF) {
Andreas Eversbergadb2f182012-08-07 17:06:08 +0200434 /* if USF available */
435 usf = find_free_usf(pdch, ts);
436 if (usf >= 0) {
437 LOGP(DRLCMAC, LOGL_DEBUG, "- Assign uplink "
438 "TS=%d USF=%d\n", ts, usf);
439 bts->trx[tbf->trx].ul_tbf[tbf->tfi] = tbf;
440 pdch->ul_tbf[tbf->tfi] = tbf;
441 tbf->pdch[ts] = pdch;
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200442 } else {
Andreas Eversbergadb2f182012-08-07 17:06:08 +0200443 LOGP(DRLCMAC, LOGL_NOTICE, "- Failed "
444 "allocating TS=%d, no USF available\n", ts);
Andreas Eversbergf298fa82012-07-13 14:50:57 +0200445 return -EBUSY;
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200446 }
Andreas Eversbergf298fa82012-07-13 14:50:57 +0200447 } else {
Andreas Eversbergadb2f182012-08-07 17:06:08 +0200448 LOGP(DRLCMAC, LOGL_DEBUG, "- Assign downlink TS=%d\n", ts);
449 bts->trx[tbf->trx].dl_tbf[tbf->tfi] = tbf;
450 pdch->dl_tbf[tbf->tfi] = tbf;
451 tbf->pdch[ts] = pdch;
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200452 }
Andreas Eversberg592e04a2012-07-15 06:25:37 +0200453 /* the only one TS is the common TS */
Andreas Eversberg02d7cd22013-01-15 08:59:34 +0100454 tbf->first_ts = tbf->first_common_ts = ts;
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200455
Andreas Eversbergf298fa82012-07-13 14:50:57 +0200456 return 0;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400457}
458
Andreas Eversberg53f47252012-07-15 07:10:10 +0200459/* Slot Allocation: Algorithm B
460 *
461 * Assign as many downlink slots as possible.
462 * Assign one uplink slot. (With free USF)
463 *
464 */
Holger Hans Peter Freytherb67a8a32013-07-28 18:55:14 +0200465int alloc_algorithm_b(struct gprs_rlcmac_bts *bts,
466 struct gprs_rlcmac_tbf *old_tbf,
Andreas Eversbergf01929b2012-10-08 12:40:49 +0200467 struct gprs_rlcmac_tbf *tbf, uint32_t cust, uint8_t single)
Andreas Eversberg53f47252012-07-15 07:10:10 +0200468{
Andreas Eversberg53f47252012-07-15 07:10:10 +0200469 struct gprs_rlcmac_pdch *pdch;
470 struct gprs_ms_multislot_class *ms_class;
471 uint8_t Rx, Tx, Sum; /* Maximum Number of Slots: RX, Tx, Sum Rx+Tx */
472 uint8_t Tta, Ttb, Tra, Trb, Tt, Tr; /* Minimum Number of Slots */
473 uint8_t Type; /* Type of Mobile */
Andreas Eversberg02d7cd22013-01-15 08:59:34 +0100474 uint8_t rx_win_min = 0, rx_win_max = 7;
Andreas Eversberg53f47252012-07-15 07:10:10 +0200475 uint8_t tx_win_min, tx_win_max, tx_range;
476 uint8_t rx_window = 0, tx_window = 0;
477 const char *digit[10] = { "0","1","2","3","4","5","6","7","8","9" };
Andreas Eversbergba1cd9b2012-07-25 09:14:09 +0200478 int8_t usf[8] = { -1, -1, -1, -1, -1, -1, -1, -1 }; /* must be signed */
Andreas Eversberg53f47252012-07-15 07:10:10 +0200479 int8_t tsc = -1; /* must be signed */
Andreas Eversberg97644ed2013-01-15 13:20:22 +0100480 int8_t first_common_ts = -1;
Andreas Eversberg53f47252012-07-15 07:10:10 +0200481 uint8_t i, ts;
Andreas Eversbergf01929b2012-10-08 12:40:49 +0200482 uint8_t slotcount = 0;
Andreas Eversberg53f47252012-07-15 07:10:10 +0200483
Andreas Eversberg53f47252012-07-15 07:10:10 +0200484
485 if (tbf->ms_class >= 32) {
486 LOGP(DRLCMAC, LOGL_ERROR, "Multislot class %d out of range.\n",
487 tbf->ms_class);
488 return -EINVAL;
489 }
490
Andreas Eversbergf01929b2012-10-08 12:40:49 +0200491 if (tbf->ms_class) {
492 ms_class = &gprs_ms_multislot_class[tbf->ms_class];
493 LOGP(DRLCMAC, LOGL_DEBUG, "Slot Allocation (Algorithm B) for "
494 "class %d\n", tbf->ms_class);
495 } else {
496 ms_class = &gprs_ms_multislot_class[12];
497 LOGP(DRLCMAC, LOGL_DEBUG, "Slot Allocation (Algorithm B) for "
498 "unknow class (assuming 12)\n");
499 }
500
Andreas Eversberg53f47252012-07-15 07:10:10 +0200501 if (ms_class->tx == MS_NA) {
502 LOGP(DRLCMAC, LOGL_NOTICE, "Multislot class %d not "
503 "applicable.\n", tbf->ms_class);
504 return -EINVAL;
505 }
506
507 Rx = ms_class->rx;
Andreas Eversberg97644ed2013-01-15 13:20:22 +0100508#if 0
Andreas Eversbergf01929b2012-10-08 12:40:49 +0200509 if (Rx > 4) {
510 LOGP(DRLCMAC, LOGL_DEBUG, "- Degrading max Rx slots to 4\n");
511 Rx = 4;
512 }
Andreas Eversberg97644ed2013-01-15 13:20:22 +0100513#endif
Andreas Eversberg53f47252012-07-15 07:10:10 +0200514 Tx = ms_class->tx;
Andreas Eversberg97644ed2013-01-15 13:20:22 +0100515#if 0
Andreas Eversbergf01929b2012-10-08 12:40:49 +0200516 if (Tx > 4) {
517 LOGP(DRLCMAC, LOGL_DEBUG, "- Degrading max Tx slots to 4\n");
518 Tx = 4;
519 }
Andreas Eversberg97644ed2013-01-15 13:20:22 +0100520#endif
Andreas Eversberg53f47252012-07-15 07:10:10 +0200521 Sum = ms_class->sum;
522 Tta = ms_class->ta;
523 Ttb = ms_class->tb;
524 Tra = ms_class->ra;
525 Trb = ms_class->rb;
526 Type = ms_class->type;
527
528 /* Tta and Ttb may depend on hopping or frequency change */
529 if (Ttb == MS_A) {
530 if (/* FIXME: hopping*/ 0)
531 Ttb = 1;
532 else
533 Ttb = 0;
534 }
535 if (Trb == MS_A) {
536 if (/* FIXME: hopping*/ 0)
Andreas Eversberg97644ed2013-01-15 13:20:22 +0100537 Trb = 1;
Andreas Eversberg53f47252012-07-15 07:10:10 +0200538 else
Andreas Eversberg97644ed2013-01-15 13:20:22 +0100539 Trb = 0;
Andreas Eversberg53f47252012-07-15 07:10:10 +0200540 }
541 if (Ttb == MS_B) {
542 /* FIXME: or frequency change */
543 if (/* FIXME: hopping*/ 0)
544 Ttb = 1;
545 else
546 Ttb = 0;
547 }
548 if (Trb == MS_C) {
549 /* FIXME: or frequency change */
550 if (/* FIXME: hopping*/ 0)
Andreas Eversberg97644ed2013-01-15 13:20:22 +0100551 Trb = 1;
Andreas Eversberg53f47252012-07-15 07:10:10 +0200552 else
Andreas Eversberg97644ed2013-01-15 13:20:22 +0100553 Trb = 0;
Andreas Eversberg53f47252012-07-15 07:10:10 +0200554 }
555
556 LOGP(DRLCMAC, LOGL_DEBUG, "- Rx=%d Tx=%d Sum Rx+Tx=%s Tta=%s Ttb=%d "
557 " Tra=%d Trb=%d Type=%d\n", Rx, Tx,
558 (Sum == MS_NA) ? "N/A" : digit[Sum],
559 (Tta == MS_NA) ? "N/A" : digit[Tta], Ttb, Tra, Trb, Type);
560
561 /* select the values for time contraints */
562 if (/* FIXME: monitoring */0) {
563 /* applicable to type 1 and type 2 */
564 Tt = Ttb;
565 Tr = Tra;
566 } else {
567 /* applicable to type 1 and type 2 */
568 Tt = Ttb;
569 Tr = Trb;
570 }
571
572 /* select a window of Rx slots if available
573 * The maximum allowed slots depend on RX or the window of available
574 * slots.
575 * This must be done for uplink TBF also, because it is the basis
576 * for calculating control slot and uplink slot(s). */
Andreas Eversbergf01929b2012-10-08 12:40:49 +0200577 for (ts = 0, i = 0; ts < 8; ts++) {
Andreas Eversberg53f47252012-07-15 07:10:10 +0200578 pdch = &bts->trx[tbf->trx].pdch[ts];
579 /* check if enabled */
580 if (!pdch->enable) {
581 LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, because "
582 "not enabled\n", ts);
583 /* increase window for Type 1 */
Andreas Eversberg97644ed2013-01-15 13:20:22 +0100584 if (Type == 1 && rx_window)
Andreas Eversberg53f47252012-07-15 07:10:10 +0200585 i++;
586 continue;
587 }
588 /* check if TSC changes */
589 if (tsc < 0)
590 tbf->tsc = tsc = pdch->tsc;
591 else if (tsc != pdch->tsc) {
592 LOGP(DRLCMAC, LOGL_ERROR, "Skipping TS %d of TRX=%d, "
593 "because it has different TSC than lower TS "
594 "of TRX. In order to allow multislot, all "
595 "slots must be configured with the same "
596 "TSC!\n", ts, tbf->trx);
597 /* increase window for Type 1 */
Andreas Eversberg97644ed2013-01-15 13:20:22 +0100598 if (Type == 1 && rx_window)
Andreas Eversberg53f47252012-07-15 07:10:10 +0200599 i++;
600 continue;
601 }
Andreas Eversberg53f47252012-07-15 07:10:10 +0200602
Andreas Eversberg97644ed2013-01-15 13:20:22 +0100603 if (!rx_window)
604 rx_win_min = ts;
605
Andreas Eversberg53f47252012-07-15 07:10:10 +0200606 rx_window |= (1 << ts);
607 LOGP(DRLCMAC, LOGL_DEBUG, "- Selected DL TS %d\n", ts);
608
609 /* range of window (required for Type 1) */
610 rx_win_max = ts;
611
612 if (++i == Rx) {
613 LOGP(DRLCMAC, LOGL_DEBUG, "- Done, because slots / "
614 "window reached maximum alowed Rx size\n");
615 break;
616 }
617 }
618
619 LOGP(DRLCMAC, LOGL_DEBUG, "- Selected slots for RX: "
620 "(TS=0)\"%c%c%c%c%c%c%c%c\"(TS=7)\n",
621 ((rx_window & 0x01)) ? 'D' : '.',
622 ((rx_window & 0x02)) ? 'D' : '.',
623 ((rx_window & 0x04)) ? 'D' : '.',
624 ((rx_window & 0x08)) ? 'D' : '.',
625 ((rx_window & 0x10)) ? 'D' : '.',
626 ((rx_window & 0x20)) ? 'D' : '.',
627 ((rx_window & 0x40)) ? 'D' : '.',
628 ((rx_window & 0x80)) ? 'D' : '.');
629
630 /* reduce window, if existing uplink slots collide RX window */
631 if (Type == 1 && old_tbf && old_tbf->direction == GPRS_RLCMAC_UL_TBF) {
632 uint8_t collide = 0, ul_usage = 0;
633 int j;
634
635 /* calculate mask of colliding slots */
Andreas Eversberg02d7cd22013-01-15 08:59:34 +0100636 for (ts = 0; ts < 8; ts++) {
Andreas Eversberg53f47252012-07-15 07:10:10 +0200637 if (old_tbf->pdch[ts]) {
638 ul_usage |= (1 << ts);
639 /* mark bits from TS-t .. TS+r */
640 for (j = ts - Tt; j != ((ts + Tr + 1) & 7);
641 j = (j + 1) & 7)
642 collide |= (1 << j);
643 }
644 }
645 LOGP(DRLCMAC, LOGL_DEBUG, "- Not allowed slots due to existing "
646 "UL allocation: (TS=0)\"%c%c%c%c%c%c%c%c\"(TS=7) "
647 " D=downlink x=not usable\n",
648 ((ul_usage & 0x01)) ? 'D' : ((collide & 0x01))?'x':'.',
649 ((ul_usage & 0x02)) ? 'D' : ((collide & 0x02))?'x':'.',
650 ((ul_usage & 0x04)) ? 'D' : ((collide & 0x04))?'x':'.',
651 ((ul_usage & 0x08)) ? 'D' : ((collide & 0x08))?'x':'.',
652 ((ul_usage & 0x10)) ? 'D' : ((collide & 0x10))?'x':'.',
653 ((ul_usage & 0x20)) ? 'D' : ((collide & 0x20))?'x':'.',
654 ((ul_usage & 0x40)) ? 'D' : ((collide & 0x40))?'x':'.',
655 ((ul_usage & 0x80)) ? 'D' : ((collide & 0x80))?'x':'.');
656
657 /* apply massk to reduce tx_window (shifted by 3 slots) */
658 rx_window &= ~(collide << 3);
659 rx_window &= ~(collide >> 5);
660 LOGP(DRLCMAC, LOGL_DEBUG, "- Remaining slots for RX: "
661 "(TS=0)\"%c%c%c%c%c%c%c%c\"(TS=7)\n",
662 ((rx_window & 0x01)) ? 'D' : '.',
663 ((rx_window & 0x02)) ? 'D' : '.',
664 ((rx_window & 0x04)) ? 'D' : '.',
665 ((rx_window & 0x08)) ? 'D' : '.',
666 ((rx_window & 0x10)) ? 'D' : '.',
667 ((rx_window & 0x20)) ? 'D' : '.',
668 ((rx_window & 0x40)) ? 'D' : '.',
669 ((rx_window & 0x80)) ? 'D' : '.');
670 if (!rx_window) {
671 LOGP(DRLCMAC, LOGL_NOTICE, "No suitable downlink slots "
672 "available with current uplink assignment\n");
673 return -EBUSY;
674 }
675
676 /* calculate new min/max */
677 for (ts = rx_win_min; ts <= rx_win_max; ts++) {
678 if ((rx_window & (1 << ts)))
679 break;
680 rx_win_min = ts + 1;
Andreas Eversberg52c748c2012-07-15 16:33:02 +0200681 LOGP(DRLCMAC, LOGL_DEBUG, "- TS has been deleted, so "
Andreas Eversberg53f47252012-07-15 07:10:10 +0200682 "raising start of DL window to %d\n",
683 rx_win_min);
684 }
685 for (ts = rx_win_max; ts >= rx_win_min; ts--) {
686 if ((rx_window & (1 << ts)))
687 break;
688 rx_win_max = ts - 1;
Andreas Eversberg52c748c2012-07-15 16:33:02 +0200689 LOGP(DRLCMAC, LOGL_DEBUG, "- TS has been deleted, so "
Andreas Eversberg53f47252012-07-15 07:10:10 +0200690 "lowering end of DL window to %d\n",
691 rx_win_max);
692 }
693 }
694
695 /* reduce window, to allow at least one uplink TX slot
696 * this is only required for Type 1 */
697 if (Type == 1 && rx_win_max - rx_win_min + 1 + Tt + 1 + Tr > 8) {
Andreas Eversberg97644ed2013-01-15 13:20:22 +0100698 rx_win_max = rx_win_min + 7 - Tt - 1 - Tr;
Andreas Eversberg53f47252012-07-15 07:10:10 +0200699 LOGP(DRLCMAC, LOGL_DEBUG, "- Reduce RX window due to time "
700 "contraints to %d slots\n",
701 rx_win_max - rx_win_min + 1);
702 }
703
704 LOGP(DRLCMAC, LOGL_DEBUG, "- RX-Window is: %d..%d\n", rx_win_min,
705 rx_win_max);
706
707 /* calculate TX window */
708 if (Type == 1) {
709 /* calculate TX window (shifted by 3 timeslots)
710 * it uses the space between tx_win_max and tx_win_min */
711 tx_win_min = (rx_win_max - 2 + Tt) & 7;
712 tx_win_max = (rx_win_min + 4 - Tr) & 7;
713 /* calculate the TX window size (might be larger than Tx) */
714 tx_range = (tx_win_max - tx_win_min + 1) & 7;
715 } else {
716 /* TX and RX simultaniously */
717 tx_win_min = rx_win_min;
718 tx_win_max = 7;
719 /* TX window size (might be larger than Tx) */
720 tx_range = tx_win_max - tx_win_min + 1;
721 }
722
723 LOGP(DRLCMAC, LOGL_DEBUG, "- TX-Window is: %d..%d\n", tx_win_min,
724 tx_win_max);
725
726 /* select a window of Tx slots if available
727 * The maximum allowed slots depend on TX or the window of available
Andreas Eversberg97644ed2013-01-15 13:20:22 +0100728 * slots.
729 *
730 * also assign the first common ts, which is used for control or single
731 * slot. */
Andreas Eversberg53f47252012-07-15 07:10:10 +0200732 if (tbf->direction == GPRS_RLCMAC_UL_TBF) {
733 for (ts = tx_win_min, i = 0; i < tx_range; ts = (ts + 1) & 7) {
734 pdch = &bts->trx[tbf->trx].pdch[ts];
735 /* check if enabled */
736 if (!pdch->enable) {
737 LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, "
738 "because not enabled\n", ts);
739 continue;
740 }
741 /* check if TSC changes */
742 if (tsc < 0)
743 tbf->tsc = tsc = pdch->tsc;
744 else if (tsc != pdch->tsc) {
745 LOGP(DRLCMAC, LOGL_ERROR, "Skipping TS %d of "
746 "TRX=%d, because it has different TSC "
747 "than lower TS of TRX. In order to "
748 "allow multislot, all slots must be "
749 "configured with the same TSC!\n",
750 ts, tbf->trx);
751 /* increase window for Type 1 */
752 if (Type == 1)
753 i++;
754 continue;
755 }
Andreas Eversberg53f47252012-07-15 07:10:10 +0200756 /* check for free usf */
757 usf[ts] = find_free_usf(pdch, ts);
758 if (usf[ts] < 0) {
759 LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, "
760 "because no USF available\n", ts);
761 /* increase window for Type 1 */
762 if (Type == 1)
763 i++;
764 continue;
765 }
766
Andreas Eversberg97644ed2013-01-15 13:20:22 +0100767 if (!tx_window)
768 first_common_ts = ts;
769
Andreas Eversberg53f47252012-07-15 07:10:10 +0200770 tx_window |= (1 << ts);
771 LOGP(DRLCMAC, LOGL_DEBUG, "- Selected UL TS %d\n", ts);
772
Andreas Eversberg97644ed2013-01-15 13:20:22 +0100773 if (1 && Type == 1) { /* FIXME: multislot UL assignment */
Andreas Eversberg53f47252012-07-15 07:10:10 +0200774 LOGP(DRLCMAC, LOGL_DEBUG, "- Done, because "
775 "1 slot assigned\n");
776 break;
777 }
778 if (++i == Tx) {
779 LOGP(DRLCMAC, LOGL_DEBUG, "- Done, because "
Andreas Eversbergf01929b2012-10-08 12:40:49 +0200780 "slots / window reached maximum "
781 "allowed Tx size\n");
Andreas Eversberg53f47252012-07-15 07:10:10 +0200782 break;
783 }
784 }
785
786 LOGP(DRLCMAC, LOGL_DEBUG, "- Selected TX window: "
787 "(TS=0)\"%c%c%c%c%c%c%c%c\"(TS=7)\n",
788 ((tx_window & 0x01)) ? 'U' : '.',
789 ((tx_window & 0x02)) ? 'U' : '.',
790 ((tx_window & 0x04)) ? 'U' : '.',
791 ((tx_window & 0x08)) ? 'U' : '.',
792 ((tx_window & 0x10)) ? 'U' : '.',
793 ((tx_window & 0x20)) ? 'U' : '.',
794 ((tx_window & 0x40)) ? 'U' : '.',
795 ((tx_window & 0x80)) ? 'U' : '.');
796
797 if (!tx_window) {
798 LOGP(DRLCMAC, LOGL_NOTICE, "No suitable uplink slots "
799 "available\n");
800 return -EBUSY;
801 }
Andreas Eversberg97644ed2013-01-15 13:20:22 +0100802 } else {
803 /* assign the first common ts, which is used for control or
804 * single slot. */
805 for (ts = tx_win_min, i = 0; i < tx_range; ts = (ts + 1) & 7) {
806 pdch = &bts->trx[tbf->trx].pdch[ts];
807 /* check if enabled */
808 if (!pdch->enable) {
809 LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, "
810 "because not enabled\n", ts);
811 continue;
812 }
813 first_common_ts = ts;
814 break;
815 }
816 }
817
818 if (first_common_ts < 0) {
819 LOGP(DRLCMAC, LOGL_NOTICE, "No first common slots available\n");
820 return -EINVAL;
Andreas Eversberg53f47252012-07-15 07:10:10 +0200821 }
822
823 if (tbf->direction == GPRS_RLCMAC_DL_TBF) {
824 /* assign downlink */
825 if (rx_window == 0) {
826 LOGP(DRLCMAC, LOGL_NOTICE, "No downlink slots "
827 "available\n");
828 return -EINVAL;
829 }
830 for (ts = 0; ts < 8; ts++) {
831 if ((rx_window & (1 << ts))) {
Andreas Eversbergf01929b2012-10-08 12:40:49 +0200832 /* be sure to select a single downlink slots
833 * that can be used for uplink, if multiple
834 * slots are assigned later. */
Andreas Eversberg97644ed2013-01-15 13:20:22 +0100835 if (single && first_common_ts != ts)
Andreas Eversbergf01929b2012-10-08 12:40:49 +0200836 continue;
Andreas Eversberg53f47252012-07-15 07:10:10 +0200837 LOGP(DRLCMAC, LOGL_DEBUG, "- Assigning DL TS "
838 "%d\n", ts);
839 pdch = &bts->trx[tbf->trx].pdch[ts];
Andreas Eversbergadb2f182012-08-07 17:06:08 +0200840 bts->trx[tbf->trx].dl_tbf[tbf->tfi] = tbf;
Andreas Eversberg53f47252012-07-15 07:10:10 +0200841 pdch->dl_tbf[tbf->tfi] = tbf;
842 tbf->pdch[ts] = pdch;
Andreas Eversberg52c748c2012-07-15 16:33:02 +0200843 slotcount++;
Andreas Eversbergf01929b2012-10-08 12:40:49 +0200844 if (slotcount == 1)
845 tbf->first_ts = ts;
846 if (single)
847 break;
Andreas Eversberg53f47252012-07-15 07:10:10 +0200848 }
849 }
850 } else {
851 /* assign uplink */
852 if (tx_window == 0) {
853 LOGP(DRLCMAC, LOGL_NOTICE, "No uplink slots "
854 "available\n");
855 return -EINVAL;
856 }
857 for (ts = 0; ts < 8; ts++) {
858 if ((tx_window & (1 << ts))) {
859 LOGP(DRLCMAC, LOGL_DEBUG, "- Assigning UL TS "
860 "%d\n", ts);
861 pdch = &bts->trx[tbf->trx].pdch[ts];
Andreas Eversbergadb2f182012-08-07 17:06:08 +0200862 bts->trx[tbf->trx].ul_tbf[tbf->tfi] = tbf;
Andreas Eversberg53f47252012-07-15 07:10:10 +0200863 pdch->ul_tbf[tbf->tfi] = tbf;
864 tbf->pdch[ts] = pdch;
865 tbf->dir.ul.usf[ts] = usf[ts];
Andreas Eversbergf01929b2012-10-08 12:40:49 +0200866 slotcount++;
867 if (slotcount == 1)
868 tbf->first_ts = ts;
869 if (single)
870 break;
Andreas Eversberg53f47252012-07-15 07:10:10 +0200871 }
872 }
873 }
Andreas Eversbergf01929b2012-10-08 12:40:49 +0200874 if (single && slotcount) {
875 LOGP(DRLCMAC, LOGL_INFO, "Using single slot at TS %d for %s\n",
876 tbf->first_ts,
877 (tbf->direction == GPRS_RLCMAC_DL_TBF) ? "DL" : "UL");
878 } else {
879 LOGP(DRLCMAC, LOGL_INFO, "Using %d slots for %s\n", slotcount,
880 (tbf->direction == GPRS_RLCMAC_DL_TBF) ? "DL" : "UL");
881 }
882 if (slotcount == 0)
883 return -EBUSY;
Andreas Eversberg53f47252012-07-15 07:10:10 +0200884
Andreas Eversberg97644ed2013-01-15 13:20:22 +0100885 tbf->first_common_ts = first_common_ts;
Andreas Eversberg53f47252012-07-15 07:10:10 +0200886
887 return 0;
888}
889
Andreas Eversberg592e04a2012-07-15 06:25:37 +0200890static void tbf_unlink_pdch(struct gprs_rlcmac_tbf *tbf)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400891{
Andreas Eversbergadb2f182012-08-07 17:06:08 +0200892 struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200893 struct gprs_rlcmac_pdch *pdch;
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200894 int ts;
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200895
Andreas Eversberg592e04a2012-07-15 06:25:37 +0200896 if (tbf->direction == GPRS_RLCMAC_UL_TBF) {
Andreas Eversbergadb2f182012-08-07 17:06:08 +0200897 bts->trx[tbf->trx].ul_tbf[tbf->tfi] = NULL;
Andreas Eversberg592e04a2012-07-15 06:25:37 +0200898 for (ts = 0; ts < 8; ts++) {
899 pdch = tbf->pdch[ts];
900 if (pdch)
901 pdch->ul_tbf[tbf->tfi] = NULL;
902 tbf->pdch[ts] = NULL;
903 }
904 } else {
Andreas Eversbergadb2f182012-08-07 17:06:08 +0200905 bts->trx[tbf->trx].dl_tbf[tbf->tfi] = NULL;
Andreas Eversberg592e04a2012-07-15 06:25:37 +0200906 for (ts = 0; ts < 8; ts++) {
907 pdch = tbf->pdch[ts];
908 if (pdch)
909 pdch->dl_tbf[tbf->tfi] = NULL;
910 tbf->pdch[ts] = NULL;
911 }
912 }
913}
914
915void tbf_free(struct gprs_rlcmac_tbf *tbf)
916{
917 struct msgb *msg;
918
Andreas Eversberg050ace22013-03-16 16:22:02 +0100919 /* Give final measurement report */
920 gprs_rlcmac_rssi_rep(tbf);
921 gprs_rlcmac_lost_rep(tbf);
922
Andreas Eversbergb83e2a72012-10-07 15:26:00 +0200923 debug_diagram(tbf->diag, "+---------------+");
924 debug_diagram(tbf->diag, "| THE END |");
925 debug_diagram(tbf->diag, "+---------------+");
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200926 LOGP(DRLCMAC, LOGL_INFO, "Free %s TBF=%d with TLLI=0x%08x.\n",
927 (tbf->direction == GPRS_RLCMAC_UL_TBF) ? "UL" : "DL", tbf->tfi,
Andreas Eversberge6228b32012-07-03 13:36:03 +0200928 tbf->tlli);
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200929 if (tbf->ul_ass_state != GPRS_RLCMAC_UL_ASS_NONE)
930 LOGP(DRLCMAC, LOGL_ERROR, "Software error: Pending uplink "
931 "assignment. This may not happen, because the "
932 "assignment message never gets transmitted. Please "
933 "be shure not to free in this state. PLEASE FIX!\n");
934 if (tbf->dl_ass_state != GPRS_RLCMAC_DL_ASS_NONE)
935 LOGP(DRLCMAC, LOGL_ERROR, "Software error: Pending downlink "
936 "assignment. This may not happen, because the "
937 "assignment message never gets transmitted. Please "
938 "be shure not to free in this state. PLEASE FIX!\n");
Andreas Eversberg5dac2f02012-06-27 15:52:04 +0200939 tbf_timer_stop(tbf);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200940 while ((msg = msgb_dequeue(&tbf->llc_queue)))
941 msgb_free(msg);
Andreas Eversberg592e04a2012-07-15 06:25:37 +0200942 tbf_unlink_pdch(tbf);
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400943 llist_del(&tbf->list);
Andreas Eversberg0e403092012-07-06 11:04:57 +0200944 LOGP(DRLCMAC, LOGL_DEBUG, "********** TBF ends here **********\n");
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +0400945 talloc_free(tbf);
946}
947
Andreas Eversberg592e04a2012-07-15 06:25:37 +0200948int tbf_update(struct gprs_rlcmac_tbf *tbf)
949{
950 struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
951 struct gprs_rlcmac_tbf *ul_tbf = NULL;
952 int rc;
953
954 LOGP(DRLCMAC, LOGL_DEBUG, "********** TBF update **********\n");
955
956 if (tbf->direction != GPRS_RLCMAC_DL_TBF)
957 return -EINVAL;
958
959 if (!tbf->ms_class) {
960 LOGP(DRLCMAC, LOGL_DEBUG, "- Cannot update, no class\n");
961 return -EINVAL;
962 }
963
Andreas Eversberga9b94072012-07-15 19:30:41 +0200964 ul_tbf = tbf_by_tlli(tbf->tlli, GPRS_RLCMAC_UL_TBF);
Andreas Eversberg592e04a2012-07-15 06:25:37 +0200965
966 tbf_unlink_pdch(tbf);
Holger Hans Peter Freytherb67a8a32013-07-28 18:55:14 +0200967 rc = bts->alloc_algorithm(bts, ul_tbf, tbf, bts->alloc_algorithm_curst, 0);
Andreas Eversberg592e04a2012-07-15 06:25:37 +0200968 /* if no ressource */
969 if (rc < 0) {
970 LOGP(DRLCMAC, LOGL_ERROR, "No ressource after update???\n");
971 return -rc;
972 }
973
974 return 0;
975}
976
977int tbf_assign_control_ts(struct gprs_rlcmac_tbf *tbf)
978{
979 if (tbf->control_ts == 0xff)
Andreas Eversbergf01929b2012-10-08 12:40:49 +0200980 LOGP(DRLCMAC, LOGL_INFO, "- Setting Control TS %d\n",
Andreas Eversberg52c748c2012-07-15 16:33:02 +0200981 tbf->first_common_ts);
Andreas Eversberg592e04a2012-07-15 06:25:37 +0200982 else if (tbf->control_ts != tbf->first_common_ts)
Andreas Eversbergf01929b2012-10-08 12:40:49 +0200983 LOGP(DRLCMAC, LOGL_INFO, "- Changing Control TS %d\n",
Andreas Eversberg52c748c2012-07-15 16:33:02 +0200984 tbf->first_common_ts);
Andreas Eversberg592e04a2012-07-15 06:25:37 +0200985 tbf->control_ts = tbf->first_common_ts;
986
987 return 0;
988}
989
990
Andreas Eversberge6228b32012-07-03 13:36:03 +0200991const char *tbf_state_name[] = {
992 "NULL",
993 "ASSIGN",
994 "FLOW",
995 "FINISHED",
996 "WAIT RELEASE",
997 "RELEASING",
998};
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +0400999
Andreas Eversberge6228b32012-07-03 13:36:03 +02001000void tbf_new_state(struct gprs_rlcmac_tbf *tbf,
1001 enum gprs_rlcmac_tbf_state state)
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +04001002{
Andreas Eversbergb83e2a72012-10-07 15:26:00 +02001003 debug_diagram(tbf->diag, "->%s", tbf_state_name[state]);
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001004 LOGP(DRLCMAC, LOGL_DEBUG, "%s TBF=%d changes state from %s to %s\n",
1005 (tbf->direction == GPRS_RLCMAC_UL_TBF) ? "UL" : "DL", tbf->tfi,
1006 tbf_state_name[tbf->state], tbf_state_name[state]);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001007 tbf->state = state;
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +04001008}
1009
Andreas Eversberg5dac2f02012-06-27 15:52:04 +02001010void tbf_timer_start(struct gprs_rlcmac_tbf *tbf, unsigned int T,
Andreas Eversberge6228b32012-07-03 13:36:03 +02001011 unsigned int seconds, unsigned int microseconds)
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +04001012{
Andreas Eversberg5dac2f02012-06-27 15:52:04 +02001013 if (!osmo_timer_pending(&tbf->timer))
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001014 LOGP(DRLCMAC, LOGL_DEBUG, "Starting %s TBF=%d timer %u.\n",
1015 (tbf->direction == GPRS_RLCMAC_UL_TBF) ? "UL" : "DL",
Andreas Eversberge6228b32012-07-03 13:36:03 +02001016 tbf->tfi, T);
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +04001017 else
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001018 LOGP(DRLCMAC, LOGL_DEBUG, "Restarting %s TBF=%d timer %u "
1019 "while old timer %u pending \n",
1020 (tbf->direction == GPRS_RLCMAC_UL_TBF) ? "UL" : "DL",
1021 tbf->tfi, T, tbf->T);
Ivan Kluchnikova9e6dc52012-06-17 08:30:06 +04001022
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +04001023 tbf->T = T;
1024 tbf->num_T_exp = 0;
1025
Andreas Eversberg5dac2f02012-06-27 15:52:04 +02001026 /* Tunning timers can be safely re-scheduled. */
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +04001027 tbf->timer.data = tbf;
1028 tbf->timer.cb = &tbf_timer_cb;
1029
Andreas Eversberge6228b32012-07-03 13:36:03 +02001030 osmo_timer_schedule(&tbf->timer, seconds, microseconds);
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +04001031}
1032
Andreas Eversberg5dac2f02012-06-27 15:52:04 +02001033void tbf_timer_stop(struct gprs_rlcmac_tbf *tbf)
1034{
1035 if (osmo_timer_pending(&tbf->timer)) {
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001036 LOGP(DRLCMAC, LOGL_DEBUG, "Stopping %s TBF=%d timer %u.\n",
1037 (tbf->direction == GPRS_RLCMAC_UL_TBF) ? "UL" : "DL",
Andreas Eversberge6228b32012-07-03 13:36:03 +02001038 tbf->tfi, tbf->T);
Andreas Eversberg5dac2f02012-06-27 15:52:04 +02001039 osmo_timer_del(&tbf->timer);
1040 }
1041}
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +04001042
Andreas Eversberg07e97cf2012-08-07 16:00:56 +02001043/* starting time for assigning single slot
1044 * This offset must be a multiple of 13. */
1045#define AGCH_START_OFFSET 52
1046
1047LLIST_HEAD(gprs_rlcmac_sbas);
1048
1049int sba_alloc(uint8_t *_trx, uint8_t *_ts, uint32_t *_fn, uint8_t ta)
1050{
1051
1052 struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
1053 struct gprs_rlcmac_pdch *pdch;
1054 struct gprs_rlcmac_sba *sba;
1055 uint8_t trx, ts;
1056 uint32_t fn;
1057
1058 sba = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_sba);
1059 if (!sba)
1060 return -ENOMEM;
1061
1062 for (trx = 0; trx < 8; trx++) {
1063 for (ts = 0; ts < 8; ts++) {
1064 pdch = &bts->trx[trx].pdch[ts];
1065 if (!pdch->enable)
1066 continue;
1067 break;
1068 }
1069 if (ts < 8)
1070 break;
1071 }
1072 if (trx == 8) {
1073 LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH available.\n");
1074 return -EINVAL;
1075 }
1076
1077 fn = (pdch->last_rts_fn + AGCH_START_OFFSET) % 2715648;
1078
1079 sba->trx = trx;
1080 sba->ts = ts;
1081 sba->fn = fn;
1082 sba->ta = ta;
1083
1084 llist_add(&sba->list, &gprs_rlcmac_sbas);
1085
1086 *_trx = trx;
1087 *_ts = ts;
1088 *_fn = fn;
1089 return 0;
1090}
1091
1092struct gprs_rlcmac_sba *sba_find(uint8_t trx, uint8_t ts, uint32_t fn)
1093{
1094 struct gprs_rlcmac_sba *sba;
1095
1096 llist_for_each_entry(sba, &gprs_rlcmac_sbas, list) {
1097 if (sba->trx == trx && sba->ts == ts && sba->fn == fn)
1098 return sba;
1099 }
1100
1101 return NULL;
1102}
1103
Andreas Eversberge6228b32012-07-03 13:36:03 +02001104#if 0
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +04001105static void tbf_gsm_timer_cb(void *_tbf)
1106{
1107 struct gprs_rlcmac_tbf *tbf = (struct gprs_rlcmac_tbf *)_tbf;
1108
1109 tbf->num_fT_exp++;
1110
1111 switch (tbf->fT) {
1112 case 0:
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001113hier alles berdenken
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +04001114 // This is timer for delay RLC/MAC data sending after Downlink Immediate Assignment on CCCH.
1115 gprs_rlcmac_segment_llc_pdu(tbf);
Ivan Kluchnikova9f1ff22012-05-24 22:25:06 +04001116 LOGP(DRLCMAC, LOGL_NOTICE, "TBF: [DOWNLINK] END TFI: %u TLLI: 0x%08x \n", tbf->tfi, tbf->tlli);
Ivan Kluchnikov9c795ab2012-05-24 23:12:59 +04001117 tbf_free(tbf);
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +04001118 break;
1119 default:
Ivan Kluchnikov856221f2012-06-15 09:31:29 +04001120 LOGP(DRLCMAC, LOGL_NOTICE, "Timer expired in unknown mode: %u \n", tbf->fT);
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +04001121 }
1122}
1123
1124static void tbf_gsm_timer_start(struct gprs_rlcmac_tbf *tbf, unsigned int fT,
1125 int frames)
1126{
1127 if (osmo_gsm_timer_pending(&tbf->gsm_timer))
Ivan Kluchnikov856221f2012-06-15 09:31:29 +04001128 LOGP(DRLCMAC, LOGL_NOTICE, "Starting TBF timer %u while old timer %u pending \n", fT, tbf->fT);
Ivan Kluchnikov61a33f72012-04-12 15:22:06 +04001129 tbf->fT = fT;
1130 tbf->num_fT_exp = 0;
1131
1132 /* FIXME: we should do this only once ? */
1133 tbf->gsm_timer.data = tbf;
1134 tbf->gsm_timer.cb = &tbf_gsm_timer_cb;
1135
1136 osmo_gsm_timer_schedule(&tbf->gsm_timer, frames);
1137}
1138
Andreas Eversberge6228b32012-07-03 13:36:03 +02001139eine stop-funktion, auch im tbf_free aufrufen
1140
1141#endif
1142
1143#if 0
Andreas Eversberg5dac2f02012-06-27 15:52:04 +02001144void gprs_rlcmac_enqueue_block(bitvec *block, int len)
Andreas Eversberg0aed6542012-06-23 10:33:16 +02001145{
1146 struct msgb *msg = msgb_alloc(len, "rlcmac_dl");
1147 bitvec_pack(block, msgb_put(msg, len));
1148 msgb_enqueue(&block_queue, msg);
1149}
Andreas Eversberge6228b32012-07-03 13:36:03 +02001150#endif
Andreas Eversberg0aed6542012-06-23 10:33:16 +02001151
Andreas Eversberge6228b32012-07-03 13:36:03 +02001152/* received RLC/MAC block from L1 */
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001153int gprs_rlcmac_rcv_block(uint8_t trx, uint8_t ts, uint8_t *data, uint8_t len,
Andreas Eversberg570b44b2013-03-16 16:15:01 +01001154 uint32_t fn, int8_t rssi)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04001155{
Andreas Eversberge6228b32012-07-03 13:36:03 +02001156 unsigned payload = data[0] >> 6;
1157 bitvec *block;
1158 int rc = 0;
Ivan Kluchnikov34460b82012-06-27 18:41:04 +04001159
Andreas Eversberge6228b32012-07-03 13:36:03 +02001160 switch (payload) {
1161 case GPRS_RLCMAC_DATA_BLOCK:
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001162 rc = gprs_rlcmac_rcv_data_block_acknowledged(trx, ts, data,
Andreas Eversberg570b44b2013-03-16 16:15:01 +01001163 len, rssi);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001164 break;
1165 case GPRS_RLCMAC_CONTROL_BLOCK:
1166 block = bitvec_alloc(len);
1167 if (!block)
1168 return -ENOMEM;
1169 bitvec_unpack(block, data);
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001170 rc = gprs_rlcmac_rcv_control_block(block, trx, ts, fn);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001171 bitvec_free(block);
1172 break;
1173 case GPRS_RLCMAC_CONTROL_BLOCK_OPT:
1174 LOGP(DRLCMAC, LOGL_NOTICE, "GPRS_RLCMAC_CONTROL_BLOCK_OPT block payload is not supported.\n");
1175 default:
1176 LOGP(DRLCMAC, LOGL_NOTICE, "Unknown RLCMAC block payload.\n");
1177 rc = -EINVAL;
Ivan Kluchnikov34460b82012-06-27 18:41:04 +04001178 }
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04001179
Andreas Eversberge6228b32012-07-03 13:36:03 +02001180 return rc;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04001181}
1182
Andreas Eversberg2b914642012-07-19 13:06:26 +02001183/* add paging to paging queue(s) */
1184int gprs_rlcmac_add_paging(uint8_t chan_needed, uint8_t *identity_lv)
1185{
1186 struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
1187 uint8_t l, trx, ts, any_tbf = 0;
1188 struct gprs_rlcmac_tbf *tbf;
1189 struct gprs_rlcmac_paging *pag;
1190 uint8_t slot_mask[8];
1191 int8_t first_ts; /* must be signed */
1192
Andreas Eversberg3b7461c2012-07-20 11:19:59 +02001193 LOGP(DRLCMAC, LOGL_INFO, "Add RR paging: chan-needed=%d MI=%s\n",
1194 chan_needed, osmo_hexdump(identity_lv + 1, identity_lv[0]));
Andreas Eversberg2b914642012-07-19 13:06:26 +02001195
1196 /* collect slots to page
1197 * Mark slots for every TBF, but only mark one of it.
1198 * Mark only the first slot found.
1199 * Don't mark, if TBF uses a different slot that is already marked. */
1200 memset(slot_mask, 0, sizeof(slot_mask));
1201 for (l = 0; gprs_rlcmac_tbfs_lists[l]; l++) {
1202 llist_for_each_entry(tbf, gprs_rlcmac_tbfs_lists[l], list) {
1203 first_ts = -1;
1204 for (ts = 0; ts < 8; ts++) {
1205 if (tbf->pdch[ts]) {
1206 /* remember the first slot found */
1207 if (first_ts < 0)
1208 first_ts = ts;
1209 /* break, if we already marked a slot */
1210 if ((slot_mask[tbf->trx] & (1 << ts)))
1211 break;
1212 }
1213 }
1214 /* mark first slot found, if none is marked already */
1215 if (ts == 8 && first_ts >= 0) {
1216 LOGP(DRLCMAC, LOGL_DEBUG, "- %s TBF=%d uses "
1217 "TRX=%d TS=%d, so we mark\n",
1218 (tbf->direction == GPRS_RLCMAC_UL_TBF)
1219 ? "UL" : "DL",
Andreas Eversberg3b7461c2012-07-20 11:19:59 +02001220 tbf->tfi, tbf->trx, first_ts);
Andreas Eversberg2b914642012-07-19 13:06:26 +02001221 slot_mask[tbf->trx] |= (1 << first_ts);
1222 } else
1223 LOGP(DRLCMAC, LOGL_DEBUG, "- %s TBF=%d uses "
1224 "already marked TRX=%d TS=%d\n",
1225 (tbf->direction == GPRS_RLCMAC_UL_TBF)
1226 ? "UL" : "DL",
1227 tbf->tfi, tbf->trx, ts);
1228 }
1229 }
1230
1231 /* Now we have a list of marked slots. Every TBF uses at least one
1232 * of these slots. */
1233
1234 /* schedule paging to all marked slots */
1235 for (trx = 0; trx < 8; trx++) {
1236 if (slot_mask[trx] == 0)
1237 continue;
1238 any_tbf = 1;
1239 for (ts = 0; ts < 8; ts++) {
1240 if ((slot_mask[trx] & (1 << ts))) {
1241 /* schedule */
Andreas Eversberg6681bb82012-07-25 08:48:44 +02001242 pag = talloc_zero(tall_pcu_ctx,
Andreas Eversberg2b914642012-07-19 13:06:26 +02001243 struct gprs_rlcmac_paging);
1244 if (!pag)
1245 return -ENOMEM;
1246 pag->chan_needed = chan_needed;
1247 memcpy(pag->identity_lv, identity_lv,
1248 identity_lv[0] + 1);
1249 llist_add(&pag->list,
1250 &bts->trx[trx].pdch[ts].paging_list);
Andreas Eversberg3b7461c2012-07-20 11:19:59 +02001251 LOGP(DRLCMAC, LOGL_INFO, "Paging on PACCH of "
1252 "TRX=%d TS=%d\n", trx, ts);
Andreas Eversberg2b914642012-07-19 13:06:26 +02001253 }
1254 }
1255 }
1256
Andreas Eversberg3b7461c2012-07-20 11:19:59 +02001257 if (!any_tbf)
Andreas Eversberg2b914642012-07-19 13:06:26 +02001258 LOGP(DRLCMAC, LOGL_INFO, "No paging, because no TBF\n");
Andreas Eversberg2b914642012-07-19 13:06:26 +02001259
1260 return 0;
1261}
1262
1263struct gprs_rlcmac_paging *gprs_rlcmac_dequeue_paging(
1264 struct gprs_rlcmac_pdch *pdch)
1265{
1266 struct gprs_rlcmac_paging *pag;
1267
Andreas Eversberg3b7461c2012-07-20 11:19:59 +02001268 if (llist_empty(&pdch->paging_list))
1269 return NULL;
Andreas Eversberg2b914642012-07-19 13:06:26 +02001270 pag = llist_entry(pdch->paging_list.next,
1271 struct gprs_rlcmac_paging, list);
1272 llist_del(&pag->list);
1273
1274 return pag;
1275}
1276
1277struct msgb *gprs_rlcmac_send_packet_paging_request(
1278 struct gprs_rlcmac_pdch *pdch)
1279{
1280 struct gprs_rlcmac_paging *pag;
1281 struct msgb *msg;
1282 unsigned wp = 0, len;
1283
1284 /* no paging, no message */
1285 pag = gprs_rlcmac_dequeue_paging(pdch);
1286 if (!pag)
1287 return NULL;
1288
1289 LOGP(DRLCMAC, LOGL_DEBUG, "Scheduling paging\n");
1290
1291 /* alloc message */
1292 msg = msgb_alloc(23, "pag ctrl block");
Andreas Eversberg5cae0872012-10-07 15:08:22 +02001293 if (!msg) {
1294 talloc_free(pag);
Andreas Eversberg2b914642012-07-19 13:06:26 +02001295 return NULL;
Andreas Eversberg5cae0872012-10-07 15:08:22 +02001296 }
Andreas Eversberg2b914642012-07-19 13:06:26 +02001297 bitvec *pag_vec = bitvec_alloc(23);
1298 if (!pag_vec) {
1299 msgb_free(msg);
Andreas Eversberg5cae0872012-10-07 15:08:22 +02001300 talloc_free(pag);
Andreas Eversberg2b914642012-07-19 13:06:26 +02001301 return NULL;
1302 }
1303 wp = write_packet_paging_request(pag_vec);
1304
1305 /* loop until message is full */
1306 while (pag) {
1307 /* try to add paging */
1308 if ((pag->identity_lv[1] & 0x07) == 4) {
1309 /* TMSI */
1310 LOGP(DRLCMAC, LOGL_DEBUG, "- TMSI=0x%08x\n",
1311 ntohl(*((uint32_t *)(pag->identity_lv + 1))));
Andreas Eversberg3b7461c2012-07-20 11:19:59 +02001312 len = 1 + 1 + 1 + 32 + 2 + 1;
Andreas Eversberg2b914642012-07-19 13:06:26 +02001313 if (pag->identity_lv[0] != 5) {
1314 LOGP(DRLCMAC, LOGL_ERROR, "TMSI paging with "
1315 "MI != 5 octets!\n");
Andreas Eversberg5cae0872012-10-07 15:08:22 +02001316 goto continue_next;
Andreas Eversberg2b914642012-07-19 13:06:26 +02001317 }
1318 } else {
1319 /* MI */
1320 LOGP(DRLCMAC, LOGL_DEBUG, "- MI=%s\n",
1321 osmo_hexdump(pag->identity_lv + 1,
1322 pag->identity_lv[0]));
Andreas Eversberg3b7461c2012-07-20 11:19:59 +02001323 len = 1 + 1 + 1 + 4 + (pag->identity_lv[0]<<3) + 2 + 1;
Andreas Eversberg2b914642012-07-19 13:06:26 +02001324 if (pag->identity_lv[0] > 8) {
1325 LOGP(DRLCMAC, LOGL_ERROR, "Paging with "
1326 "MI > 8 octets!\n");
Andreas Eversberg5cae0872012-10-07 15:08:22 +02001327 goto continue_next;
Andreas Eversberg2b914642012-07-19 13:06:26 +02001328 }
1329 }
1330 if (wp + len > 184) {
1331 LOGP(DRLCMAC, LOGL_DEBUG, "- Does not fit, so schedule "
1332 "next time\n");
1333 /* put back paging record, because does not fit */
1334 llist_add_tail(&pag->list, &pdch->paging_list);
1335 break;
1336 }
1337 write_repeated_page_info(pag_vec, wp, pag->identity_lv[0],
1338 pag->identity_lv + 1, pag->chan_needed);
1339
Andreas Eversberg5cae0872012-10-07 15:08:22 +02001340continue_next:
1341 talloc_free(pag);
Andreas Eversberg2b914642012-07-19 13:06:26 +02001342 pag = gprs_rlcmac_dequeue_paging(pdch);
1343 }
1344
1345 bitvec_pack(pag_vec, msgb_put(msg, 23));
Andreas Eversberg6681bb82012-07-25 08:48:44 +02001346 RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)talloc_zero(tall_pcu_ctx, RlcMacDownlink_t);
Andreas Eversberg2b914642012-07-19 13:06:26 +02001347 LOGP(DRLCMAC, LOGL_DEBUG, "+++++++++++++++++++++++++ TX : Packet Paging Request +++++++++++++++++++++++++\n");
1348 decode_gsm_rlcmac_downlink(pag_vec, mac_control_block);
1349 LOGPC(DCSN1, LOGL_NOTICE, "\n");
1350 LOGP(DRLCMAC, LOGL_DEBUG, "------------------------- TX : Packet Paging Request -------------------------\n");
1351 bitvec_free(pag_vec);
Andreas Eversberg6681bb82012-07-25 08:48:44 +02001352 talloc_free(mac_control_block);
Andreas Eversberg2b914642012-07-19 13:06:26 +02001353
1354 return msg;
1355}
1356
Ivan Kluchnikov5310d452012-04-17 22:00:31 +04001357// GSM 04.08 9.1.18 Immediate assignment
Andreas Eversberge6228b32012-07-03 13:36:03 +02001358int write_immediate_assignment(bitvec * dest, uint8_t downlink, uint8_t ra,
Andreas Eversberg07e97cf2012-08-07 16:00:56 +02001359 uint32_t ref_fn, uint8_t ta, uint16_t arfcn, uint8_t ts, uint8_t tsc,
Andreas Eversberge6228b32012-07-03 13:36:03 +02001360 uint8_t tfi, uint8_t usf, uint32_t tlli,
Andreas Eversbergaafcbbb2012-09-27 09:20:45 +02001361 uint8_t polling, uint32_t fn, uint8_t single_block, uint8_t alpha,
Andreas Eversbergafdd9e12012-10-07 17:08:55 +02001362 uint8_t gamma, int8_t ta_idx)
Ivan Kluchnikov5310d452012-04-17 22:00:31 +04001363{
1364 unsigned wp = 0;
Andreas Eversberg7b045012012-07-05 07:38:49 +02001365 uint8_t plen;
Ivan Kluchnikov5310d452012-04-17 22:00:31 +04001366
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +04001367 bitvec_write_field(dest, wp,0x0,4); // Skip Indicator
1368 bitvec_write_field(dest, wp,0x6,4); // Protocol Discriminator
1369 bitvec_write_field(dest, wp,0x3F,8); // Immediate Assignment Message Type
Ivan Kluchnikov5310d452012-04-17 22:00:31 +04001370
1371 // 10.5.2.25b Dedicated mode or TBF
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +04001372 bitvec_write_field(dest, wp,0x0,1); // spare
1373 bitvec_write_field(dest, wp,0x0,1); // TMA : Two-message assignment: No meaning
1374 bitvec_write_field(dest, wp,downlink,1); // Downlink : Downlink assignment to mobile in packet idle mode
1375 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 +04001376
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +04001377 bitvec_write_field(dest, wp,0x0,4); // Page Mode
Ivan Kluchnikov5310d452012-04-17 22:00:31 +04001378
1379 // GSM 04.08 10.5.2.25a Packet Channel Description
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +04001380 bitvec_write_field(dest, wp,0x1,5); // Channel type
Andreas Eversberg0aed6542012-06-23 10:33:16 +02001381 bitvec_write_field(dest, wp,ts,3); // TN
1382 bitvec_write_field(dest, wp,tsc,3); // TSC
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +04001383 bitvec_write_field(dest, wp,0x0,3); // non-hopping RF channel configuraion
Andreas Eversberg0aed6542012-06-23 10:33:16 +02001384 bitvec_write_field(dest, wp,arfcn,10); // ARFCN
Ivan Kluchnikov5310d452012-04-17 22:00:31 +04001385
1386 //10.5.2.30 Request Reference
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +04001387 bitvec_write_field(dest, wp,ra,8); // RA
Andreas Eversberg07e97cf2012-08-07 16:00:56 +02001388 bitvec_write_field(dest, wp,(ref_fn / (26 * 51)) % 32,5); // T1'
1389 bitvec_write_field(dest, wp,ref_fn % 51,6); // T3
1390 bitvec_write_field(dest, wp,ref_fn % 26,5); // T2
Ivan Kluchnikov5310d452012-04-17 22:00:31 +04001391
1392 // 10.5.2.40 Timing Advance
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +04001393 bitvec_write_field(dest, wp,0x0,2); // spare
1394 bitvec_write_field(dest, wp,ta,6); // Timing Advance value
Ivan Kluchnikov5310d452012-04-17 22:00:31 +04001395
1396 // No mobile allocation in non-hopping systems.
1397 // A zero-length LV. Just write L=0.
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +04001398 bitvec_write_field(dest, wp,0,8);
Ivan Kluchnikov5310d452012-04-17 22:00:31 +04001399
Andreas Eversberg7b045012012-07-05 07:38:49 +02001400 if ((wp % 8)) {
1401 LOGP(DRLCMACUL, LOGL_ERROR, "Length of IMM.ASS without rest "
1402 "octets is not multiple of 8 bits, PLEASE FIX!\n");
1403 exit (0);
1404 }
1405 plen = wp / 8;
1406
Ivan Kluchnikov5310d452012-04-17 22:00:31 +04001407 if (downlink)
1408 {
1409 // GSM 04.08 10.5.2.16 IA Rest Octets
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +04001410 bitvec_write_field(dest, wp, 3, 2); // "HH"
1411 bitvec_write_field(dest, wp, 1, 2); // "01" Packet Downlink Assignment
1412 bitvec_write_field(dest, wp,tlli,32); // TLLI
1413 bitvec_write_field(dest, wp,0x1,1); // switch TFI : on
1414 bitvec_write_field(dest, wp,tfi,5); // TFI
1415 bitvec_write_field(dest, wp,0x0,1); // RLC acknowledged mode
Andreas Eversbergaafcbbb2012-09-27 09:20:45 +02001416 if (alpha) {
1417 bitvec_write_field(dest, wp,0x1,1); // ALPHA = present
1418 bitvec_write_field(dest, wp,alpha,4); // ALPHA
1419 } else {
1420 bitvec_write_field(dest, wp,0x0,1); // ALPHA = not present
1421 }
1422 bitvec_write_field(dest, wp,gamma,5); // GAMMA power control parameter
Andreas Eversberge6228b32012-07-03 13:36:03 +02001423 bitvec_write_field(dest, wp,polling,1); // Polling Bit
1424 bitvec_write_field(dest, wp,!polling,1); // TA_VALID ???
Andreas Eversbergafdd9e12012-10-07 17:08:55 +02001425 if (ta_idx < 0) {
1426 bitvec_write_field(dest, wp,0x0,1); // switch TIMING_ADVANCE_INDEX = off
1427 } else {
1428 bitvec_write_field(dest, wp,0x1,1); // switch TIMING_ADVANCE_INDEX = on
1429 bitvec_write_field(dest, wp,ta_idx,4); // TIMING_ADVANCE_INDEX
1430 }
Andreas Eversberge6228b32012-07-03 13:36:03 +02001431 if (polling) {
1432 bitvec_write_field(dest, wp,0x1,1); // TBF Starting TIME present
Andreas Eversberg07e97cf2012-08-07 16:00:56 +02001433 bitvec_write_field(dest, wp,(fn / (26 * 51)) % 32,5); // T1'
1434 bitvec_write_field(dest, wp,fn % 51,6); // T3
1435 bitvec_write_field(dest, wp,fn % 26,5); // T2
Andreas Eversberge6228b32012-07-03 13:36:03 +02001436 } else {
1437 bitvec_write_field(dest, wp,0x0,1); // TBF Starting TIME present
1438 }
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +04001439 bitvec_write_field(dest, wp,0x0,1); // P0 not present
Andreas Eversberge6228b32012-07-03 13:36:03 +02001440// bitvec_write_field(dest, wp,0x1,1); // P0 not present
1441// bitvec_write_field(dest, wp,0xb,4);
Ivan Kluchnikov5310d452012-04-17 22:00:31 +04001442 }
1443 else
1444 {
Andreas Eversbergdfa563c2012-07-06 08:13:59 +02001445 struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
Ivan Kluchnikov5310d452012-04-17 22:00:31 +04001446 // GMS 04.08 10.5.2.37b 10.5.2.16
Ivan Kluchnikov835f91e2012-04-30 18:00:36 +04001447 bitvec_write_field(dest, wp, 3, 2); // "HH"
1448 bitvec_write_field(dest, wp, 0, 2); // "0" Packet Uplink Assignment
Andreas Eversberg07e97cf2012-08-07 16:00:56 +02001449 if (single_block) {
1450 bitvec_write_field(dest, wp, 0, 1); // Block Allocation : Single Block Allocation
Andreas Eversbergaafcbbb2012-09-27 09:20:45 +02001451 if (alpha) {
1452 bitvec_write_field(dest, wp,0x1,1); // ALPHA = present
1453 bitvec_write_field(dest, wp,alpha,4); // ALPHA = present
1454 } else
1455 bitvec_write_field(dest, wp,0x0,1); // ALPHA = not present
1456 bitvec_write_field(dest, wp,gamma,5); // GAMMA power control parameter
Andreas Eversbergafdd9e12012-10-07 17:08:55 +02001457 if (ta_idx < 0) {
1458 bitvec_write_field(dest, wp,0x0,1); // switch TIMING_ADVANCE_INDEX = off
1459 } else {
1460 bitvec_write_field(dest, wp,0x1,1); // switch TIMING_ADVANCE_INDEX = on
1461 bitvec_write_field(dest, wp,ta_idx,4); // TIMING_ADVANCE_INDEX
1462 }
Andreas Eversberg07e97cf2012-08-07 16:00:56 +02001463 bitvec_write_field(dest, wp, 1, 1); // TBF_STARTING_TIME_FLAG
1464 bitvec_write_field(dest, wp,(fn / (26 * 51)) % 32,5); // T1'
1465 bitvec_write_field(dest, wp,fn % 51,6); // T3
1466 bitvec_write_field(dest, wp,fn % 26,5); // T2
1467 } else {
1468 bitvec_write_field(dest, wp, 1, 1); // Block Allocation : Not Single Block Allocation
1469 bitvec_write_field(dest, wp, tfi, 5); // TFI_ASSIGNMENT Temporary Flow Identity
1470 bitvec_write_field(dest, wp, 0, 1); // POLLING
1471 bitvec_write_field(dest, wp, 0, 1); // ALLOCATION_TYPE: dynamic
1472 bitvec_write_field(dest, wp, usf, 3); // USF
1473 bitvec_write_field(dest, wp, 0, 1); // USF_GRANULARITY
1474 bitvec_write_field(dest, wp, 0, 1); // "0" power control: Not Present
Andreas Eversberg499ff412012-10-03 14:21:36 +02001475 bitvec_write_field(dest, wp, bts->initial_cs_ul-1, 2); // CHANNEL_CODING_COMMAND
Andreas Eversberg07e97cf2012-08-07 16:00:56 +02001476 bitvec_write_field(dest, wp, 1, 1); // TLLI_BLOCK_CHANNEL_CODING
Andreas Eversbergaafcbbb2012-09-27 09:20:45 +02001477 if (alpha) {
1478 bitvec_write_field(dest, wp,0x1,1); // ALPHA = present
1479 bitvec_write_field(dest, wp,alpha,4); // ALPHA
1480 } else
1481 bitvec_write_field(dest, wp,0x0,1); // ALPHA = not present
1482 bitvec_write_field(dest, wp,gamma,5); // GAMMA power control parameter
Andreas Eversbergafdd9e12012-10-07 17:08:55 +02001483 /* note: there is no choise for TAI and no starting time */
1484 bitvec_write_field(dest, wp, 0, 1); // switch TIMING_ADVANCE_INDEX = off
Andreas Eversberg07e97cf2012-08-07 16:00:56 +02001485 bitvec_write_field(dest, wp, 0, 1); // TBF_STARTING_TIME_FLAG
1486 }
Ivan Kluchnikov5310d452012-04-17 22:00:31 +04001487 }
1488
Andreas Eversberg7b045012012-07-05 07:38:49 +02001489 return plen;
Ivan Kluchnikov5310d452012-04-17 22:00:31 +04001490}
1491
Andreas Eversberge6228b32012-07-03 13:36:03 +02001492/* generate uplink assignment */
1493void write_packet_uplink_assignment(bitvec * dest, uint8_t old_tfi,
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001494 uint8_t old_downlink, uint32_t tlli, uint8_t use_tlli,
Andreas Eversbergaafcbbb2012-09-27 09:20:45 +02001495 struct gprs_rlcmac_tbf *tbf, uint8_t poll, uint8_t alpha,
Andreas Eversbergafdd9e12012-10-07 17:08:55 +02001496 uint8_t gamma, int8_t ta_idx)
Ivan Kluchnikovc7e7f682012-06-29 22:53:15 +04001497{
Andreas Eversberge6228b32012-07-03 13:36:03 +02001498 // TODO We should use our implementation of encode RLC/MAC Control messages.
Andreas Eversbergdfa563c2012-07-06 08:13:59 +02001499 struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
Ivan Kluchnikovc7e7f682012-06-29 22:53:15 +04001500 unsigned wp = 0;
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001501 uint8_t ts;
Ivan Kluchnikovc7e7f682012-06-29 22:53:15 +04001502
Andreas Eversberge6228b32012-07-03 13:36:03 +02001503 bitvec_write_field(dest, wp,0x1,2); // Payload Type
1504 bitvec_write_field(dest, wp,0x0,2); // Uplink block with TDMA framenumber (N+13)
1505 bitvec_write_field(dest, wp,poll,1); // Suppl/Polling Bit
1506 bitvec_write_field(dest, wp,0x0,3); // Uplink state flag
1507 bitvec_write_field(dest, wp,0xa,6); // MESSAGE TYPE
Ivan Kluchnikovc7e7f682012-06-29 22:53:15 +04001508
Andreas Eversberge6228b32012-07-03 13:36:03 +02001509 bitvec_write_field(dest, wp,0x0,2); // Page Mode
Ivan Kluchnikovc7e7f682012-06-29 22:53:15 +04001510
Andreas Eversberge6228b32012-07-03 13:36:03 +02001511 bitvec_write_field(dest, wp,0x0,1); // switch PERSIST_LEVEL: off
1512 if (use_tlli) {
1513 bitvec_write_field(dest, wp,0x2,2); // switch TLLI : on
1514 bitvec_write_field(dest, wp,tlli,32); // TLLI
1515 } else {
1516 bitvec_write_field(dest, wp,0x0,1); // switch TFI : on
1517 bitvec_write_field(dest, wp,old_downlink,1); // 0=UPLINK TFI, 1=DL TFI
1518 bitvec_write_field(dest, wp,old_tfi,5); // TFI
Ivan Kluchnikovc7e7f682012-06-29 22:53:15 +04001519 }
Ivan Kluchnikovb2b81002012-06-04 21:57:02 +04001520
Andreas Eversberge6228b32012-07-03 13:36:03 +02001521 bitvec_write_field(dest, wp,0x0,1); // Message escape
Andreas Eversberg499ff412012-10-03 14:21:36 +02001522 bitvec_write_field(dest, wp,bts->initial_cs_ul-1, 2); // CHANNEL_CODING_COMMAND
Andreas Eversbergdfa563c2012-07-06 08:13:59 +02001523 bitvec_write_field(dest, wp,0x1,1); // TLLI_BLOCK_CHANNEL_CODING
Andreas Eversberge6228b32012-07-03 13:36:03 +02001524 bitvec_write_field(dest, wp,0x1,1); // switch TIMING_ADVANCE_VALUE = on
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001525 bitvec_write_field(dest, wp,tbf->ta,6); // TIMING_ADVANCE_VALUE
Andreas Eversbergafdd9e12012-10-07 17:08:55 +02001526 if (ta_idx < 0) {
1527 bitvec_write_field(dest, wp,0x0,1); // switch TIMING_ADVANCE_INDEX = off
1528 } else {
1529 bitvec_write_field(dest, wp,0x1,1); // switch TIMING_ADVANCE_INDEX = on
1530 bitvec_write_field(dest, wp,ta_idx,4); // TIMING_ADVANCE_INDEX
1531 }
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04001532
Andreas Eversberge6228b32012-07-03 13:36:03 +02001533#if 1
1534 bitvec_write_field(dest, wp,0x1,1); // Frequency Parameters information elements = present
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001535 bitvec_write_field(dest, wp,tbf->tsc,3); // Training Sequence Code (TSC)
Andreas Eversberge6228b32012-07-03 13:36:03 +02001536 bitvec_write_field(dest, wp,0x0,2); // ARFCN = present
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001537 bitvec_write_field(dest, wp,tbf->arfcn,10); // ARFCN
Andreas Eversberge6228b32012-07-03 13:36:03 +02001538#else
1539 bitvec_write_field(dest, wp,0x0,1); // Frequency Parameters = off
Andreas Eversberg5dac2f02012-06-27 15:52:04 +02001540#endif
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04001541
Andreas Eversberge6228b32012-07-03 13:36:03 +02001542 bitvec_write_field(dest, wp,0x1,2); // Dynamic Allocation
Ivan Kluchnikove3594232012-06-07 01:12:29 +04001543
Andreas Eversberge6228b32012-07-03 13:36:03 +02001544 bitvec_write_field(dest, wp,0x0,1); // Extended Dynamic Allocation = off
1545 bitvec_write_field(dest, wp,0x0,1); // P0 = off
Ivan Kluchnikove3594232012-06-07 01:12:29 +04001546
Andreas Eversberge6228b32012-07-03 13:36:03 +02001547 bitvec_write_field(dest, wp,0x0,1); // USF_GRANULARITY
1548 bitvec_write_field(dest, wp,0x1,1); // switch TFI : on
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001549 bitvec_write_field(dest, wp,tbf->tfi,5);// TFI
Andreas Eversberge6228b32012-07-03 13:36:03 +02001550
1551 bitvec_write_field(dest, wp,0x0,1); //
1552 bitvec_write_field(dest, wp,0x0,1); // TBF Starting Time = off
Andreas Eversbergaafcbbb2012-09-27 09:20:45 +02001553 if (alpha || gamma) {
1554 bitvec_write_field(dest, wp,0x1,1); // Timeslot Allocation with Power Control
1555 bitvec_write_field(dest, wp,alpha,4); // ALPHA
1556 } else
1557 bitvec_write_field(dest, wp,0x0,1); // Timeslot Allocation
Andreas Eversberge6228b32012-07-03 13:36:03 +02001558
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001559 for (ts = 0; ts < 8; ts++) {
1560 if (tbf->pdch[ts]) {
Andreas Eversberge6228b32012-07-03 13:36:03 +02001561 bitvec_write_field(dest, wp,0x1,1); // USF_TN(i): on
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001562 bitvec_write_field(dest, wp,tbf->dir.ul.usf[ts],3); // USF_TN(i)
Andreas Eversbergaafcbbb2012-09-27 09:20:45 +02001563 if (alpha || gamma)
1564 bitvec_write_field(dest, wp,gamma,5); // GAMMA power control parameter
Andreas Eversberge6228b32012-07-03 13:36:03 +02001565 } else
1566 bitvec_write_field(dest, wp,0x0,1); // USF_TN(i): off
Ivan Kluchnikove3594232012-06-07 01:12:29 +04001567 }
Andreas Eversberge6228b32012-07-03 13:36:03 +02001568// bitvec_write_field(dest, wp,0x0,1); // Measurement Mapping struct not present
Ivan Kluchnikovc7e7f682012-06-29 22:53:15 +04001569}
1570
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001571
Andreas Eversberge6228b32012-07-03 13:36:03 +02001572/* generate downlink assignment */
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001573void write_packet_downlink_assignment(RlcMacDownlink_t * block, uint8_t old_tfi,
Andreas Eversbergaafcbbb2012-09-27 09:20:45 +02001574 uint8_t old_downlink, struct gprs_rlcmac_tbf *tbf, uint8_t poll,
Andreas Eversbergafdd9e12012-10-07 17:08:55 +02001575 uint8_t alpha, uint8_t gamma, int8_t ta_idx, uint8_t ta_ts)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04001576{
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001577 // Packet downlink assignment TS 44.060 11.2.7
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04001578
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001579 uint8_t tn;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04001580
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001581 block->PAYLOAD_TYPE = 0x1; // RLC/MAC control block that does not include the optional octets of the RLC/MAC control header
1582 block->RRBP = 0x0; // N+13
1583 block->SP = poll; // RRBP field is valid
1584 block->USF = 0x0; // Uplink state flag
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04001585
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001586 block->u.Packet_Downlink_Assignment.MESSAGE_TYPE = 0x2; // Packet Downlink Assignment
1587 block->u.Packet_Downlink_Assignment.PAGE_MODE = 0x0; // Normal Paging
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04001588
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001589 block->u.Packet_Downlink_Assignment.Exist_PERSISTENCE_LEVEL = 0x0; // PERSISTENCE_LEVEL: off
Andreas Eversberge6228b32012-07-03 13:36:03 +02001590
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001591 block->u.Packet_Downlink_Assignment.ID.UnionType = 0x0; // TFI = on
1592 block->u.Packet_Downlink_Assignment.ID.u.Global_TFI.UnionType = old_downlink; // 0=UPLINK TFI, 1=DL TFI
1593 block->u.Packet_Downlink_Assignment.ID.u.Global_TFI.u.UPLINK_TFI = old_tfi; // TFI
Andreas Eversberge6228b32012-07-03 13:36:03 +02001594
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001595 block->u.Packet_Downlink_Assignment.MAC_MODE = 0x0; // Dynamic Allocation
1596 block->u.Packet_Downlink_Assignment.RLC_MODE = 0x0; // RLC acknowledged mode
1597 block->u.Packet_Downlink_Assignment.CONTROL_ACK = old_downlink; // NW establishes no new DL TBF for the MS with running timer T3192
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001598 block->u.Packet_Downlink_Assignment.TIMESLOT_ALLOCATION = 0; // timeslot(s)
1599 for (tn = 0; tn < 8; tn++) {
1600 if (tbf->pdch[tn])
1601 block->u.Packet_Downlink_Assignment.TIMESLOT_ALLOCATION |= 0x80 >> tn; // timeslot(s)
1602 }
Andreas Eversberge6228b32012-07-03 13:36:03 +02001603
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001604 block->u.Packet_Downlink_Assignment.Packet_Timing_Advance.Exist_TIMING_ADVANCE_VALUE = 0x1; // TIMING_ADVANCE_VALUE = on
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001605 block->u.Packet_Downlink_Assignment.Packet_Timing_Advance.TIMING_ADVANCE_VALUE = tbf->ta; // TIMING_ADVANCE_VALUE
Andreas Eversbergafdd9e12012-10-07 17:08:55 +02001606 if (ta_idx < 0) {
1607 block->u.Packet_Downlink_Assignment.Packet_Timing_Advance.Exist_IndexAndtimeSlot = 0x0; // TIMING_ADVANCE_INDEX = off
1608 } else {
1609 block->u.Packet_Downlink_Assignment.Packet_Timing_Advance.Exist_IndexAndtimeSlot = 0x1; // TIMING_ADVANCE_INDEX = on
1610 block->u.Packet_Downlink_Assignment.Packet_Timing_Advance.TIMING_ADVANCE_INDEX = ta_idx; // TIMING_ADVANCE_INDEX
1611 block->u.Packet_Downlink_Assignment.Packet_Timing_Advance.TIMING_ADVANCE_TIMESLOT_NUMBER = ta_ts; // TIMING_ADVANCE_TS
1612 }
Andreas Eversberge6228b32012-07-03 13:36:03 +02001613
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001614 block->u.Packet_Downlink_Assignment.Exist_P0_and_BTS_PWR_CTRL_MODE = 0x0; // POWER CONTROL = off
Andreas Eversberge6228b32012-07-03 13:36:03 +02001615
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001616 block->u.Packet_Downlink_Assignment.Exist_Frequency_Parameters = 0x1; // Frequency Parameters = on
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001617 block->u.Packet_Downlink_Assignment.Frequency_Parameters.TSC = tbf->tsc; // Training Sequence Code (TSC)
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001618 block->u.Packet_Downlink_Assignment.Frequency_Parameters.UnionType = 0x0; // ARFCN = on
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001619 block->u.Packet_Downlink_Assignment.Frequency_Parameters.u.ARFCN = tbf->arfcn; // ARFCN
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001620
1621 block->u.Packet_Downlink_Assignment.Exist_DOWNLINK_TFI_ASSIGNMENT = 0x1; // DOWNLINK TFI ASSIGNMENT = on
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001622 block->u.Packet_Downlink_Assignment.DOWNLINK_TFI_ASSIGNMENT = tbf->tfi; // TFI
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001623
1624 block->u.Packet_Downlink_Assignment.Exist_Power_Control_Parameters = 0x1; // Power Control Parameters = on
Andreas Eversbergaafcbbb2012-09-27 09:20:45 +02001625 block->u.Packet_Downlink_Assignment.Power_Control_Parameters.ALPHA = alpha; // ALPHA
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001626
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001627 for (tn = 0; tn < 8; tn++)
Ivan Kluchnikov34460b82012-06-27 18:41:04 +04001628 {
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001629 if (tbf->pdch[tn])
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001630 {
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001631 block->u.Packet_Downlink_Assignment.Power_Control_Parameters.Slot[tn].Exist = 0x1; // Slot[i] = on
Andreas Eversbergaafcbbb2012-09-27 09:20:45 +02001632 block->u.Packet_Downlink_Assignment.Power_Control_Parameters.Slot[tn].GAMMA_TN = gamma; // GAMMA_TN
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001633 }
1634 else
1635 {
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001636 block->u.Packet_Downlink_Assignment.Power_Control_Parameters.Slot[tn].Exist = 0x0; // Slot[i] = off
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001637 }
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04001638 }
Ivan Kluchnikov34460b82012-06-27 18:41:04 +04001639
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001640 block->u.Packet_Downlink_Assignment.Exist_TBF_Starting_Time = 0x0; // TBF Starting TIME = off
1641 block->u.Packet_Downlink_Assignment.Exist_Measurement_Mapping = 0x0; // Measurement_Mapping = off
1642 block->u.Packet_Downlink_Assignment.Exist_AdditionsR99 = 0x0; // AdditionsR99 = off
Andreas Eversberge6228b32012-07-03 13:36:03 +02001643}
1644
Andreas Eversberg8c3680d2012-10-08 12:30:56 +02001645/* generate paging request */
1646int write_paging_request(bitvec * dest, uint8_t *ptmsi, uint16_t ptmsi_len)
1647{
1648 unsigned wp = 0;
1649 int plen;
1650
1651 bitvec_write_field(dest, wp,0x0,4); // Skip Indicator
1652 bitvec_write_field(dest, wp,0x6,4); // Protocol Discriminator
1653 bitvec_write_field(dest, wp,0x21,8); // Paging Request Message Type
1654
1655 bitvec_write_field(dest, wp,0x0,4); // Page Mode
1656 bitvec_write_field(dest, wp,0x0,4); // Channel Needed
1657
1658 // Mobile Identity
1659 bitvec_write_field(dest, wp,ptmsi_len+1,8); // Mobile Identity length
1660 bitvec_write_field(dest, wp,0xf,4); // unused
1661 bitvec_write_field(dest, wp,0x4,4); // PTMSI type
1662 for (int i = 0; i < ptmsi_len; i++)
1663 {
1664 bitvec_write_field(dest, wp,ptmsi[i],8); // PTMSI
1665 }
1666 if ((wp % 8)) {
1667 LOGP(DRLCMACUL, LOGL_ERROR, "Length of PAG.REQ without rest "
1668 "octets is not multiple of 8 bits, PLEASE FIX!\n");
1669 exit (0);
1670 }
1671 plen = wp / 8;
1672 bitvec_write_field(dest, wp,0x0,1); // "L" NLN(PCH) = off
1673 bitvec_write_field(dest, wp,0x0,1); // "L" Priority1 = off
1674 bitvec_write_field(dest, wp,0x1,1); // "L" Priority2 = off
1675 bitvec_write_field(dest, wp,0x0,1); // "L" Group Call information = off
1676 bitvec_write_field(dest, wp,0x0,1); // "H" Packet Page Indication 1 = packet paging procedure
1677 bitvec_write_field(dest, wp,0x1,1); // "H" Packet Page Indication 2 = packet paging procedure
1678
1679 return plen;
1680}
1681
Andreas Eversberge6228b32012-07-03 13:36:03 +02001682/* generate uplink ack */
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001683void write_packet_uplink_ack(RlcMacDownlink_t * block, struct gprs_rlcmac_tbf *tbf,
Andreas Eversberge6228b32012-07-03 13:36:03 +02001684 uint8_t final)
1685{
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001686 // Packet Uplink Ack/Nack TS 44.060 11.2.28
1687
Andreas Eversberge6228b32012-07-03 13:36:03 +02001688 char show_v_n[65];
1689
Andreas Eversbergab18bab2012-07-15 16:34:07 +02001690 struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001691 uint8_t rbb = 0;
Andreas Eversberge6228b32012-07-03 13:36:03 +02001692 uint16_t i, bbn;
1693 uint16_t mod_sns_half = (tbf->sns >> 1) - 1;
1694 char bit;
1695
1696 LOGP(DRLCMACUL, LOGL_DEBUG, "Sending Ack/Nack for TBF=%d "
1697 "(final=%d)\n", tbf->tfi, final);
1698
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001699 block->PAYLOAD_TYPE = 0x1; // RLC/MAC control block that does not include the optional octets of the RLC/MAC control header
1700 block->RRBP = 0x0; // N+13
1701 block->SP = final; // RRBP field is valid, if it is final ack
1702 block->USF = 0x0; // Uplink state flag
Andreas Eversberge6228b32012-07-03 13:36:03 +02001703
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001704 block->u.Packet_Uplink_Ack_Nack.MESSAGE_TYPE = 0x9; // Packet Downlink Assignment
1705 block->u.Packet_Uplink_Ack_Nack.PAGE_MODE = 0x0; // Normal Paging
1706 block->u.Packet_Uplink_Ack_Nack.UPLINK_TFI = tbf->tfi; // Uplink TFI
Andreas Eversberge6228b32012-07-03 13:36:03 +02001707
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001708 block->u.Packet_Uplink_Ack_Nack.UnionType = 0x0; // PU_AckNack_GPRS = on
Andreas Eversberg499ff412012-10-03 14:21:36 +02001709 block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.CHANNEL_CODING_COMMAND = bts->initial_cs_ul - 1; // CS1
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001710 block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.Ack_Nack_Description.FINAL_ACK_INDICATION = final; // FINAL ACK INDICATION
1711 block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.Ack_Nack_Description.STARTING_SEQUENCE_NUMBER = tbf->dir.ul.v_r; // STARTING_SEQUENCE_NUMBER
Andreas Eversberge6228b32012-07-03 13:36:03 +02001712 // RECEIVE_BLOCK_BITMAP
1713 for (i = 0, bbn = (tbf->dir.ul.v_r - 64) & mod_sns_half; i < 64;
1714 i++, bbn = (bbn + 1) & mod_sns_half) {
1715 bit = tbf->dir.ul.v_n[bbn];
1716 if (bit == 0)
1717 bit = ' ';
1718 show_v_n[i] = bit;
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001719 if (bit == 'R')
1720 rbb = (rbb << 1)|1;
1721 else
1722 rbb = (rbb << 1);
1723 if((i%8) == 7)
1724 {
1725 block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.Ack_Nack_Description.RECEIVED_BLOCK_BITMAP[i/8] = rbb;
1726 rbb = 0;
1727 }
Ivan Kluchnikove3594232012-06-07 01:12:29 +04001728 }
Andreas Eversberge6228b32012-07-03 13:36:03 +02001729 show_v_n[64] = '\0';
1730 LOGP(DRLCMACUL, LOGL_DEBUG, "- V(N): \"%s\" R=Received "
1731 "N=Not-Received\n", show_v_n);
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001732
1733 block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.UnionType = 0x0; // Fixed Allocation Dummy = on
Ivan Kluchnikov34460b82012-06-27 18:41:04 +04001734 block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.u.FixedAllocationDummy = 0x0; // Fixed Allocation Dummy
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001735 block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.Exist_AdditionsR99 = 0x0; // AdditionsR99 = off
Ivan Kluchnikov34460b82012-06-27 18:41:04 +04001736
1737 block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.Common_Uplink_Ack_Nack_Data.Exist_CONTENTION_RESOLUTION_TLLI = 0x1;
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001738 block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.Common_Uplink_Ack_Nack_Data.CONTENTION_RESOLUTION_TLLI = tbf->tlli;
Ivan Kluchnikov34460b82012-06-27 18:41:04 +04001739 block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.Common_Uplink_Ack_Nack_Data.Exist_Packet_Timing_Advance = 0x0;
1740 block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.Common_Uplink_Ack_Nack_Data.Exist_Extension_Bits = 0x0;
1741 block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.Common_Uplink_Ack_Nack_Data.Exist_Power_Control_Parameters = 0x0;
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04001742}
1743
Andreas Eversberg2b914642012-07-19 13:06:26 +02001744unsigned write_packet_paging_request(bitvec * dest)
1745{
1746 unsigned wp = 0;
1747
1748 bitvec_write_field(dest, wp,0x1,2); // Payload Type
1749 bitvec_write_field(dest, wp,0x0,3); // No polling
1750 bitvec_write_field(dest, wp,0x0,3); // Uplink state flag
1751 bitvec_write_field(dest, wp,0x22,6); // MESSAGE TYPE
1752
Andreas Eversberg3b7461c2012-07-20 11:19:59 +02001753 bitvec_write_field(dest, wp,0x0,2); // Page Mode
1754
Andreas Eversberg2b914642012-07-19 13:06:26 +02001755 bitvec_write_field(dest, wp,0x0,1); // No PERSISTENCE_LEVEL
1756 bitvec_write_field(dest, wp,0x0,1); // No NLN
1757
1758 return wp;
1759}
1760
1761unsigned write_repeated_page_info(bitvec * dest, unsigned& wp, uint8_t len,
1762 uint8_t *identity, uint8_t chan_needed)
1763{
Andreas Eversberg3b7461c2012-07-20 11:19:59 +02001764 bitvec_write_field(dest, wp,0x1,1); // Repeated Page info exists
1765
Andreas Eversberg2b914642012-07-19 13:06:26 +02001766 bitvec_write_field(dest, wp,0x1,1); // RR connection paging
1767
1768 if ((identity[0] & 0x07) == 4) {
1769 bitvec_write_field(dest, wp,0x0,1); // TMSI
1770 identity++;
1771 len--;
1772 } else {
1773 bitvec_write_field(dest, wp,0x0,1); // MI
1774 bitvec_write_field(dest, wp,len,4); // MI len
1775 }
1776 while (len) {
1777 bitvec_write_field(dest, wp,*identity++,8); // MI data
1778 len--;
1779 }
1780 bitvec_write_field(dest, wp,chan_needed,2); // CHANNEL_NEEDED
1781 bitvec_write_field(dest, wp,0x0,1); // No eMLPP_PRIORITY
1782
1783 return wp;
1784}
1785
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04001786/* Send Uplink unit-data to SGSN. */
Andreas Eversberg3e372d52012-07-06 09:28:15 +02001787int gprs_rlcmac_tx_ul_ud(gprs_rlcmac_tbf *tbf)
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04001788{
Andreas Eversberg9a913462012-09-23 06:42:38 +02001789 uint8_t qos_profile[3];
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04001790 struct msgb *llc_pdu;
Andreas Eversberg5dac2f02012-06-27 15:52:04 +02001791 unsigned msg_len = NS_HDR_LEN + BSSGP_HDR_LEN + tbf->llc_index;
Holger Hans Peter Freyther90692f92013-07-13 12:51:16 +02001792 struct bssgp_bvc_ctx *bctx = gprs_bssgp_pcu_current_bctx();
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04001793
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001794 LOGP(DBSSGP, LOGL_INFO, "LLC [PCU -> SGSN] TFI: %u TLLI: 0x%08x len=%d\n", tbf->tfi, tbf->tlli, tbf->llc_index);
Andreas Eversberg3e372d52012-07-06 09:28:15 +02001795 if (!bctx) {
1796 LOGP(DBSSGP, LOGL_ERROR, "No bctx\n");
1797 return -EIO;
1798 }
Ivan Kluchnikovc320d862012-03-18 15:04:48 +04001799
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04001800 llc_pdu = msgb_alloc_headroom(msg_len, msg_len,"llc_pdu");
Andreas Eversberg9a913462012-09-23 06:42:38 +02001801 uint8_t *buf = msgb_push(llc_pdu, TL16V_GROSS_LEN(sizeof(uint8_t)*tbf->llc_index));
1802 tl16v_put(buf, BSSGP_IE_LLC_PDU, sizeof(uint8_t)*tbf->llc_index, tbf->llc_frame);
1803 qos_profile[0] = QOS_PROFILE >> 16;
1804 qos_profile[1] = QOS_PROFILE >> 8;
1805 qos_profile[2] = QOS_PROFILE;
1806 bssgp_tx_ul_ud(bctx, tbf->tlli, qos_profile, llc_pdu);
Ivan Kluchnikov8ee60512012-03-05 19:24:57 +04001807
Andreas Eversberg3e372d52012-07-06 09:28:15 +02001808 return 0;
Ivan Kluchnikovc7e7f682012-06-29 22:53:15 +04001809}
Andreas Eversberg8c3680d2012-10-08 12:30:56 +02001810
1811int gprs_rlcmac_paging_request(uint8_t *ptmsi, uint16_t ptmsi_len,
1812 const char *imsi)
1813{
1814 LOGP(DRLCMAC, LOGL_NOTICE, "TX: [PCU -> BTS] Paging Request (CCCH)\n");
1815 bitvec *paging_request = bitvec_alloc(23);
1816 bitvec_unhex(paging_request, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
1817 int plen = write_paging_request(paging_request, ptmsi, ptmsi_len);
1818 pcu_l1if_tx_pch(paging_request, plen, (char *)imsi);
1819 bitvec_free(paging_request);
1820
1821 return 0;
1822}
Andreas Eversberga004e6a2013-05-13 16:45:21 +02001823
1824
1825/*
1826 * timing advance memory
1827 */
1828
1829/* enable to debug timing advance memory */
1830//#define DEBUG_TA
1831
1832static LLIST_HEAD(gprs_rlcmac_ta_list);
1833static int gprs_rlcmac_ta_num = 0;
1834
1835struct gprs_rlcmac_ta {
1836 struct llist_head list;
1837 uint32_t tlli;
1838 uint8_t ta;
1839};
1840
1841/* remember timing advance of a given TLLI */
1842int remember_timing_advance(uint32_t tlli, uint8_t ta)
1843{
1844 struct gprs_rlcmac_ta *ta_entry;
1845
1846 /* check for existing entry */
1847 llist_for_each_entry(ta_entry, &gprs_rlcmac_ta_list, list) {
1848 if (ta_entry->tlli == tlli) {
1849#ifdef DEBUG_TA
1850 fprintf(stderr, "update %08x %d\n", tlli, ta);
1851#endif
1852 ta_entry->ta = ta;
1853 /* relink to end of list */
1854 llist_del(&ta_entry->list);
1855 llist_add_tail(&ta_entry->list, &gprs_rlcmac_ta_list);
1856 return 0;
1857 }
1858 }
1859
1860#ifdef DEBUG_TA
1861 fprintf(stderr, "remember %08x %d\n", tlli, ta);
1862#endif
1863 /* if list is full, remove oldest entry */
1864 if (gprs_rlcmac_ta_num == 30) {
1865 ta_entry = llist_entry(gprs_rlcmac_ta_list.next,
1866 struct gprs_rlcmac_ta, list);
1867 llist_del(&ta_entry->list);
1868 talloc_free(ta_entry);
1869 gprs_rlcmac_ta_num--;
1870 }
1871
1872 /* create new TA entry */
1873 ta_entry = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_ta);
1874 if (!ta_entry)
1875 return -ENOMEM;
1876
1877 ta_entry->tlli = tlli;
1878 ta_entry->ta = ta;
1879 llist_add_tail(&ta_entry->list, &gprs_rlcmac_ta_list);
1880 gprs_rlcmac_ta_num++;
1881
1882 return 0;
1883}
1884
1885int recall_timing_advance(uint32_t tlli)
1886{
1887 struct gprs_rlcmac_ta *ta_entry;
1888 uint8_t ta;
1889
1890 llist_for_each_entry(ta_entry, &gprs_rlcmac_ta_list, list) {
1891 if (ta_entry->tlli == tlli) {
1892 ta = ta_entry->ta;
1893#ifdef DEBUG_TA
1894 fprintf(stderr, "recall %08x %d\n", tlli, ta);
1895#endif
1896 return ta;
1897 }
1898 }
1899#ifdef DEBUG_TA
1900 fprintf(stderr, "no entry for %08x\n", tlli);
1901#endif
1902
1903 return -EINVAL;
1904}
1905
1906int flush_timing_advance(void)
1907{
1908 struct gprs_rlcmac_ta *ta_entry;
1909 int count = 0;
1910
1911 while (!llist_empty(&gprs_rlcmac_ta_list)) {
1912 ta_entry = llist_entry(gprs_rlcmac_ta_list.next,
1913 struct gprs_rlcmac_ta, list);
1914#ifdef DEBUG_TA
1915 fprintf(stderr, "flush entry %08x %d\n", ta_entry->tlli,
1916 ta_entry->ta);
1917#endif
1918 llist_del(&ta_entry->list);
1919 talloc_free(ta_entry);
1920 count++;
1921 }
1922 gprs_rlcmac_ta_num = 0;
1923
1924 return count;
1925}
1926