blob: bb2687171be17b62e3103be2dc787b960875e032 [file] [log] [blame]
Andreas Eversberg66690dd2012-06-27 15:44:31 +02001/* Data block transfer
2 *
3 * Copyright (C) 2012 Ivan Klyuchnikov
4 * Copyright (C) 2012 Andreas Eversberg <jolly@eversberg.eu>
5 *
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 <gprs_rlcmac.h>
Andreas Eversberge6228b32012-07-03 13:36:03 +020023#include <pcu_l1_if.h>
Holger Hans Peter Freyther67ed34e2013-10-17 17:01:54 +020024#include <bts.h>
Holger Hans Peter Freyther86921282013-08-24 21:26:42 +020025#include <tbf.h>
Andreas Eversberg66690dd2012-06-27 15:44:31 +020026
Andreas Eversberg6681bb82012-07-25 08:48:44 +020027extern void *tall_pcu_ctx;
Andreas Eversberg66690dd2012-06-27 15:44:31 +020028
Andreas Eversberg24131bf2012-07-21 11:09:58 +020029extern "C" {
30int bssgp_tx_llc_discarded(struct bssgp_bvc_ctx *bctx, uint32_t tlli,
31 uint8_t num_frames, uint32_t num_octets);
32}
33
Andreas Eversbergf54a89e2012-07-16 11:56:11 +020034/* After receiving these frames, we send ack/nack. */
35#define SEND_ACK_AFTER_FRAMES 20
36
37/* After sending these frames, we poll for ack/nack. */
Andreas Eversberg5f14bd92012-10-03 14:20:26 +020038#define POLL_ACK_AFTER_FRAMES 20
Andreas Eversberg66690dd2012-06-27 15:44:31 +020039
Andreas Eversberg802bb6e2012-08-06 11:15:05 +020040/* If acknowledgement to uplink/downlink assignmentshould be polled */
41#define POLLING_ASSIGNMENT_DL 1
42#define POLLING_ASSIGNMENT_UL 1
Andreas Eversberge6228b32012-07-03 13:36:03 +020043
Andreas Eversberg66690dd2012-06-27 15:44:31 +020044extern "C" {
45/* TS 04.60 10.2.2 */
Andreas Eversberge6228b32012-07-03 13:36:03 +020046struct rlc_ul_header {
Andreas Eversberg66690dd2012-06-27 15:44:31 +020047 uint8_t r:1,
48 si:1,
49 cv:4,
50 pt:2;
51 uint8_t ti:1,
52 tfi:5,
53 pi:1,
54 spare:1;
55 uint8_t e:1,
56 bsn:7;
57} __attribute__ ((packed));
58
Andreas Eversberge6228b32012-07-03 13:36:03 +020059struct rlc_dl_header {
60 uint8_t usf:3,
61 s_p:1,
62 rrbp:2,
63 pt:2;
64 uint8_t fbi:1,
65 tfi:5,
66 pr:2;
67 uint8_t e:1,
68 bsn:7;
69} __attribute__ ((packed));
70
Andreas Eversberg66690dd2012-06-27 15:44:31 +020071struct rlc_li_field {
72 uint8_t e:1,
73 m:1,
74 li:6;
75} __attribute__ ((packed));
76}
77
Holger Hans Peter Freyther344ff482013-10-17 12:01:04 +020078static void gprs_rlcmac_downlink_assignment(struct gprs_rlcmac_bts *bts,
79 gprs_rlcmac_tbf *tbf, uint8_t poll,
Holger Hans Peter Freyther52c911b2013-08-24 18:30:54 +020080 const char *imsi);
Andreas Eversberga9be1542012-09-27 09:23:24 +020081
Andreas Eversberg14db19e2012-08-06 15:03:03 +020082static int gprs_rlcmac_diag(struct gprs_rlcmac_tbf *tbf)
83{
Holger Hans Peter Freyther7380bab2013-10-16 18:09:19 +020084 return tbf->rlcmac_diag();
Andreas Eversberg14db19e2012-08-06 15:03:03 +020085}
86
Holger Hans Peter Freyther344ff482013-10-17 12:01:04 +020087int gprs_rlcmac_poll_timeout(struct gprs_rlcmac_bts *bts, struct gprs_rlcmac_tbf *tbf)
Andreas Eversberge6228b32012-07-03 13:36:03 +020088{
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +020089 LOGP(DRLCMAC, LOGL_NOTICE, "Poll timeout for %s TBF=%d\n",
90 (tbf->direction == GPRS_RLCMAC_UL_TBF) ? "UL" : "DL", tbf->tfi);
Andreas Eversberge6228b32012-07-03 13:36:03 +020091
92 tbf->poll_state = GPRS_RLCMAC_POLL_NONE;
93
94 if (tbf->ul_ack_state == GPRS_RLCMAC_UL_ACK_WAIT_ACK) {
Andreas Eversberg14db19e2012-08-06 15:03:03 +020095 if (!(tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_TO_UL_ACK))) {
96 LOGP(DRLCMAC, LOGL_NOTICE, "- Timeout for polling "
97 "PACKET CONTROL ACK for PACKET UPLINK ACK\n");
98 gprs_rlcmac_diag(tbf);
99 tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_TO_UL_ACK);
100 }
Andreas Eversberge6228b32012-07-03 13:36:03 +0200101 tbf->ul_ack_state = GPRS_RLCMAC_UL_ACK_NONE;
Andreas Eversbergb83e2a72012-10-07 15:26:00 +0200102 debug_diagram(tbf->diag, "timeout UL-ACK");
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200103 if (tbf->state_is(GPRS_RLCMAC_FINISHED)) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200104 tbf->dir.ul.n3103++;
Andreas Eversbergdfa563c2012-07-06 08:13:59 +0200105 if (tbf->dir.ul.n3103 == bts->n3103) {
Andreas Eversberg4b470ff2012-07-16 12:02:40 +0200106 LOGP(DRLCMAC, LOGL_NOTICE,
107 "- N3103 exceeded\n");
Andreas Eversbergb83e2a72012-10-07 15:26:00 +0200108 debug_diagram(tbf->diag, "N3103 exceeded");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200109 tbf_new_state(tbf, GPRS_RLCMAC_RELEASING);
Andreas Eversbergdfa563c2012-07-06 08:13:59 +0200110 tbf_timer_start(tbf, 3169, bts->t3169, 0);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200111 return 0;
112 }
113 /* reschedule UL ack */
114 tbf->ul_ack_state = GPRS_RLCMAC_UL_ACK_SEND_ACK;
115 }
116 } else
117 if (tbf->ul_ass_state == GPRS_RLCMAC_UL_ASS_WAIT_ACK) {
Andreas Eversberg14db19e2012-08-06 15:03:03 +0200118 if (!(tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_TO_UL_ASS))) {
119 LOGP(DRLCMAC, LOGL_NOTICE, "- Timeout for polling "
120 "PACKET CONTROL ACK for PACKET UPLINK "
121 "ASSIGNMENT.\n");
122 gprs_rlcmac_diag(tbf);
123 tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_TO_UL_ASS);
124 }
Andreas Eversberge6228b32012-07-03 13:36:03 +0200125 tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_NONE;
Andreas Eversbergb83e2a72012-10-07 15:26:00 +0200126 debug_diagram(tbf->diag, "timeout UL-ASS");
Andreas Eversberg802bb6e2012-08-06 11:15:05 +0200127 tbf->n3105++;
128 if (tbf->n3105 == bts->n3105) {
129 LOGP(DRLCMAC, LOGL_NOTICE, "- N3105 exceeded\n");
Andreas Eversbergb83e2a72012-10-07 15:26:00 +0200130 debug_diagram(tbf->diag, "N3105 exceeded");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200131 tbf_new_state(tbf, GPRS_RLCMAC_RELEASING);
Andreas Eversbergdfa563c2012-07-06 08:13:59 +0200132 tbf_timer_start(tbf, 3195, bts->t3195, 0);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200133 return 0;
134 }
Andreas Eversberg802bb6e2012-08-06 11:15:05 +0200135 /* reschedule UL assignment */
136 tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200137 } else
138 if (tbf->dl_ass_state == GPRS_RLCMAC_DL_ASS_WAIT_ACK) {
Andreas Eversberg14db19e2012-08-06 15:03:03 +0200139 if (!(tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_TO_DL_ASS))) {
140 LOGP(DRLCMAC, LOGL_NOTICE, "- Timeout for polling "
141 "PACKET CONTROL ACK for PACKET DOWNLINK "
142 "ASSIGNMENT.\n");
143 gprs_rlcmac_diag(tbf);
144 tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_TO_DL_ASS);
145 }
Andreas Eversberge6228b32012-07-03 13:36:03 +0200146 tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE;
Andreas Eversbergb83e2a72012-10-07 15:26:00 +0200147 debug_diagram(tbf->diag, "timeout DL-ASS");
Andreas Eversberg802bb6e2012-08-06 11:15:05 +0200148 tbf->n3105++;
149 if (tbf->n3105 == bts->n3105) {
150 LOGP(DRLCMAC, LOGL_NOTICE, "- N3105 exceeded\n");
Andreas Eversbergb83e2a72012-10-07 15:26:00 +0200151 debug_diagram(tbf->diag, "N3105 exceeded");
Andreas Eversberg802bb6e2012-08-06 11:15:05 +0200152 tbf_new_state(tbf, GPRS_RLCMAC_RELEASING);
153 tbf_timer_start(tbf, 3195, bts->t3195, 0);
154 return 0;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200155 }
Andreas Eversberg802bb6e2012-08-06 11:15:05 +0200156 /* reschedule DL assignment */
157 tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_SEND_ASS;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200158 } else
Andreas Eversberg802bb6e2012-08-06 11:15:05 +0200159 if (tbf->direction == GPRS_RLCMAC_DL_TBF) {
Andreas Eversberg14db19e2012-08-06 15:03:03 +0200160 if (!(tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_TO_DL_ACK))) {
161 LOGP(DRLCMAC, LOGL_NOTICE, "- Timeout for polling "
162 "PACKET DOWNLINK ACK.\n");
163 gprs_rlcmac_diag(tbf);
164 tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_TO_DL_ACK);
165 }
Andreas Eversbergb83e2a72012-10-07 15:26:00 +0200166 debug_diagram(tbf->diag, "timeout DL-ACK");
Andreas Eversberg802bb6e2012-08-06 11:15:05 +0200167 tbf->n3105++;
168 if (tbf->n3105 == bts->n3105) {
Andreas Eversberg4b470ff2012-07-16 12:02:40 +0200169 LOGP(DRLCMAC, LOGL_NOTICE, "- N3105 exceeded\n");
Andreas Eversbergb83e2a72012-10-07 15:26:00 +0200170 debug_diagram(tbf->diag, "N3105 exceeded");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200171 tbf_new_state(tbf, GPRS_RLCMAC_RELEASING);
172 tbf_timer_start(tbf, 3195, bts->t3195, 0);
173 return 0;
174 }
Andreas Eversberga9be1542012-09-27 09:23:24 +0200175 /* resend IMM.ASS on CCCH on timeout */
176 if ((tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))
177 && !(tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_DL_ACK))) {
178 LOGP(DRLCMAC, LOGL_DEBUG, "Re-send dowlink assignment "
179 "for TBF=%d on PCH (IMSI=%s)\n", tbf->tfi,
180 tbf->dir.dl.imsi);
181 /* send immediate assignment */
Holger Hans Peter Freyther344ff482013-10-17 12:01:04 +0200182 gprs_rlcmac_downlink_assignment(bts, tbf, 0, tbf->dir.dl.imsi);
Andreas Eversberga9be1542012-09-27 09:23:24 +0200183 tbf->dir.dl.wait_confirm = 1;
184 }
Andreas Eversberg4b470ff2012-07-16 12:02:40 +0200185 } else
186 LOGP(DRLCMAC, LOGL_ERROR, "- Poll Timeout, but no event!\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200187
188 return 0;
189}
190
Andreas Eversberga004e6a2013-05-13 16:45:21 +0200191int gprs_rlcmac_sba_timeout(struct gprs_rlcmac_sba *sba)
192{
193 LOGP(DRLCMAC, LOGL_NOTICE, "Poll timeout for SBA\n");
194 llist_del(&sba->list);
195 talloc_free(sba);
196
197 return 0;
198}
199
Andreas Eversberg07e97cf2012-08-07 16:00:56 +0200200static uint8_t get_ms_class_by_capability(MS_Radio_Access_capability_t *cap)
201{
202 int i;
203
204 for (i = 0; i < cap->Count_MS_RA_capability_value; i++) {
205 if (!cap->MS_RA_capability_value[i].u.Content.Exist_Multislot_capability)
206 continue;
207 if (!cap->MS_RA_capability_value[i].u.Content.Multislot_capability.Exist_GPRS_multislot_class)
208 continue;
209 return cap->MS_RA_capability_value[i].u.Content.Multislot_capability.GPRS_multislot_class;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200210 }
211
212 return 0;
213}
214
215/* Received Uplink RLC control block. */
Holger Hans Peter Freyther8d7a6322013-10-17 15:23:49 +0200216int gprs_rlcmac_rcv_control_block(struct gprs_rlcmac_bts *bts,
217 bitvec *rlc_block, uint8_t trx, uint8_t ts,
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200218 uint32_t fn)
Andreas Eversberge6228b32012-07-03 13:36:03 +0200219{
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200220 int8_t tfi = 0; /* must be signed */
Andreas Eversberge6228b32012-07-03 13:36:03 +0200221 uint32_t tlli = 0;
222 struct gprs_rlcmac_tbf *tbf;
Andreas Eversberga004e6a2013-05-13 16:45:21 +0200223 struct gprs_rlcmac_sba *sba;
Andreas Eversberg0f13c402012-07-16 11:59:23 +0200224 int rc;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200225
Andreas Eversberg6681bb82012-07-25 08:48:44 +0200226 RlcMacUplink_t * ul_control_block = (RlcMacUplink_t *)talloc_zero(tall_pcu_ctx, RlcMacUplink_t);
Andreas Eversberg0e403092012-07-06 11:04:57 +0200227 LOGP(DRLCMAC, LOGL_DEBUG, "+++++++++++++++++++++++++ RX : Uplink Control Block +++++++++++++++++++++++++\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200228 decode_gsm_rlcmac_uplink(rlc_block, ul_control_block);
Andreas Eversberg0e403092012-07-06 11:04:57 +0200229 LOGPC(DCSN1, LOGL_NOTICE, "\n");
230 LOGP(DRLCMAC, LOGL_DEBUG, "------------------------- RX : Uplink Control Block -------------------------\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200231 switch (ul_control_block->u.MESSAGE_TYPE) {
232 case MT_PACKET_CONTROL_ACK:
233 tlli = ul_control_block->u.Packet_Control_Acknowledgement.TLLI;
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200234 tbf = tbf_by_poll_fn(fn, trx, ts);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200235 if (!tbf) {
236 LOGP(DRLCMAC, LOGL_NOTICE, "PACKET CONTROL ACK with "
Andreas Eversberg592e04a2012-07-15 06:25:37 +0200237 "unknown FN=%u TLL=0x%08x (TRX %d TS %d)\n",
238 fn, tlli, trx, ts);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200239 break;
240 }
241 tfi = tbf->tfi;
242 if (tlli != tbf->tlli) {
Andreas Eversberg0e403092012-07-06 11:04:57 +0200243 LOGP(DRLCMAC, LOGL_INFO, "Phone changed TLLI to "
Andreas Eversberge6228b32012-07-03 13:36:03 +0200244 "0x%08x\n", tlli);
245 tbf->tlli = tlli;
246 }
Andreas Eversberg0e403092012-07-06 11:04:57 +0200247 LOGP(DRLCMAC, LOGL_DEBUG, "RX: [PCU <- BTS] TFI: %u TLLI: 0x%08x Packet Control Ack\n", tbf->tfi, tbf->tlli);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200248 tbf->poll_state = GPRS_RLCMAC_POLL_NONE;
249
250 /* check if this control ack belongs to packet uplink ack */
251 if (tbf->ul_ack_state == GPRS_RLCMAC_UL_ACK_WAIT_ACK) {
Andreas Eversberg0e403092012-07-06 11:04:57 +0200252 LOGP(DRLCMAC, LOGL_DEBUG, "TBF: [UPLINK] END TFI: %u TLLI: 0x%08x \n", tbf->tfi, tbf->tlli);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200253 tbf->ul_ack_state = GPRS_RLCMAC_UL_ACK_NONE;
Andreas Eversbergb83e2a72012-10-07 15:26:00 +0200254 debug_diagram(tbf->diag, "got CTL-ACK (fin)");
Andreas Eversberg14db19e2012-08-06 15:03:03 +0200255 if ((tbf->state_flags &
256 (1 << GPRS_RLCMAC_FLAG_TO_UL_ACK))) {
257 tbf->state_flags &=
258 ~(1 << GPRS_RLCMAC_FLAG_TO_UL_ACK);
259 LOGP(DRLCMAC, LOGL_NOTICE, "Recovered uplink "
Andreas Eversbergb83e2a72012-10-07 15:26:00 +0200260 "ack for UL TBF=%d\n", tbf->tfi);
Andreas Eversberg14db19e2012-08-06 15:03:03 +0200261 }
Andreas Eversberge6228b32012-07-03 13:36:03 +0200262 tbf_free(tbf);
263 break;
264 }
265 if (tbf->dl_ass_state == GPRS_RLCMAC_DL_ASS_WAIT_ACK) {
Andreas Eversberg0e403092012-07-06 11:04:57 +0200266 LOGP(DRLCMAC, LOGL_DEBUG, "TBF: [UPLINK] DOWNLINK ASSIGNED TFI: %u TLLI: 0x%08x \n", tbf->tfi, tbf->tlli);
Andreas Eversberg802bb6e2012-08-06 11:15:05 +0200267 /* reset N3105 */
268 tbf->n3105 = 0;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200269 tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE;
Andreas Eversbergb83e2a72012-10-07 15:26:00 +0200270 debug_diagram(tbf->diag, "got CTL-ACK DL-ASS");
Andreas Eversberg642c7d32012-07-23 17:58:55 +0200271 if (tbf->direction == GPRS_RLCMAC_UL_TBF)
272 tbf = tbf_by_tlli(tbf->tlli,
273 GPRS_RLCMAC_DL_TBF);
274 if (!tbf) {
275 LOGP(DRLCMAC, LOGL_ERROR, "Got ACK, but DL "
276 "TBF is gone\n");
277 break;
278 }
279 tbf_new_state(tbf, GPRS_RLCMAC_FLOW);
Andreas Eversbergcbcd1242012-08-07 15:48:21 +0200280 /* stop pending assignment timer */
281 tbf_timer_stop(tbf);
Andreas Eversberg14db19e2012-08-06 15:03:03 +0200282 if ((tbf->state_flags &
283 (1 << GPRS_RLCMAC_FLAG_TO_DL_ASS))) {
284 tbf->state_flags &=
285 ~(1 << GPRS_RLCMAC_FLAG_TO_DL_ASS);
286 LOGP(DRLCMAC, LOGL_NOTICE, "Recovered downlink "
Andreas Eversbergb83e2a72012-10-07 15:26:00 +0200287 "assignment for DL TBF=%d\n", tbf->tfi);
Andreas Eversberg14db19e2012-08-06 15:03:03 +0200288 }
Andreas Eversberg642c7d32012-07-23 17:58:55 +0200289 tbf_assign_control_ts(tbf);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200290 break;
291 }
292 if (tbf->ul_ass_state == GPRS_RLCMAC_UL_ASS_WAIT_ACK) {
Andreas Eversberg0e403092012-07-06 11:04:57 +0200293 LOGP(DRLCMAC, LOGL_DEBUG, "TBF: [DOWNLINK] UPLINK ASSIGNED TFI: %u TLLI: 0x%08x \n", tbf->tfi, tbf->tlli);
Andreas Eversberg802bb6e2012-08-06 11:15:05 +0200294 /* reset N3105 */
295 tbf->n3105 = 0;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200296 tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_NONE;
Andreas Eversbergb83e2a72012-10-07 15:26:00 +0200297 debug_diagram(tbf->diag, "got CTL-AC UL-ASS");
Andreas Eversberg642c7d32012-07-23 17:58:55 +0200298 if (tbf->direction == GPRS_RLCMAC_DL_TBF)
299 tbf = tbf_by_tlli(tbf->tlli,
300 GPRS_RLCMAC_UL_TBF);
301 if (!tbf) {
302 LOGP(DRLCMAC, LOGL_ERROR, "Got ACK, but UL "
303 "TBF is gone\n");
304 break;
305 }
306 tbf_new_state(tbf, GPRS_RLCMAC_FLOW);
Andreas Eversberg14db19e2012-08-06 15:03:03 +0200307 if ((tbf->state_flags &
308 (1 << GPRS_RLCMAC_FLAG_TO_UL_ASS))) {
309 tbf->state_flags &=
310 ~(1 << GPRS_RLCMAC_FLAG_TO_UL_ASS);
311 LOGP(DRLCMAC, LOGL_NOTICE, "Recovered uplink "
Andreas Eversbergb83e2a72012-10-07 15:26:00 +0200312 "assignment for UL TBF=%d\n", tbf->tfi);
Andreas Eversberg14db19e2012-08-06 15:03:03 +0200313 }
Andreas Eversberg642c7d32012-07-23 17:58:55 +0200314 tbf_assign_control_ts(tbf);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200315 break;
316 }
317 LOGP(DRLCMAC, LOGL_ERROR, "Error: received PACET CONTROL ACK "
318 "at no request\n");
319 break;
320 case MT_PACKET_DOWNLINK_ACK_NACK:
321 tfi = ul_control_block->u.Packet_Downlink_Ack_Nack.DOWNLINK_TFI;
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200322 tbf = tbf_by_poll_fn(fn, trx, ts);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200323 if (!tbf) {
324 LOGP(DRLCMAC, LOGL_NOTICE, "PACKET DOWNLINK ACK with "
Andreas Eversbergaafcd702012-10-07 15:33:31 +0200325 "unknown FN=%u TFI=%d (TRX %d TS %d)\n",
Andreas Eversberg592e04a2012-07-15 06:25:37 +0200326 fn, tfi, trx, ts);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200327 break;
328 }
Andreas Eversbergaafcd702012-10-07 15:33:31 +0200329 if (tbf->tfi != tfi) {
330 LOGP(DRLCMAC, LOGL_NOTICE, "PACKET DOWNLINK ACK with "
331 "wrong TFI=%d, ignoring!\n", tfi);
332 break;
333 }
Andreas Eversberg14db19e2012-08-06 15:03:03 +0200334 tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_DL_ACK);
335 if ((tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_TO_DL_ACK))) {
336 tbf->state_flags &= ~(1 << GPRS_RLCMAC_FLAG_TO_DL_ACK);
Andreas Eversbergaafcd702012-10-07 15:33:31 +0200337 LOGP(DRLCMAC, LOGL_NOTICE, "Recovered downlink ack "
338 "for DL TBF=%d\n", tbf->tfi);
Andreas Eversberg14db19e2012-08-06 15:03:03 +0200339 }
Andreas Eversberge6228b32012-07-03 13:36:03 +0200340 /* reset N3105 */
Andreas Eversberg802bb6e2012-08-06 11:15:05 +0200341 tbf->n3105 = 0;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200342 /* stop timer T3191 */
343 tbf_timer_stop(tbf);
344 tlli = tbf->tlli;
Andreas Eversberg0e403092012-07-06 11:04:57 +0200345 LOGP(DRLCMAC, LOGL_DEBUG, "RX: [PCU <- BTS] TFI: %u TLLI: 0x%08x Packet Downlink Ack/Nack\n", tbf->tfi, tbf->tlli);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200346 tbf->poll_state = GPRS_RLCMAC_POLL_NONE;
Andreas Eversbergb83e2a72012-10-07 15:26:00 +0200347 debug_diagram(tbf->diag, "got DL-ACK");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200348
Holger Hans Peter Freyther344ff482013-10-17 12:01:04 +0200349 rc = gprs_rlcmac_downlink_ack(bts, tbf,
Andreas Eversberge6228b32012-07-03 13:36:03 +0200350 ul_control_block->u.Packet_Downlink_Ack_Nack.Ack_Nack_Description.FINAL_ACK_INDICATION,
351 ul_control_block->u.Packet_Downlink_Ack_Nack.Ack_Nack_Description.STARTING_SEQUENCE_NUMBER,
352 ul_control_block->u.Packet_Downlink_Ack_Nack.Ack_Nack_Description.RECEIVED_BLOCK_BITMAP);
Andreas Eversberg0f13c402012-07-16 11:59:23 +0200353 if (rc == 1) {
354 tbf_free(tbf);
355 break;
356 }
Andreas Eversberge6228b32012-07-03 13:36:03 +0200357 /* check for channel request */
358 if (ul_control_block->u.Packet_Downlink_Ack_Nack.Exist_Channel_Request_Description) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200359 LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF in ack "
360 "message, so we provide one:\n");
Holger Hans Peter Freyther96efa702013-09-29 07:44:39 +0200361 tbf_alloc_ul(bts, tbf->trx_no, tbf->ms_class, tbf->tlli, tbf->ta, tbf);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200362 /* schedule uplink assignment */
363 tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS;
364 }
365 break;
366 case MT_PACKET_RESOURCE_REQUEST:
367 if (ul_control_block->u.Packet_Resource_Request.ID.UnionType) {
368 tlli = ul_control_block->u.Packet_Resource_Request.ID.u.TLLI;
369 tbf = tbf_by_tlli(tlli, GPRS_RLCMAC_UL_TBF);
Andreas Eversberg99a107d2012-09-27 09:21:52 +0200370 if (tbf) {
371 LOGP(DRLCMACUL, LOGL_NOTICE, "Got RACH from "
372 "TLLI=0x%08x while UL TBF=%d still "
373 "exists. Killing pending DL TBF\n",
374 tlli, tbf->tfi);
375 tbf_free(tbf);
376 tbf = NULL;
377 }
Andreas Eversberge6228b32012-07-03 13:36:03 +0200378 if (!tbf) {
Andreas Eversberg07e97cf2012-08-07 16:00:56 +0200379 uint8_t ms_class = 0;
Andreas Eversberg99a107d2012-09-27 09:21:52 +0200380 struct gprs_rlcmac_tbf *dl_tbf;
Andreas Eversberga004e6a2013-05-13 16:45:21 +0200381 uint8_t ta;
Andreas Eversberg99a107d2012-09-27 09:21:52 +0200382
383 if ((dl_tbf = tbf_by_tlli(tlli, GPRS_RLCMAC_DL_TBF))) {
384 LOGP(DRLCMACUL, LOGL_NOTICE, "Got RACH from "
385 "TLLI=0x%08x while DL TBF=%d still exists. "
386 "Killing pending DL TBF\n", tlli,
387 dl_tbf->tfi);
388 tbf_free(dl_tbf);
389 }
Andreas Eversberg07e97cf2012-08-07 16:00:56 +0200390 LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF "
391 "in packet ressource request of single "
392 "block, so we provide one:\n");
Andreas Eversberga004e6a2013-05-13 16:45:21 +0200393 sba = sba_find(trx, ts, fn);
394 if (!sba) {
395 LOGP(DRLCMAC, LOGL_NOTICE, "MS requests UL TBF "
396 "in packet ressource request of single "
397 "block, but there is no resource request "
398 "scheduled!\n");
399 rc = recall_timing_advance(tlli);
400 if (rc >= 0)
401 ta = rc;
402 else
403 ta = 0;
404 } else {
405 ta = sba->ta;
406 remember_timing_advance(tlli, ta);
407 llist_del(&sba->list);
408 talloc_free(sba);
409 }
Andreas Eversberg07e97cf2012-08-07 16:00:56 +0200410 if (ul_control_block->u.Packet_Resource_Request.Exist_MS_Radio_Access_capability)
411 ms_class = get_ms_class_by_capability(&ul_control_block->u.Packet_Resource_Request.MS_Radio_Access_capability);
412 if (!ms_class)
413 LOGP(DRLCMAC, LOGL_NOTICE, "MS does not give us a class.\n");
Holger Hans Peter Freyther86921282013-08-24 21:26:42 +0200414 tbf = tbf_alloc_ul(bts, trx, ms_class, tlli, ta, NULL);
Andreas Eversberg07e97cf2012-08-07 16:00:56 +0200415 if (!tbf)
416 break;
417 /* set control ts to current MS's TS, until assignment complete */
418 LOGP(DRLCMAC, LOGL_DEBUG, "Change control TS to %d until assinment is complete.\n", ts);
419 tbf->control_ts = ts;
420 /* schedule uplink assignment */
421 tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS;
Andreas Eversbergb83e2a72012-10-07 15:26:00 +0200422 debug_diagram(tbf->diag, "Res. REQ");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200423 break;
424 }
425 tfi = tbf->tfi;
426 } else {
427 if (ul_control_block->u.Packet_Resource_Request.ID.u.Global_TFI.UnionType) {
428 tfi = ul_control_block->u.Packet_Resource_Request.ID.u.Global_TFI.u.DOWNLINK_TFI;
Holger Hans Peter Freytherb67a8a32013-07-28 18:55:14 +0200429 tbf = tbf_by_tfi(bts, tfi, trx, GPRS_RLCMAC_DL_TBF);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200430 if (!tbf) {
Andreas Eversberg0e403092012-07-06 11:04:57 +0200431 LOGP(DRLCMAC, LOGL_NOTICE, "PACKET RESSOURCE REQ unknown downlink TBF=%d\n", tlli);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200432 break;
433 }
434 } else {
435 tfi = ul_control_block->u.Packet_Resource_Request.ID.u.Global_TFI.u.UPLINK_TFI;
Holger Hans Peter Freytherb67a8a32013-07-28 18:55:14 +0200436 tbf = tbf_by_tfi(bts, tfi, trx, GPRS_RLCMAC_UL_TBF);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200437 if (!tbf) {
Andreas Eversberg0e403092012-07-06 11:04:57 +0200438 LOGP(DRLCMAC, LOGL_NOTICE, "PACKET RESSOURCE REQ unknown uplink TBF=%d\n", tlli);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200439 break;
440 }
441 }
442 tlli = tbf->tlli;
443 }
Andreas Eversbergc8466f42012-07-15 19:34:53 +0200444 LOGP(DRLCMAC, LOGL_ERROR, "RX: [PCU <- BTS] %s TFI: %u TLLI: 0x%08x FIXME: Packet ressource request\n", (tbf->direction == GPRS_RLCMAC_UL_TBF) ? "UL" : "DL", tbf->tfi, tbf->tlli);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200445 break;
Andreas Eversberg050ace22013-03-16 16:22:02 +0100446 case MT_PACKET_MEASUREMENT_REPORT:
Andreas Eversberga004e6a2013-05-13 16:45:21 +0200447 sba = sba_find(trx, ts, fn);
448 if (!sba) {
449 LOGP(DRLCMAC, LOGL_NOTICE, "MS send measurement "
450 "in packet ressource request of single "
451 "block, but there is no resource request "
452 "scheduled!\n");
453 } else {
454 remember_timing_advance(ul_control_block->u.Packet_Measurement_Report.TLLI, sba->ta);
455 llist_del(&sba->list);
456 talloc_free(sba);
457 }
Andreas Eversberg050ace22013-03-16 16:22:02 +0100458 gprs_rlcmac_meas_rep(&ul_control_block->u.Packet_Measurement_Report);
459 break;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200460 default:
Andreas Eversberg0e403092012-07-06 11:04:57 +0200461 LOGP(DRLCMAC, LOGL_NOTICE, "RX: [PCU <- BTS] unknown control block received\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200462 }
Andreas Eversberg6681bb82012-07-25 08:48:44 +0200463 talloc_free(ul_control_block);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200464 return 1;
465}
466
Andreas Eversberge13fa2d2012-07-09 17:10:44 +0200467#ifdef DEBUG_DL_ASS_IDLE
468 char debug_imsi[16];
469#endif
Andreas Eversberge6228b32012-07-03 13:36:03 +0200470
Andreas Eversberge6228b32012-07-03 13:36:03 +0200471/*
472 * UL data block flow
473 */
474
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200475/* get TLLI from received UL data block */
476static int tlli_from_ul_data(uint8_t *data, uint8_t len, uint32_t *tlli)
477{
Andreas Eversberge6228b32012-07-03 13:36:03 +0200478 struct rlc_ul_header *rh = (struct rlc_ul_header *)data;
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200479 struct rlc_li_field *li;
480 uint8_t e;
Andreas Eversberg106ea792012-11-04 12:55:16 +0100481 uint32_t _tlli;
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200482
483 if (!rh->ti)
484 return -EINVAL;
485
486 data += 3;
487 len -= 3;
488 e = rh->e;
489 /* if E is not set (LI follows) */
490 while (!e) {
491 if (!len) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200492 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA LI extended, "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200493 "but no more data\n");
494 return -EINVAL;
495 }
496 /* get new E */
497 li = (struct rlc_li_field *)data;
498 if (li->e == 0) /* if LI==0, E is interpreted as '1' */
499 e = 1;
500 else
501 e = li->e;
502 data++;
503 len--;
504 }
505 if (len < 4) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200506 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA TLLI out of frame "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200507 "border\n");
508 return -EINVAL;
509 }
Andreas Eversberg106ea792012-11-04 12:55:16 +0100510 memcpy(&_tlli, data, 4);
511 *tlli = ntohl(_tlli);
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200512
513 return 0;
514}
515
516/* Store received block data in LLC message(s) and forward to SGSN if complete.
517 */
518static int gprs_rlcmac_assemble_llc(struct gprs_rlcmac_tbf *tbf, uint8_t *data,
519 uint8_t len)
520{
Andreas Eversberge6228b32012-07-03 13:36:03 +0200521 struct rlc_ul_header *rh = (struct rlc_ul_header *)data;
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200522 uint8_t e, m;
523 struct rlc_li_field *li;
524 uint8_t frame_offset[16], offset = 0, chunk;
525 int i, frames = 0;
526
Andreas Eversberge6228b32012-07-03 13:36:03 +0200527 LOGP(DRLCMACUL, LOGL_DEBUG, "- Assembling frames: (len=%d)\n", len);
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200528
529 data += 3;
530 len -= 3;
531 e = rh->e; /* if extended */
532 m = 1; /* more frames, that means: the first frame */
533
534 /* Parse frame offsets from length indicator(s), if any. */
535 while (1) {
536 if (frames == (int)sizeof(frame_offset)) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200537 LOGP(DRLCMACUL, LOGL_ERROR, "Too many frames in "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200538 "block\n");
539 return -EINVAL;
540 }
541 frame_offset[frames++] = offset;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200542 LOGP(DRLCMACUL, LOGL_DEBUG, "-- Frame %d starts at offset "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200543 "%d\n", frames, offset);
544 if (!len)
545 break;
546 /* M == 0 and E == 0 is not allowed in this version. */
547 if (!m && !e) {
Andreas Eversberg0e403092012-07-06 11:04:57 +0200548 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA TBF=%d "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200549 "ignored, because M='0' and E='0'.\n",
550 tbf->tfi);
551 return 0;
552 }
553 /* no more frames in this segment */
554 if (e) {
555 break;
556 }
557 /* There is a new frame and an LI that delimits it. */
558 if (m) {
559 li = (struct rlc_li_field *)data;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200560 LOGP(DRLCMACUL, LOGL_DEBUG, "-- Delimiter len=%d\n",
561 li->li);
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200562 /* Special case: LI == 0
563 * If the last segment would fit precisely into the
564 * rest of the RLC MAC block, there would be no way
565 * to delimit that this segment ends and is not
566 * continued in the next block.
567 * The special LI (0) is used to force the segment to
568 * extend into the next block, so it is delimited there.
569 * This LI must be skipped. Also it is the last LI.
570 */
571 if (li->li == 0) {
572 data++;
573 len--;
574 m = 1; /* M is ignored, we know there is more */
575 break; /* handle E as '1', so we break! */
576 }
577 e = li->e;
578 m = li->m;
579 offset += li->li;
580 data++;
581 len--;
582 continue;
583 }
584 }
585 if (!m) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200586 LOGP(DRLCMACUL, LOGL_DEBUG, "- Last frame carries spare "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200587 "data\n");
588 }
589
Andreas Eversberge6228b32012-07-03 13:36:03 +0200590 LOGP(DRLCMACUL, LOGL_DEBUG, "- Data length after length fields: %d\n",
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200591 len);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200592 /* TLLI */
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200593 if (rh->ti) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200594 if (len < 4) {
595 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA TLLI out of "
596 "frame border\n");
597 return -EINVAL;
598 }
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200599 data += 4;
600 len -= 4;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200601 LOGP(DRLCMACUL, LOGL_DEBUG, "- Length after skipping TLLI: "
602 "%d\n", len);
603 }
604
605 /* PFI */
606 if (rh->pi) {
607 LOGP(DRLCMACUL, LOGL_ERROR, "ERROR: PFI not supported, "
608 "please disable in SYSTEM INFORMATION\n");
609 if (len < 1) {
610 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA PFI out of "
611 "frame border\n");
612 return -EINVAL;
613 }
614 data++;
615 len--;
616 LOGP(DRLCMACUL, LOGL_DEBUG, "- Length after skipping PFI: "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200617 "%d\n", len);
618 }
619
620 /* Now we have:
621 * - a list of frames offsets: frame_offset[]
622 * - number of frames: i
623 * - m == 0: Last frame carries spare data (end of TBF).
624 */
625
626 /* Check if last offset would exceed frame. */
627 if (offset > len) {
Andreas Eversberg0e403092012-07-06 11:04:57 +0200628 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA TBF=%d ignored, "
629 "because LI delimits data that exceeds block size.\n",
630 tbf->tfi);
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200631 return -EINVAL;
632 }
633
634 /* create LLC frames */
635 for (i = 0; i < frames; i++) {
636 /* last frame ? */
637 if (i == frames - 1) {
638 /* no more data in last frame */
639 if (!m)
640 break;
641 /* data until end of frame */
642 chunk = len - frame_offset[i];
643 } else {
644 /* data until next frame */
645 chunk = frame_offset[i + 1] - frame_offset[i];
646 }
Andreas Eversberge6228b32012-07-03 13:36:03 +0200647 LOGP(DRLCMACUL, LOGL_DEBUG, "-- Appending chunk (len=%d) to "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200648 "frame at %d.\n", chunk, tbf->llc_index);
649 if (tbf->llc_index + chunk > LLC_MAX_LEN) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200650 LOGP(DRLCMACUL, LOGL_NOTICE, "LLC frame exceeds "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200651 "maximum size.\n");
652 chunk = LLC_MAX_LEN - tbf->llc_index;
653 }
654 memcpy(tbf->llc_frame + tbf->llc_index, data + frame_offset[i],
655 chunk);
656 tbf->llc_index += chunk;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200657 /* not last frame. */
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200658 if (i != frames - 1) {
659 /* send frame to SGSN */
Andreas Eversberge6228b32012-07-03 13:36:03 +0200660 LOGP(DRLCMACUL, LOGL_INFO, "Complete UL frame for "
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200661 "TBF=%d: len=%d\n", tbf->tfi, tbf->llc_index);
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200662 gprs_rlcmac_tx_ul_ud(tbf);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200663 tbf->llc_index = 0; /* reset frame space */
664 /* also check if CV==0, because the frame may fill up the
665 * block precisely, then it is also complete. normally the
666 * frame would be extended into the next block with a 0-length
667 * delimiter added to this block. */
668 } else if (rh->cv == 0) {
669 /* send frame to SGSN */
670 LOGP(DRLCMACUL, LOGL_INFO, "Complete UL frame for "
Andreas Eversberg0e403092012-07-06 11:04:57 +0200671 "TBF=%d that fits precisely in last block: "
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200672 "len=%d\n", tbf->tfi, tbf->llc_index);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200673 gprs_rlcmac_tx_ul_ud(tbf);
674 tbf->llc_index = 0; /* reset frame space */
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200675 }
676 }
677
678 return 0;
679}
680
Holger Hans Peter Freytherae947fc2013-10-17 13:29:03 +0200681struct msgb *gprs_rlcmac_send_uplink_ack(struct gprs_rlcmac_bts *bts,
682 struct gprs_rlcmac_tbf *tbf,
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200683 uint32_t fn)
684{
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200685 int final = (tbf->state_is(GPRS_RLCMAC_FINISHED));
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200686 struct msgb *msg;
687
Andreas Eversberg07e97cf2012-08-07 16:00:56 +0200688 if (final) {
689 if (tbf->poll_state != GPRS_RLCMAC_POLL_NONE) {
690 LOGP(DRLCMACUL, LOGL_DEBUG, "Polling is already "
691 "sheduled for TBF=%d, so we must wait for "
692 "final uplink ack...\n", tbf->tfi);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200693 return NULL;
Andreas Eversberg07e97cf2012-08-07 16:00:56 +0200694 }
Holger Hans Peter Freyther96efa702013-09-29 07:44:39 +0200695 if (sba_find(tbf->trx_no, tbf->control_ts, (fn + 13) % 2715648)) {
Andreas Eversberg07e97cf2012-08-07 16:00:56 +0200696 LOGP(DRLCMACUL, LOGL_DEBUG, "Polling is already "
697 "scheduled for single block allocation...\n");
698 return NULL;
699 }
Andreas Eversberge6228b32012-07-03 13:36:03 +0200700 }
701
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200702 msg = msgb_alloc(23, "rlcmac_ul_ack");
703 if (!msg)
704 return NULL;
705 bitvec *ack_vec = bitvec_alloc(23);
706 if (!ack_vec) {
707 msgb_free(msg);
708 return NULL;
709 }
710 bitvec_unhex(ack_vec,
711 "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
Andreas Eversberg6681bb82012-07-25 08:48:44 +0200712 RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)talloc_zero(tall_pcu_ctx, RlcMacDownlink_t);
Holger Hans Peter Freytherae947fc2013-10-17 13:29:03 +0200713 write_packet_uplink_ack(bts, mac_control_block, tbf, final);
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +0400714 encode_gsm_rlcmac_downlink(ack_vec, mac_control_block);
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200715 bitvec_pack(ack_vec, msgb_put(msg, 23));
716 bitvec_free(ack_vec);
Andreas Eversberg6681bb82012-07-25 08:48:44 +0200717 talloc_free(mac_control_block);
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200718
Andreas Eversbergee31b782012-07-15 16:27:01 +0200719 /* now we must set this flag, so we are allowed to assign downlink
720 * TBF on PACCH. it is only allowed when TLLI is aknowledged. */
Andreas Eversberg08e93cd2012-07-26 08:13:06 +0200721 tbf->dir.ul.contention_resolution_done = 1;
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200722
723 if (final) {
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200724 tbf->poll_state = GPRS_RLCMAC_POLL_SCHED;
725 tbf->poll_fn = (fn + 13) % 2715648;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200726 /* waiting for final acknowledge */
727 tbf->ul_ack_state = GPRS_RLCMAC_UL_ACK_WAIT_ACK;
Andreas Eversberg08e93cd2012-07-26 08:13:06 +0200728 tbf->dir.ul.final_ack_sent = 1;
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200729 } else
Andreas Eversberge6228b32012-07-03 13:36:03 +0200730 tbf->ul_ack_state = GPRS_RLCMAC_UL_ACK_NONE;
Andreas Eversbergb83e2a72012-10-07 15:26:00 +0200731 debug_diagram(tbf->diag, "send UL-ACK");
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200732
733 return msg;
734}
735
736/* receive UL data block
737 *
738 * The blocks are defragmented and forwarded as LLC frames, if complete.
739 */
Holger Hans Peter Freyther698b6122013-10-17 13:44:18 +0200740int gprs_rlcmac_rcv_data_block_acknowledged(struct gprs_rlcmac_bts *bts,
741 uint8_t trx, uint8_t ts,
Andreas Eversberg570b44b2013-03-16 16:15:01 +0100742 uint8_t *data, uint8_t len, int8_t rssi)
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200743{
744 struct gprs_rlcmac_tbf *tbf;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200745 struct rlc_ul_header *rh = (struct rlc_ul_header *)data;
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200746 uint16_t mod_sns, mod_sns_half, offset_v_q, offset_v_r, index;
747 int rc;
748
Andreas Eversbergdfa563c2012-07-06 08:13:59 +0200749 switch (len) {
750 case 54:
751 /* omitting spare bits */
752 len = 53;
753 break;
754 case 40:
755 /* omitting spare bits */
756 len = 39;
757 break;
758 case 34:
759 /* omitting spare bits */
760 len = 33;
761 break;
762 case 23:
763 break;
764 default:
765 LOGP(DRLCMACUL, LOGL_ERROR, "Dropping data block with invalid"
766 "length: %d)\n", len);
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200767 return -EINVAL;
768 }
769
770 /* find TBF inst from given TFI */
Holger Hans Peter Freytherb67a8a32013-07-28 18:55:14 +0200771 tbf = tbf_by_tfi(bts, rh->tfi, trx, GPRS_RLCMAC_UL_TBF);
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200772 if (!tbf) {
Andreas Eversberg0e403092012-07-06 11:04:57 +0200773 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA unknown TBF=%d\n",
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200774 rh->tfi);
775 return 0;
776 }
Andreas Eversberg14db19e2012-08-06 15:03:03 +0200777 tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_UL_DATA);
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200778
Andreas Eversberg0e403092012-07-06 11:04:57 +0200779 LOGP(DRLCMACUL, LOGL_DEBUG, "UL DATA TBF=%d received (V(Q)=%d .. "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200780 "V(R)=%d)\n", rh->tfi, tbf->dir.ul.v_q, tbf->dir.ul.v_r);
781
Andreas Eversberg050ace22013-03-16 16:22:02 +0100782 /* process RSSI */
783 gprs_rlcmac_rssi(tbf, rssi);
784
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200785 /* get TLLI */
786 if (!tbf->tlli_valid) {
Andreas Eversberg3a7eb6b2012-10-07 15:55:25 +0200787 struct gprs_rlcmac_tbf *dl_tbf, *ul_tbf;
Andreas Eversbergbc655862012-07-23 18:13:31 +0200788
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200789 /* no TLLI yet */
790 if (!rh->ti) {
Andreas Eversberg0e403092012-07-06 11:04:57 +0200791 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA TBF=%d without "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200792 "TLLI, but no TLLI received yet\n", rh->tfi);
793 return 0;
794 }
795 rc = tlli_from_ul_data(data, len, &tbf->tlli);
796 if (rc) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200797 LOGP(DRLCMACUL, LOGL_NOTICE, "Failed to decode TLLI "
Andreas Eversberg0e403092012-07-06 11:04:57 +0200798 "of UL DATA TBF=%d.\n", rh->tfi);
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200799 return 0;
800 }
Andreas Eversberg0e403092012-07-06 11:04:57 +0200801 LOGP(DRLCMACUL, LOGL_INFO, "Decoded premier TLLI=0x%08x of "
802 "UL DATA TBF=%d.\n", tbf->tlli, rh->tfi);
Andreas Eversbergbc655862012-07-23 18:13:31 +0200803 if ((dl_tbf = tbf_by_tlli(tbf->tlli, GPRS_RLCMAC_DL_TBF))) {
804 LOGP(DRLCMACUL, LOGL_NOTICE, "Got RACH from "
805 "TLLI=0x%08x while DL TBF=%d still exists. "
806 "Killing pending DL TBF\n", tbf->tlli,
807 dl_tbf->tfi);
808 tbf_free(dl_tbf);
809 }
Andreas Eversberg3a7eb6b2012-10-07 15:55:25 +0200810 /* tbf_by_tlli will not find your TLLI, because it is not
811 * yet marked valid */
812 if ((ul_tbf = tbf_by_tlli(tbf->tlli, GPRS_RLCMAC_UL_TBF))) {
813 LOGP(DRLCMACUL, LOGL_NOTICE, "Got RACH from "
814 "TLLI=0x%08x while UL TBF=%d still exists. "
815 "Killing pending UL TBF\n", tbf->tlli,
816 ul_tbf->tfi);
817 tbf_free(ul_tbf);
818 }
819 /* mark TLLI valid now */
820 tbf->tlli_valid = 1;
Andreas Eversberga004e6a2013-05-13 16:45:21 +0200821 /* store current timing advance */
822 remember_timing_advance(tbf->tlli, tbf->ta);
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200823 /* already have TLLI, but we stille get another one */
824 } else if (rh->ti) {
825 uint32_t tlli;
826 rc = tlli_from_ul_data(data, len, &tlli);
827 if (rc) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200828 LOGP(DRLCMACUL, LOGL_NOTICE, "Failed to decode TLLI "
Andreas Eversberg0e403092012-07-06 11:04:57 +0200829 "of UL DATA TBF=%d.\n", rh->tfi);
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200830 return 0;
831 }
832 if (tlli != tbf->tlli) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200833 LOGP(DRLCMACUL, LOGL_NOTICE, "TLLI mismatch on UL "
Andreas Eversberg0e403092012-07-06 11:04:57 +0200834 "DATA TBF=%d. (Ignoring due to contention "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200835 "resolution)\n", rh->tfi);
836 return 0;
837 }
838 }
839
840 mod_sns = tbf->sns - 1;
841 mod_sns_half = (tbf->sns >> 1) - 1;
842
843 /* restart T3169 */
Andreas Eversbergdfa563c2012-07-06 08:13:59 +0200844 tbf_timer_start(tbf, 3169, bts->t3169, 0);
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200845
846 /* Increment RX-counter */
847 tbf->dir.ul.rx_counter++;
848
849 /* current block relative to lowest unreceived block */
850 offset_v_q = (rh->bsn - tbf->dir.ul.v_q) & mod_sns;
851 /* If out of window (may happen if blocks below V(Q) are received
852 * again. */
853 if (offset_v_q >= tbf->ws) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200854 LOGP(DRLCMACUL, LOGL_DEBUG, "- BSN %d out of window "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200855 "%d..%d (it's normal)\n", rh->bsn, tbf->dir.ul.v_q,
856 (tbf->dir.ul.v_q + tbf->ws - 1) & mod_sns);
857 return 0;
858 }
859 /* Write block to buffer and set receive state array. */
860 index = rh->bsn & mod_sns_half; /* memory index of block */
861 memcpy(tbf->rlc_block[index], data, len); /* Copy block. */
862 tbf->rlc_block_len[index] = len;
863 tbf->dir.ul.v_n[index] = 'R'; /* Mark received block. */
Andreas Eversberge6228b32012-07-03 13:36:03 +0200864 LOGP(DRLCMACUL, LOGL_DEBUG, "- BSN %d storing in window (%d..%d)\n",
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200865 rh->bsn, tbf->dir.ul.v_q,
866 (tbf->dir.ul.v_q + tbf->ws - 1) & mod_sns);
867 /* Raise V(R) to highest received sequence number not received. */
868 offset_v_r = (rh->bsn + 1 - tbf->dir.ul.v_r) & mod_sns;
869 if (offset_v_r < (tbf->sns >> 1)) { /* Positive offset, so raise. */
870 while (offset_v_r--) {
871 if (offset_v_r) /* all except the received block */
872 tbf->dir.ul.v_n[tbf->dir.ul.v_r & mod_sns_half]
873 = 'N'; /* Mark block as not received */
874 tbf->dir.ul.v_r = (tbf->dir.ul.v_r + 1) & mod_sns;
875 /* Inc V(R). */
876 }
Andreas Eversberge6228b32012-07-03 13:36:03 +0200877 LOGP(DRLCMACUL, LOGL_DEBUG, "- Raising V(R) to %d\n",
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200878 tbf->dir.ul.v_r);
879 }
880
881 /* Raise V(Q) if possible, and retrieve LLC frames from blocks.
882 * This is looped until there is a gap (non received block) or
883 * the window is empty.*/
884 while (tbf->dir.ul.v_q != tbf->dir.ul.v_r && tbf->dir.ul.v_n[
885 (index = tbf->dir.ul.v_q & mod_sns_half)] == 'R') {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200886 LOGP(DRLCMACUL, LOGL_DEBUG, "- Taking block %d out, raising "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200887 "V(Q) to %d\n", tbf->dir.ul.v_q,
888 (tbf->dir.ul.v_q + 1) & mod_sns);
889 /* get LLC data from block */
890 gprs_rlcmac_assemble_llc(tbf, tbf->rlc_block[index],
891 tbf->rlc_block_len[index]);
892 /* raise V(Q), because block already received */
893 tbf->dir.ul.v_q = (tbf->dir.ul.v_q + 1) & mod_sns;
894 }
895
896 /* Check CV of last frame in buffer */
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200897 if (tbf->state_is(GPRS_RLCMAC_FLOW) /* still in flow state */
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200898 && tbf->dir.ul.v_q == tbf->dir.ul.v_r) { /* if complete */
Andreas Eversberge6228b32012-07-03 13:36:03 +0200899 struct rlc_ul_header *last_rh = (struct rlc_ul_header *)
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200900 tbf->rlc_block[(tbf->dir.ul.v_r - 1) & mod_sns_half];
Andreas Eversberge6228b32012-07-03 13:36:03 +0200901 LOGP(DRLCMACUL, LOGL_DEBUG, "- No gaps in received block, "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200902 "last block: BSN=%d CV=%d\n", last_rh->bsn,
903 last_rh->cv);
904 if (last_rh->cv == 0) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200905 LOGP(DRLCMACUL, LOGL_DEBUG, "- Finished with UL "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200906 "TBF\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200907 tbf_new_state(tbf, GPRS_RLCMAC_FINISHED);
908 /* Reset N3103 counter. */
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200909 tbf->dir.ul.n3103 = 0;
910 }
911 }
912
913 /* If TLLI is included or if we received half of the window, we send
914 * an ack/nack */
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200915 if (rh->si || rh->ti || tbf->state_is(GPRS_RLCMAC_FINISHED)
Andreas Eversbergf54a89e2012-07-16 11:56:11 +0200916 || (tbf->dir.ul.rx_counter % SEND_ACK_AFTER_FRAMES) == 0) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200917 if (rh->si) {
Andreas Eversbergf54a89e2012-07-16 11:56:11 +0200918 LOGP(DRLCMACUL, LOGL_NOTICE, "- Scheduling Ack/Nack, "
Andreas Eversberge6228b32012-07-03 13:36:03 +0200919 "because MS is stalled.\n");
920 }
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200921 if (rh->ti) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200922 LOGP(DRLCMACUL, LOGL_DEBUG, "- Scheduling Ack/Nack, "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200923 "because TLLI is included.\n");
924 }
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200925 if (tbf->state_is(GPRS_RLCMAC_FINISHED)) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200926 LOGP(DRLCMACUL, LOGL_DEBUG, "- Scheduling Ack/Nack, "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200927 "because last block has CV==0.\n");
928 }
Andreas Eversbergf54a89e2012-07-16 11:56:11 +0200929 if ((tbf->dir.ul.rx_counter % SEND_ACK_AFTER_FRAMES) == 0) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200930 LOGP(DRLCMACUL, LOGL_DEBUG, "- Scheduling Ack/Nack, "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200931 "because %d frames received.\n",
Andreas Eversbergf54a89e2012-07-16 11:56:11 +0200932 SEND_ACK_AFTER_FRAMES);
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200933 }
Andreas Eversberge6228b32012-07-03 13:36:03 +0200934 if (tbf->ul_ack_state == GPRS_RLCMAC_UL_ACK_NONE) {
Andreas Eversbergb83e2a72012-10-07 15:26:00 +0200935#ifdef DEBUG_DIAGRAM
936 if (rh->si)
937 debug_diagram(tbf->diag, "sched UL-ACK stall");
938 if (rh->ti)
939 debug_diagram(tbf->diag, "sched UL-ACK TLLI");
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200940 if (tbf->state_is(GPRS_RLCMAC_FINISHED))
Andreas Eversbergb83e2a72012-10-07 15:26:00 +0200941 debug_diagram(tbf->diag, "sched UL-ACK CV==0");
942 if ((tbf->dir.ul.rx_counter % SEND_ACK_AFTER_FRAMES) == 0)
943 debug_diagram(tbf->diag, "sched UL-ACK n=%d",
944 tbf->dir.ul.rx_counter);
945#endif
Andreas Eversberge6228b32012-07-03 13:36:03 +0200946 /* trigger sending at next RTS */
947 tbf->ul_ack_state = GPRS_RLCMAC_UL_ACK_SEND_ACK;
948 } else {
949 /* already triggered */
950 LOGP(DRLCMACUL, LOGL_DEBUG, "- Sending Ack/Nack is "
951 "already triggered, don't schedule!\n");
952 }
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200953 }
954
955 return 0;
956}
957
Andreas Eversberge6228b32012-07-03 13:36:03 +0200958struct msgb *gprs_rlcmac_send_packet_uplink_assignment(
Holger Hans Peter Freytherd507ce62013-10-17 15:32:37 +0200959 struct gprs_rlcmac_bts *bts,
Andreas Eversberge6228b32012-07-03 13:36:03 +0200960 struct gprs_rlcmac_tbf *tbf, uint32_t fn)
961{
962 struct msgb *msg;
963 struct gprs_rlcmac_tbf *new_tbf;
964
Andreas Eversberg802bb6e2012-08-06 11:15:05 +0200965#if POLLING_ASSIGNMENT_UL == 1
Andreas Eversberge6228b32012-07-03 13:36:03 +0200966 if (tbf->poll_state != GPRS_RLCMAC_POLL_NONE) {
967 LOGP(DRLCMACUL, LOGL_DEBUG, "Polling is already "
968 "sheduled for TBF=%d, so we must wait for uplink "
969 "assignment...\n", tbf->tfi);
970 return NULL;
971 }
Holger Hans Peter Freyther96efa702013-09-29 07:44:39 +0200972 if (sba_find(tbf->trx_no, tbf->control_ts, (fn + 13) % 2715648)) {
Andreas Eversberg07e97cf2012-08-07 16:00:56 +0200973 LOGP(DRLCMACUL, LOGL_DEBUG, "Polling is already scheduled for "
974 "single block allocation...\n");
975 return NULL;
976 }
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200977#endif
Andreas Eversberge6228b32012-07-03 13:36:03 +0200978
979 /* on down TBF we get the uplink TBF to be assigned. */
980 if (tbf->direction == GPRS_RLCMAC_DL_TBF)
981 new_tbf = tbf_by_tlli(tbf->tlli, GPRS_RLCMAC_UL_TBF);
982 else
983 new_tbf = tbf;
984
985 if (!new_tbf) {
986 LOGP(DRLCMACUL, LOGL_ERROR, "We have a schedule for uplink "
987 "assignment at downlink TBF=%d, but there is no uplink "
988 "TBF\n", tbf->tfi);
989 tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_NONE;
990 return NULL;
991 }
992
993 msg = msgb_alloc(23, "rlcmac_ul_ass");
994 if (!msg)
995 return NULL;
Andreas Eversberg0e403092012-07-06 11:04:57 +0200996 LOGP(DRLCMAC, LOGL_INFO, "TBF: START TFI: %u TLLI: 0x%08x Packet Uplink Assignment (PACCH)\n", new_tbf->tfi, new_tbf->tlli);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200997 bitvec *ass_vec = bitvec_alloc(23);
998 if (!ass_vec) {
999 msgb_free(msg);
1000 return NULL;
1001 }
1002 bitvec_unhex(ass_vec,
1003 "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
Holger Hans Peter Freyther485860c2013-10-17 15:38:23 +02001004 write_packet_uplink_assignment(bts, ass_vec, tbf->tfi,
Andreas Eversberg07e97cf2012-08-07 16:00:56 +02001005 (tbf->direction == GPRS_RLCMAC_DL_TBF), tbf->tlli,
Andreas Eversbergaafcbbb2012-09-27 09:20:45 +02001006 tbf->tlli_valid, new_tbf, POLLING_ASSIGNMENT_UL, bts->alpha,
Andreas Eversbergafdd9e12012-10-07 17:08:55 +02001007 bts->gamma, -1);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001008 bitvec_pack(ass_vec, msgb_put(msg, 23));
Andreas Eversberg6681bb82012-07-25 08:48:44 +02001009 RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)talloc_zero(tall_pcu_ctx, RlcMacDownlink_t);
Andreas Eversberg0e403092012-07-06 11:04:57 +02001010 LOGP(DRLCMAC, LOGL_DEBUG, "+++++++++++++++++++++++++ TX : Packet Uplink Assignment +++++++++++++++++++++++++\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +02001011 decode_gsm_rlcmac_downlink(ass_vec, mac_control_block);
Andreas Eversberg0e403092012-07-06 11:04:57 +02001012 LOGPC(DCSN1, LOGL_NOTICE, "\n");
1013 LOGP(DRLCMAC, LOGL_DEBUG, "------------------------- TX : Packet Uplink Assignment -------------------------\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +02001014 bitvec_free(ass_vec);
Andreas Eversberg6681bb82012-07-25 08:48:44 +02001015 talloc_free(mac_control_block);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001016
Andreas Eversberg802bb6e2012-08-06 11:15:05 +02001017#if POLLING_ASSIGNMENT_UL == 1
Andreas Eversberge6228b32012-07-03 13:36:03 +02001018 tbf->poll_state = GPRS_RLCMAC_POLL_SCHED;
1019 tbf->poll_fn = (fn + 13) % 2715648;
1020 tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_WAIT_ACK;
1021#else
1022 tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_NONE;
Andreas Eversberg642c7d32012-07-23 17:58:55 +02001023 tbf_new_state(new_tbf, GPRS_RLCMAC_FLOW);
1024 tbf_assign_control_ts(new_tbf);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001025#endif
Andreas Eversbergb83e2a72012-10-07 15:26:00 +02001026 debug_diagram(tbf->diag, "send UL-ASS");
Andreas Eversberge6228b32012-07-03 13:36:03 +02001027
1028 return msg;
1029}
1030
Holger Hans Peter Freytherb0250eb2013-10-17 13:46:19 +02001031int gprs_rlcmac_rcv_rach(struct gprs_rlcmac_bts *bts,
1032 uint8_t ra, uint32_t Fn, int16_t qta)
Andreas Eversberge6228b32012-07-03 13:36:03 +02001033{
1034 struct gprs_rlcmac_tbf *tbf;
Andreas Eversberg02d7cd22013-01-15 08:59:34 +01001035 uint8_t trx, ts = 0;
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001036 int8_t tfi; /* must be signed */
Andreas Eversberg07e97cf2012-08-07 16:00:56 +02001037 uint8_t sb = 0;
1038 uint32_t sb_fn = 0;
1039 int rc;
1040 uint8_t plen;
Andreas Eversberge6228b32012-07-03 13:36:03 +02001041
1042 LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF on RACH, so we provide "
1043 "one:\n");
Andreas Eversberg07e97cf2012-08-07 16:00:56 +02001044 if ((ra & 0xf8) == 0x70) {
1045 LOGP(DRLCMAC, LOGL_DEBUG, "MS requests single block "
1046 "allocation\n");
1047 sb = 1;
1048 } else if (bts->force_two_phase) {
1049 LOGP(DRLCMAC, LOGL_DEBUG, "MS requests single phase access, "
1050 "but we force two phase access\n");
1051 sb = 1;
Andreas Eversberge6228b32012-07-03 13:36:03 +02001052 }
Andreas Eversberge6228b32012-07-03 13:36:03 +02001053 if (qta < 0)
1054 qta = 0;
1055 if (qta > 252)
1056 qta = 252;
Andreas Eversberg07e97cf2012-08-07 16:00:56 +02001057 if (sb) {
Holger Hans Peter Freyther173a2402013-10-16 21:47:45 +02001058 rc = sba_alloc(bts, &trx, &ts, &sb_fn, qta >> 2);
Andreas Eversberg07e97cf2012-08-07 16:00:56 +02001059 if (rc < 0)
1060 return rc;
1061 LOGP(DRLCMAC, LOGL_DEBUG, "RX: [PCU <- BTS] RACH qbit-ta=%d "
1062 "ra=0x%02x, Fn=%d (%d,%d,%d)\n", qta, ra, Fn,
1063 (Fn / (26 * 51)) % 32, Fn % 51, Fn % 26);
1064 LOGP(DRLCMAC, LOGL_INFO, "TX: Immediate Assignment Uplink "
1065 "(AGCH)\n");
1066 } else {
1067 // Create new TBF
Holger Hans Peter Freytherbcafdf82013-08-24 21:13:31 +02001068 #warning "Copy and pate with other routines.."
Holger Hans Peter Freytherd6bd91e2013-08-24 21:16:55 +02001069 tfi = tfi_find_free(bts, GPRS_RLCMAC_UL_TBF, &trx, -1);
Andreas Eversberg07e97cf2012-08-07 16:00:56 +02001070 if (tfi < 0) {
1071 LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n");
1072 /* FIXME: send reject */
1073 return -EBUSY;
1074 }
1075 /* set class to 0, since we don't know the multislot class yet */
Holger Hans Peter Freytherb67a8a32013-07-28 18:55:14 +02001076 tbf = tbf_alloc(bts, NULL, GPRS_RLCMAC_UL_TBF, tfi, trx, 0, 1);
Andreas Eversberg07e97cf2012-08-07 16:00:56 +02001077 if (!tbf) {
1078 LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n");
1079 /* FIXME: send reject */
1080 return -EBUSY;
1081 }
1082 tbf->ta = qta >> 2;
1083 tbf_new_state(tbf, GPRS_RLCMAC_FLOW);
1084 tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_CCCH);
1085 tbf_timer_start(tbf, 3169, bts->t3169, 0);
1086 LOGP(DRLCMAC, LOGL_DEBUG, "TBF: [UPLINK] START TFI: %u\n",
1087 tbf->tfi);
1088 LOGP(DRLCMAC, LOGL_DEBUG, "RX: [PCU <- BTS] TFI: %u RACH "
1089 "qbit-ta=%d ra=0x%02x, Fn=%d (%d,%d,%d)\n", tbf->tfi,
1090 qta, ra, Fn, (Fn / (26 * 51)) % 32, Fn % 51, Fn % 26);
1091 LOGP(DRLCMAC, LOGL_INFO, "TX: START TFI: %u Immediate "
1092 "Assignment Uplink (AGCH)\n", tbf->tfi);
1093 }
Andreas Eversberg7b045012012-07-05 07:38:49 +02001094 bitvec *immediate_assignment = bitvec_alloc(22) /* without plen */;
Andreas Eversberg07e97cf2012-08-07 16:00:56 +02001095 bitvec_unhex(immediate_assignment,
1096 "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
1097 if (sb)
Holger Hans Peter Freytheree7a5352013-10-17 15:41:36 +02001098 plen = write_immediate_assignment(bts, immediate_assignment, 0, ra,
Andreas Eversberg07e97cf2012-08-07 16:00:56 +02001099 Fn, qta >> 2, bts->trx[trx].arfcn, ts,
Andreas Eversbergaafcbbb2012-09-27 09:20:45 +02001100 bts->trx[trx].pdch[ts].tsc, 0, 0, 0, 0, sb_fn, 1,
Andreas Eversbergafdd9e12012-10-07 17:08:55 +02001101 bts->alpha, bts->gamma, -1);
Andreas Eversberg07e97cf2012-08-07 16:00:56 +02001102 else
Holger Hans Peter Freytheree7a5352013-10-17 15:41:36 +02001103 plen = write_immediate_assignment(bts, immediate_assignment, 0, ra,
Andreas Eversberg07e97cf2012-08-07 16:00:56 +02001104 Fn, tbf->ta, tbf->arfcn, tbf->first_ts, tbf->tsc,
Andreas Eversbergaafcbbb2012-09-27 09:20:45 +02001105 tbf->tfi, tbf->dir.ul.usf[tbf->first_ts], 0, 0, 0, 0,
Andreas Eversbergafdd9e12012-10-07 17:08:55 +02001106 bts->alpha, bts->gamma, -1);
Andreas Eversberg7b045012012-07-05 07:38:49 +02001107 pcu_l1if_tx_agch(immediate_assignment, plen);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001108 bitvec_free(immediate_assignment);
1109
1110 return 0;
1111}
1112
1113
1114/*
1115 * DL data block flow
1116 */
1117
Andreas Eversberg24131bf2012-07-21 11:09:58 +02001118static struct msgb *llc_dequeue(struct gprs_rlcmac_tbf *tbf)
1119{
1120 struct msgb *msg;
1121 struct timeval *tv, tv_now;
1122 uint32_t octets = 0, frames = 0;
1123
1124 gettimeofday(&tv_now, NULL);
1125
1126 while ((msg = msgb_dequeue(&tbf->llc_queue))) {
1127 tv = (struct timeval *)msg->data;
1128 msgb_pull(msg, sizeof(*tv));
1129 if (tv->tv_sec /* not infinite */
1130 && (tv_now.tv_sec > tv->tv_sec /* and secs expired */
1131 || (tv_now.tv_sec == tv->tv_sec /* .. or if secs equal .. */
1132 && tv_now.tv_usec > tv->tv_usec))) { /* .. usecs expired */
1133 LOGP(DRLCMACDL, LOGL_NOTICE, "Discarding LLC PDU of "
1134 "DL TBF=%d, because lifetime limit reached\n",
1135 tbf->tfi);
1136 frames++;
1137 octets += msg->len;
1138 msgb_free(msg);
1139 continue;
1140 }
1141 break;
1142 }
1143
1144 if (frames) {
1145 if (frames > 0xff)
1146 frames = 0xff;
1147 if (octets > 0xffffff)
1148 octets = 0xffffff;
Holger Hans Peter Freyther90692f92013-07-13 12:51:16 +02001149 bssgp_tx_llc_discarded(gprs_bssgp_pcu_current_bctx(),
1150 tbf->tlli, frames, octets);
Andreas Eversberg24131bf2012-07-21 11:09:58 +02001151 }
1152
1153 return msg;
1154}
1155
Andreas Eversberge6228b32012-07-03 13:36:03 +02001156/* send DL data block
1157 *
1158 * The messages are fragmented and forwarded as data blocks.
1159 */
1160struct msgb *gprs_rlcmac_send_data_block_acknowledged(
Holger Hans Peter Freyther4ffc2602013-10-17 15:21:10 +02001161 struct gprs_rlcmac_bts *bts,
Andreas Eversberg592e04a2012-07-15 06:25:37 +02001162 struct gprs_rlcmac_tbf *tbf, uint32_t fn, uint8_t ts)
Andreas Eversberge6228b32012-07-03 13:36:03 +02001163{
Andreas Eversberge6228b32012-07-03 13:36:03 +02001164 struct rlc_dl_header *rh;
1165 struct rlc_li_field *li;
1166 uint8_t block_length; /* total length of block, including spare bits */
1167 uint8_t block_data; /* usable data of block, w/o spare bits, inc. MAC */
1168 struct msgb *msg, *dl_msg;
1169 uint8_t bsn;
1170 uint16_t mod_sns = tbf->sns - 1;
1171 uint16_t mod_sns_half = (tbf->sns >> 1) - 1;
1172 uint16_t index;
1173 uint8_t *delimiter, *data, *e_pointer;
1174 uint8_t len;
1175 uint16_t space, chunk;
Andreas Eversberg0c9b50c2012-10-07 15:50:51 +02001176 int first_fin_ack = 0;
Andreas Eversberge6228b32012-07-03 13:36:03 +02001177
Andreas Eversberg0e403092012-07-06 11:04:57 +02001178 LOGP(DRLCMACDL, LOGL_DEBUG, "DL DATA TBF=%d downlink (V(A)==%d .. "
Andreas Eversberge6228b32012-07-03 13:36:03 +02001179 "V(S)==%d)\n", tbf->tfi, tbf->dir.dl.v_a, tbf->dir.dl.v_s);
1180
1181do_resend:
1182 /* check if there is a block with negative acknowledgement */
1183 for (bsn = tbf->dir.dl.v_a; bsn != tbf->dir.dl.v_s;
1184 bsn = (bsn + 1) & mod_sns) {
1185 index = (bsn & mod_sns_half);
1186 if (tbf->dir.dl.v_b[index] == 'N'
1187 || tbf->dir.dl.v_b[index] == 'X') {
1188 LOGP(DRLCMACDL, LOGL_DEBUG, "- Resending BSN %d\n",
1189 bsn);
1190 /* re-send block with negative aknowlegement */
1191 tbf->dir.dl.v_b[index] = 'U'; /* unacked */
1192 goto tx_block;
1193 }
1194 }
1195
1196 /* if the window has stalled, or transfer is complete,
1197 * send an unacknowledged block */
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +02001198 if (tbf->state_is(GPRS_RLCMAC_FINISHED)
Andreas Eversberge6228b32012-07-03 13:36:03 +02001199 || ((tbf->dir.dl.v_s - tbf->dir.dl.v_a) & mod_sns) == tbf->ws) {
1200 int resend = 0;
1201
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +02001202 if (tbf->state_is(GPRS_RLCMAC_FINISHED))
Andreas Eversberge6228b32012-07-03 13:36:03 +02001203 LOGP(DRLCMACDL, LOGL_DEBUG, "- Restarting at BSN %d, "
1204 "because all blocks have been transmitted.\n",
1205 tbf->dir.dl.v_a);
1206 else
Andreas Eversberg4b470ff2012-07-16 12:02:40 +02001207 LOGP(DRLCMACDL, LOGL_NOTICE, "- Restarting at BSN %d, "
Andreas Eversberge6228b32012-07-03 13:36:03 +02001208 "because all window is stalled.\n",
1209 tbf->dir.dl.v_a);
1210 /* If V(S) == V(A) and finished state, we would have received
1211 * acknowledgement of all transmitted block. In this case we
1212 * would have transmitted the final block, and received ack
1213 * from MS. But in this case we did not receive the final ack
1214 * indication from MS. This should never happen if MS works
1215 * correctly. */
1216 if (tbf->dir.dl.v_s == tbf->dir.dl.v_a) {
Andreas Eversberg0c9b50c2012-10-07 15:50:51 +02001217 LOGP(DRLCMACDL, LOGL_DEBUG, "- MS acked all blocks, "
1218 "so we re-transmit final block!\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +02001219 /* we just send final block again */
1220 index = ((tbf->dir.dl.v_s - 1) & mod_sns_half);
1221 goto tx_block;
1222 }
1223
1224 /* cycle through all unacked blocks */
1225 for (bsn = tbf->dir.dl.v_a; bsn != tbf->dir.dl.v_s;
1226 bsn = (bsn + 1) & mod_sns) {
1227 index = (bsn & mod_sns_half);
1228 if (tbf->dir.dl.v_b[index] == 'U') {
1229 /* mark to be re-send */
1230 tbf->dir.dl.v_b[index] = 'X';
1231 resend++;
1232 }
1233 }
1234 /* At this point there should be at leasst one unacked block
1235 * to be resent. If not, this is an software error. */
1236 if (resend == 0) {
1237 LOGP(DRLCMACDL, LOGL_ERROR, "Software error: "
1238 "There are no unacknowledged blocks, but V(A) "
1239 " != V(S). PLEASE FIX!\n");
1240 /* we just send final block again */
1241 index = ((tbf->dir.dl.v_s - 1) & mod_sns_half);
1242 goto tx_block;
1243 }
1244 goto do_resend;
1245 }
1246
1247 LOGP(DRLCMACDL, LOGL_DEBUG, "- Sending new block at BSN %d\n",
1248 tbf->dir.dl.v_s);
1249
1250 /* now we still have untransmitted LLC data, so we fill mac block */
1251 index = tbf->dir.dl.v_s & mod_sns_half;
1252 data = tbf->rlc_block[index];
Andreas Eversberg3b1332c2012-10-03 14:20:53 +02001253 if (tbf->cs == 0) {
Andreas Eversberg499ff412012-10-03 14:21:36 +02001254 tbf->cs = bts->initial_cs_dl;
Andreas Eversberg3b1332c2012-10-03 14:20:53 +02001255 if (tbf->cs < 1 || tbf->cs > 4)
1256 tbf->cs = 1;
Andreas Eversberge6228b32012-07-03 13:36:03 +02001257 }
Andreas Eversberg3b1332c2012-10-03 14:20:53 +02001258 block_length = gprs_rlcmac_cs[tbf->cs].block_length;
1259 block_data = gprs_rlcmac_cs[tbf->cs].block_data;
Andreas Eversberge6228b32012-07-03 13:36:03 +02001260 memset(data, 0x2b, block_data); /* spare bits will be left 0 */
1261 rh = (struct rlc_dl_header *)data;
1262 rh->pt = 0; /* Data Block */
1263 rh->rrbp = rh->s_p = 0; /* Polling, set later, if required */
1264 rh->usf = 7; /* will be set at scheduler */
1265 rh->pr = 0; /* FIXME: power reduction */
1266 rh->tfi = tbf->tfi; /* TFI */
1267 rh->fbi = 0; /* Final Block Indicator, set late, if true */
1268 rh->bsn = tbf->dir.dl.v_s; /* Block Sequence Number */
1269 rh->e = 0; /* Extension bit, maybe set later */
1270 e_pointer = data + 2; /* points to E of current chunk */
1271 data += 3;
1272 delimiter = data; /* where next length header would be stored */
1273 space = block_data - 3;
1274 while (1) {
1275 chunk = tbf->llc_length - tbf->llc_index;
1276 /* if chunk will exceed block limit */
1277 if (chunk > space) {
1278 LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d "
1279 "larger than space (%d) left in block: copy "
1280 "only remaining space, and we are done\n",
1281 chunk, space);
1282 /* block is filled, so there is no extension */
1283 *e_pointer |= 0x01;
1284 /* fill only space */
1285 memcpy(data, tbf->llc_frame + tbf->llc_index, space);
1286 /* incement index */
1287 tbf->llc_index += space;
1288 /* return data block as message */
1289 break;
1290 }
1291 /* if FINAL chunk would fit precisely in space left */
1292 if (chunk == space && llist_empty(&tbf->llc_queue)) {
1293 LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d "
1294 "would exactly fit into space (%d): because "
1295 "this is a final block, we don't add length "
1296 "header, and we are done\n", chunk, space);
Andreas Eversberg0e403092012-07-06 11:04:57 +02001297 LOGP(DRLCMACDL, LOGL_INFO, "Complete DL frame for "
1298 "TBF=%d that fits precisely in last block: "
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001299 "len=%d\n", tbf->tfi, tbf->llc_length);
Andreas Eversberg050ace22013-03-16 16:22:02 +01001300 gprs_rlcmac_dl_bw(tbf, tbf->llc_length);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001301 /* block is filled, so there is no extension */
1302 *e_pointer |= 0x01;
1303 /* fill space */
1304 memcpy(data, tbf->llc_frame + tbf->llc_index, space);
1305 /* reset LLC frame */
1306 tbf->llc_index = tbf->llc_length = 0;
1307 /* final block */
1308 rh->fbi = 1; /* we indicate final block */
1309 tbf_new_state(tbf, GPRS_RLCMAC_FINISHED);
1310 /* return data block as message */
1311 break;
1312 }
1313 /* if chunk would fit exactly in space left */
1314 if (chunk == space) {
1315 LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d "
1316 "would exactly fit into space (%d): add length "
1317 "header with LI=0, to make frame extend to "
1318 "next block, and we are done\n", chunk, space);
1319 /* make space for delimiter */
1320 if (delimiter != data)
1321 memcpy(delimiter + 1, delimiter,
1322 data - delimiter);
1323 data++;
1324 space--;
1325 /* add LI with 0 length */
1326 li = (struct rlc_li_field *)delimiter;
1327 li->e = 1; /* not more extension */
1328 li->m = 0; /* shall be set to 0, in case of li = 0 */
1329 li->li = 0; /* chunk fills the complete space */
1330 // no need to set e_pointer nor increase delimiter
1331 /* fill only space, which is 1 octet less than chunk */
1332 memcpy(data, tbf->llc_frame + tbf->llc_index, space);
1333 /* incement index */
1334 tbf->llc_index += space;
1335 /* return data block as message */
1336 break;
1337 }
1338 LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d is less "
1339 "than remaining space (%d): add length header to "
1340 "to delimit LLC frame\n", chunk, space);
1341 /* the LLC frame chunk ends in this block */
1342 /* make space for delimiter */
1343 if (delimiter != data)
1344 memcpy(delimiter + 1, delimiter, data - delimiter);
1345 data++;
1346 space--;
1347 /* add LI to delimit frame */
1348 li = (struct rlc_li_field *)delimiter;
1349 li->e = 0; /* Extension bit, maybe set later */
1350 li->m = 0; /* will be set later, if there is more LLC data */
1351 li->li = chunk; /* length of chunk */
1352 e_pointer = delimiter; /* points to E of current delimiter */
1353 delimiter++;
1354 /* copy (rest of) LLC frame to space */
1355 memcpy(data, tbf->llc_frame + tbf->llc_index, chunk);
1356 data += chunk;
1357 space -= chunk;
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001358 LOGP(DRLCMACDL, LOGL_INFO, "Complete DL frame for TBF=%d: "
1359 "len=%d\n", tbf->tfi, tbf->llc_length);
Andreas Eversberg050ace22013-03-16 16:22:02 +01001360 gprs_rlcmac_dl_bw(tbf, tbf->llc_length);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001361 /* reset LLC frame */
1362 tbf->llc_index = tbf->llc_length = 0;
1363 /* dequeue next LLC frame, if any */
Andreas Eversberg24131bf2012-07-21 11:09:58 +02001364 msg = llc_dequeue(tbf);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001365 if (msg) {
Andreas Eversberg0e403092012-07-06 11:04:57 +02001366 LOGP(DRLCMACDL, LOGL_INFO, "- Dequeue next LLC for "
1367 "TBF=%d (len=%d)\n", tbf->tfi, msg->len);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001368 memcpy(tbf->llc_frame, msg->data, msg->len);
1369 tbf->llc_length = msg->len;
1370 msgb_free(msg);
1371 }
1372 /* if we have more data and we have space left */
1373 if (space > 0 && tbf->llc_length) {
1374 li->m = 1; /* we indicate more frames to follow */
1375 continue;
1376 }
1377 /* if we don't have more LLC frames */
1378 if (!tbf->llc_length) {
Andreas Eversberg0e403092012-07-06 11:04:57 +02001379 LOGP(DRLCMACDL, LOGL_DEBUG, "-- Final block, so we "
Andreas Eversberge6228b32012-07-03 13:36:03 +02001380 "done.\n");
1381 li->e = 1; /* we cannot extend */
1382 rh->fbi = 1; /* we indicate final block */
Andreas Eversberg5f14bd92012-10-03 14:20:26 +02001383 first_fin_ack = 1;
Andreas Eversbergf54a89e2012-07-16 11:56:11 +02001384 /* + 1 indicates: first final ack */
Andreas Eversberge6228b32012-07-03 13:36:03 +02001385 tbf_new_state(tbf, GPRS_RLCMAC_FINISHED);
1386 break;
1387 }
1388 /* we have no space left */
Andreas Eversberg0e403092012-07-06 11:04:57 +02001389 LOGP(DRLCMACDL, LOGL_DEBUG, "-- No space left, so we are "
Andreas Eversberge6228b32012-07-03 13:36:03 +02001390 "done.\n");
1391 li->e = 1; /* we cannot extend */
1392 break;
1393 }
1394 LOGP(DRLCMACDL, LOGL_DEBUG, "data block: %s\n",
1395 osmo_hexdump(tbf->rlc_block[index], block_length));
1396 tbf->rlc_block_len[index] = block_length;
1397 /* raise send state and set ack state array */
1398 tbf->dir.dl.v_b[index] = 'U'; /* unacked */
1399 tbf->dir.dl.v_s = (tbf->dir.dl.v_s + 1) & mod_sns; /* inc send state */
1400
1401tx_block:
1402 /* from this point on, new block is sent or old block is resent */
1403
1404 /* get data and header from current block */
1405 data = tbf->rlc_block[index];
1406 len = tbf->rlc_block_len[index];
1407 rh = (struct rlc_dl_header *)data;
1408
Andreas Eversberge6228b32012-07-03 13:36:03 +02001409 /* Clear Polling, if still set in history buffer */
1410 rh->s_p = 0;
1411
Andreas Eversbergf54a89e2012-07-16 11:56:11 +02001412 /* poll after POLL_ACK_AFTER_FRAMES frames, or when final block is tx.
1413 */
Andreas Eversberg5f14bd92012-10-03 14:20:26 +02001414 if (tbf->dir.dl.tx_counter >= POLL_ACK_AFTER_FRAMES || first_fin_ack) {
1415 if (first_fin_ack) {
Andreas Eversberge6228b32012-07-03 13:36:03 +02001416 LOGP(DRLCMACDL, LOGL_DEBUG, "- Scheduling Ack/Nack "
Andreas Eversberg5f14bd92012-10-03 14:20:26 +02001417 "polling, because first final block sent.\n");
Andreas Eversberg5e043da2012-07-15 06:51:30 +02001418 } else {
Andreas Eversberge6228b32012-07-03 13:36:03 +02001419 LOGP(DRLCMACDL, LOGL_DEBUG, "- Scheduling Ack/Nack "
1420 "polling, because %d blocks sent.\n",
Andreas Eversbergf54a89e2012-07-16 11:56:11 +02001421 POLL_ACK_AFTER_FRAMES);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001422 }
Andreas Eversberg5e043da2012-07-15 06:51:30 +02001423 /* scheduling not possible, because: */
Andreas Eversberge6228b32012-07-03 13:36:03 +02001424 if (tbf->poll_state != GPRS_RLCMAC_POLL_NONE)
Andreas Eversberg5e043da2012-07-15 06:51:30 +02001425 LOGP(DRLCMAC, LOGL_DEBUG, "Polling is already "
Andreas Eversberge6228b32012-07-03 13:36:03 +02001426 "sheduled for TBF=%d, so we must wait for "
1427 "requesting downlink ack\n", tbf->tfi);
Andreas Eversberg5e043da2012-07-15 06:51:30 +02001428 else if (tbf->control_ts != ts)
1429 LOGP(DRLCMAC, LOGL_DEBUG, "Polling cannot be "
1430 "sheduled in this TS %d, waiting for "
1431 "TS %d\n", ts, tbf->control_ts);
Holger Hans Peter Freyther96efa702013-09-29 07:44:39 +02001432 else if (sba_find(tbf->trx_no, ts, (fn + 13) % 2715648))
Andreas Eversberg07e97cf2012-08-07 16:00:56 +02001433 LOGP(DRLCMAC, LOGL_DEBUG, "Polling cannot be "
1434 "sheduled, because single block alllocation "
1435 "already exists\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +02001436 else {
Andreas Eversbergee31b782012-07-15 16:27:01 +02001437 LOGP(DRLCMAC, LOGL_DEBUG, "Polling sheduled in this "
1438 "TS %d\n", ts);
Andreas Eversberg5f14bd92012-10-03 14:20:26 +02001439 tbf->dir.dl.tx_counter = 0;
Andreas Eversberge6228b32012-07-03 13:36:03 +02001440 /* start timer whenever we send the final block */
1441 if (rh->fbi == 1)
Andreas Eversbergdfa563c2012-07-06 08:13:59 +02001442 tbf_timer_start(tbf, 3191, bts->t3191, 0);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001443
1444 /* schedule polling */
1445 tbf->poll_state = GPRS_RLCMAC_POLL_SCHED;
1446 tbf->poll_fn = (fn + 13) % 2715648;
1447
Andreas Eversbergb83e2a72012-10-07 15:26:00 +02001448#ifdef DEBUG_DIAGRAM
1449 debug_diagram(tbf->diag, "poll DL-ACK");
1450 if (first_fin_ack)
1451 debug_diagram(tbf->diag, "(is first FINAL)");
1452 if (rh->fbi)
1453 debug_diagram(tbf->diag, "(FBI is set)");
1454#endif
1455
Andreas Eversberge6228b32012-07-03 13:36:03 +02001456 /* set polling in header */
1457 rh->rrbp = 0; /* N+13 */
1458 rh->s_p = 1; /* Polling */
Andreas Eversberg5e043da2012-07-15 06:51:30 +02001459
1460 /* Increment TX-counter */
1461 tbf->dir.dl.tx_counter++;
Andreas Eversberge6228b32012-07-03 13:36:03 +02001462 }
Andreas Eversberg5e043da2012-07-15 06:51:30 +02001463 } else {
1464 /* Increment TX-counter */
1465 tbf->dir.dl.tx_counter++;
Andreas Eversberge6228b32012-07-03 13:36:03 +02001466 }
1467
1468 /* return data block as message */
1469 dl_msg = msgb_alloc(len, "rlcmac_dl_data");
1470 if (!dl_msg)
1471 return NULL;
1472 memcpy(msgb_put(dl_msg, len), data, len);
1473
1474 return dl_msg;
1475}
1476
Holger Hans Peter Freyther344ff482013-10-17 12:01:04 +02001477int gprs_rlcmac_downlink_ack(struct gprs_rlcmac_bts *bts,
1478 struct gprs_rlcmac_tbf *tbf, uint8_t final,
Andreas Eversberge6228b32012-07-03 13:36:03 +02001479 uint8_t ssn, uint8_t *rbb)
1480{
1481 char show_rbb[65], show_v_b[RLC_MAX_SNS + 1];
1482 uint16_t mod_sns = tbf->sns - 1;
1483 uint16_t mod_sns_half = (tbf->sns >> 1) - 1;
1484 int i; /* must be signed */
1485 int16_t dist; /* must be signed */
1486 uint8_t bit;
1487 uint16_t bsn;
1488 struct msgb *msg;
Andreas Eversberg050ace22013-03-16 16:22:02 +01001489 uint16_t lost = 0, received = 0;
Andreas Eversberge6228b32012-07-03 13:36:03 +02001490
Andreas Eversberg0e403092012-07-06 11:04:57 +02001491 LOGP(DRLCMACDL, LOGL_DEBUG, "TBF=%d downlink acknowledge\n",
Andreas Eversberge6228b32012-07-03 13:36:03 +02001492 tbf->tfi);
1493
1494 if (!final) {
1495 /* show received array in debug (bit 64..1) */
1496 for (i = 63; i >= 0; i--) {
1497 bit = (rbb[i >> 3] >> (7 - (i&7))) & 1;
1498 show_rbb[i] = (bit) ? '1' : 'o';
1499 }
1500 show_rbb[64] = '\0';
1501 LOGP(DRLCMACDL, LOGL_DEBUG, "- ack: (BSN=%d)\"%s\""
Andreas Eversberg4b470ff2012-07-16 12:02:40 +02001502 "(BSN=%d) 1=ACK o=NACK\n", (ssn - 64) & mod_sns,
1503 show_rbb, (ssn - 1) & mod_sns);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001504
1505 /* apply received array to receive state (SSN-64..SSN-1) */
1506 /* calculate distance of ssn from V(S) */
1507 dist = (tbf->dir.dl.v_s - ssn) & mod_sns;
1508 /* check if distance is less than distance V(A)..V(S) */
Andreas Eversberg050ace22013-03-16 16:22:02 +01001509 if (dist >= ((tbf->dir.dl.v_s - tbf->dir.dl.v_a) & mod_sns)) {
Andreas Eversberg0f13c402012-07-16 11:59:23 +02001510 /* this might happpen, if the downlink assignment
1511 * was not received by ms and the ack refers
1512 * to previous TBF
1513 * FIXME: we should implement polling for
1514 * control ack!*/
1515 LOGP(DRLCMACDL, LOGL_NOTICE, "- ack range is out of "
1516 "V(A)..V(S) range (DL TBF=%d) Free TFB!\n",
1517 tbf->tfi);
1518 return 1; /* indicate to free TBF */
Andreas Eversberge6228b32012-07-03 13:36:03 +02001519 }
Andreas Eversberg050ace22013-03-16 16:22:02 +01001520 /* SSN - 1 is in range V(A)..V(S)-1 */
1521 for (i = 63, bsn = (ssn - 1) & mod_sns;
1522 i >= 0 && bsn != ((tbf->dir.dl.v_a - 1) & mod_sns);
1523 i--, bsn = (bsn - 1) & mod_sns) {
1524 bit = (rbb[i >> 3] >> (7 - (i&7))) & 1;
1525 if (bit) {
1526 LOGP(DRLCMACDL, LOGL_DEBUG, "- got "
1527 "ack for BSN=%d\n", bsn);
1528 if (tbf->dir.dl.v_b[bsn & mod_sns_half]
1529 != 'A')
1530 received++;
1531 tbf->dir.dl.v_b[bsn & mod_sns_half] = 'A';
1532 } else {
1533 LOGP(DRLCMACDL, LOGL_DEBUG, "- got "
1534 "NACK for BSN=%d\n", bsn);
1535 tbf->dir.dl.v_b[bsn & mod_sns_half] = 'N';
1536 lost++;
1537 }
1538 }
1539 /* report lost and received packets */
1540 gprs_rlcmac_received_lost(tbf, received, lost);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001541
1542 /* raise V(A), if possible */
1543 for (i = 0, bsn = tbf->dir.dl.v_a; bsn != tbf->dir.dl.v_s;
1544 i++, bsn = (bsn + 1) & mod_sns) {
1545 if (tbf->dir.dl.v_b[bsn & mod_sns_half] == 'A') {
1546 tbf->dir.dl.v_b[bsn & mod_sns_half] = 'I';
1547 /* mark invalid */
1548 tbf->dir.dl.v_a = (tbf->dir.dl.v_a + 1)
1549 & mod_sns;
1550 } else
1551 break;
1552 }
1553
1554 /* show receive state array in debug (V(A)..V(S)-1) */
1555 for (i = 0, bsn = tbf->dir.dl.v_a; bsn != tbf->dir.dl.v_s;
1556 i++, bsn = (bsn + 1) & mod_sns) {
1557 show_v_b[i] = tbf->dir.dl.v_b[bsn & mod_sns_half];
1558 if (show_v_b[i] == 0)
1559 show_v_b[i] = ' ';
1560 }
1561 show_v_b[i] = '\0';
1562 LOGP(DRLCMACDL, LOGL_DEBUG, "- V(B): (V(A)=%d)\"%s\""
1563 "(V(S)-1=%d) A=Acked N=Nacked U=Unacked "
1564 "X=Resend-Unacked\n", tbf->dir.dl.v_a, show_v_b,
1565 (tbf->dir.dl.v_s - 1) & mod_sns);
1566
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +02001567 if (tbf->state_is(GPRS_RLCMAC_FINISHED)
Andreas Eversberg6664a902012-07-15 06:52:19 +02001568 && tbf->dir.dl.v_s == tbf->dir.dl.v_a) {
Andreas Eversberg0c9b50c2012-10-07 15:50:51 +02001569 LOGP(DRLCMACDL, LOGL_NOTICE, "Received acknowledge of "
1570 "all blocks, but without final ack "
1571 "inidcation (don't worry)\n");
1572 }
1573 return 0;
Andreas Eversbergb83e2a72012-10-07 15:26:00 +02001574 }
Andreas Eversberge6228b32012-07-03 13:36:03 +02001575
Andreas Eversberg0c9b50c2012-10-07 15:50:51 +02001576 LOGP(DRLCMACDL, LOGL_DEBUG, "- Final ACK received.\n");
1577 debug_diagram(tbf->diag, "got Final ACK");
Andreas Eversberg050ace22013-03-16 16:22:02 +01001578 /* range V(A)..V(S)-1 */
1579 for (bsn = tbf->dir.dl.v_a; bsn != tbf->dir.dl.v_s;
1580 bsn = (bsn + 1) & mod_sns) {
1581 if (tbf->dir.dl.v_b[bsn & mod_sns_half] != 'A')
1582 received++;
1583 }
1584
1585 /* report all outstanding packets as received */
1586 gprs_rlcmac_received_lost(tbf, received, lost);
Andreas Eversberg0c9b50c2012-10-07 15:50:51 +02001587
Andreas Eversberge6228b32012-07-03 13:36:03 +02001588 /* check for LLC PDU in the LLC Queue */
Andreas Eversberg24131bf2012-07-21 11:09:58 +02001589 msg = llc_dequeue(tbf);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001590 if (!msg) {
Andreas Eversberge6228b32012-07-03 13:36:03 +02001591 /* no message, start T3193, change state to RELEASE */
1592 LOGP(DRLCMACDL, LOGL_DEBUG, "- No new message, so we "
1593 "release.\n");
Andreas Eversbergb3c6f6c2012-07-06 07:40:08 +02001594 /* start T3193 */
Andreas Eversbergb83e2a72012-10-07 15:26:00 +02001595 debug_diagram(tbf->diag, "start T3193");
Andreas Eversbergdfa563c2012-07-06 08:13:59 +02001596 tbf_timer_start(tbf, 3193, bts->t3193_msec / 1000,
Andreas Eversbergdf4d20e2012-09-24 13:49:38 +02001597 (bts->t3193_msec % 1000) * 1000);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001598 tbf_new_state(tbf, GPRS_RLCMAC_WAIT_RELEASE);
1599
1600 return 0;
1601 }
1602 memcpy(tbf->llc_frame, msg->data, msg->len);
1603 tbf->llc_length = msg->len;
1604 msgb_free(msg);
1605
1606 /* we have a message, so we trigger downlink assignment, and there
1607 * set the state to ASSIGN. also we set old_downlink, because we
1608 * re-use this tbf. */
1609 LOGP(DRLCMAC, LOGL_DEBUG, "Trigger dowlink assignment on PACCH, "
1610 "because another LLC PDU has arrived in between\n");
1611 memset(&tbf->dir.dl, 0, sizeof(tbf->dir.dl)); /* reset RLC states */
Andreas Eversberga9be1542012-09-27 09:23:24 +02001612 tbf->state_flags &= GPRS_RLCMAC_FLAG_TO_MASK; /* keep TO flags */
1613 tbf->state_flags &= ~(1 << GPRS_RLCMAC_FLAG_CCCH);
Holger Hans Peter Freyther1b333612013-10-17 18:26:33 +02001614 tbf_update(bts, tbf);
Holger Hans Peter Freyther344ff482013-10-17 12:01:04 +02001615 gprs_rlcmac_trigger_downlink_assignment(bts, tbf, tbf, NULL);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001616
1617 return 0;
1618}
1619
1620
1621struct msgb *gprs_rlcmac_send_packet_downlink_assignment(
Holger Hans Peter Freyther9f521cd2013-10-17 13:48:11 +02001622 struct gprs_rlcmac_bts *bts,
Andreas Eversberge6228b32012-07-03 13:36:03 +02001623 struct gprs_rlcmac_tbf *tbf, uint32_t fn)
1624{
1625 struct msgb *msg;
1626 struct gprs_rlcmac_tbf *new_tbf;
Andreas Eversberg802bb6e2012-08-06 11:15:05 +02001627 int poll_ass_dl = POLLING_ASSIGNMENT_DL;
Andreas Eversberge6228b32012-07-03 13:36:03 +02001628
Andreas Eversberg802bb6e2012-08-06 11:15:05 +02001629 if (poll_ass_dl && tbf->direction == GPRS_RLCMAC_DL_TBF
1630 && tbf->control_ts != tbf->first_common_ts) {
1631 LOGP(DRLCMAC, LOGL_NOTICE, "Cannot poll for downlink "
Andreas Eversbergf01929b2012-10-08 12:40:49 +02001632 "assigment, because MS cannot reply. (control TS=%d, "
1633 "first common TS=%d)\n", tbf->control_ts,
1634 tbf->first_common_ts);
Andreas Eversberg802bb6e2012-08-06 11:15:05 +02001635 poll_ass_dl = 0;
Andreas Eversberge6228b32012-07-03 13:36:03 +02001636 }
Andreas Eversberg802bb6e2012-08-06 11:15:05 +02001637 if (poll_ass_dl) {
1638 if (tbf->poll_state != GPRS_RLCMAC_POLL_NONE) {
1639 LOGP(DRLCMAC, LOGL_DEBUG, "Polling is already sheduled "
1640 "for TBF=%d, so we must wait for downlink "
1641 "assignment...\n", tbf->tfi);
1642 return NULL;
1643 }
Holger Hans Peter Freyther96efa702013-09-29 07:44:39 +02001644 if (sba_find(tbf->trx_no, tbf->control_ts, (fn + 13) % 2715648)) {
Andreas Eversberg07e97cf2012-08-07 16:00:56 +02001645 LOGP(DRLCMACUL, LOGL_DEBUG, "Polling is already "
1646 "scheduled for single block allocation...\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +02001647 return NULL;
Andreas Eversberg07e97cf2012-08-07 16:00:56 +02001648 }
Andreas Eversberge6228b32012-07-03 13:36:03 +02001649 }
1650
1651 /* on uplink TBF we get the downlink TBF to be assigned. */
Andreas Eversbergee31b782012-07-15 16:27:01 +02001652 if (tbf->direction == GPRS_RLCMAC_UL_TBF) {
1653 /* be sure to check first, if contention resolution is done,
1654 * otherwise we cannot send the assignment yet */
Andreas Eversberg08e93cd2012-07-26 08:13:06 +02001655 if (!tbf->dir.ul.contention_resolution_done) {
Andreas Eversberg7f5352c2012-07-23 18:20:36 +02001656 LOGP(DRLCMAC, LOGL_DEBUG, "Cannot assign DL TBF now, "
Andreas Eversbergee31b782012-07-15 16:27:01 +02001657 "because contention resolution is not "
1658 "finished.\n");
1659 return NULL;
1660 }
Andreas Eversberge6228b32012-07-03 13:36:03 +02001661 new_tbf = tbf_by_tlli(tbf->tlli, GPRS_RLCMAC_DL_TBF);
Andreas Eversbergee31b782012-07-15 16:27:01 +02001662 } else
Andreas Eversberge6228b32012-07-03 13:36:03 +02001663 new_tbf = tbf;
1664 if (!new_tbf) {
1665 LOGP(DRLCMACDL, LOGL_ERROR, "We have a schedule for downlink "
1666 "assignment at uplink TBF=%d, but there is no downlink "
1667 "TBF\n", tbf->tfi);
1668 tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE;
1669 return NULL;
1670 }
1671
1672 msg = msgb_alloc(23, "rlcmac_dl_ass");
1673 if (!msg)
1674 return NULL;
1675 bitvec *ass_vec = bitvec_alloc(23);
1676 if (!ass_vec) {
1677 msgb_free(msg);
1678 return NULL;
1679 }
1680 bitvec_unhex(ass_vec,
1681 "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
Andreas Eversberg0e403092012-07-06 11:04:57 +02001682 LOGP(DRLCMAC, LOGL_INFO, "TBF: START TFI: %u TLLI: 0x%08x Packet Downlink Assignment (PACCH)\n", new_tbf->tfi, new_tbf->tlli);
Andreas Eversberg6681bb82012-07-25 08:48:44 +02001683 RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)talloc_zero(tall_pcu_ctx, RlcMacDownlink_t);
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001684 write_packet_downlink_assignment(mac_control_block, tbf->tfi,
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001685 (tbf->direction == GPRS_RLCMAC_DL_TBF), new_tbf,
Andreas Eversbergafdd9e12012-10-07 17:08:55 +02001686 poll_ass_dl, bts->alpha, bts->gamma, -1, 0);
Andreas Eversberg0e403092012-07-06 11:04:57 +02001687 LOGP(DRLCMAC, LOGL_DEBUG, "+++++++++++++++++++++++++ TX : Packet Downlink Assignment +++++++++++++++++++++++++\n");
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001688 encode_gsm_rlcmac_downlink(ass_vec, mac_control_block);
Andreas Eversberg0e403092012-07-06 11:04:57 +02001689 LOGPC(DCSN1, LOGL_NOTICE, "\n");
1690 LOGP(DRLCMAC, LOGL_DEBUG, "------------------------- TX : Packet Downlink Assignment -------------------------\n");
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001691 bitvec_pack(ass_vec, msgb_put(msg, 23));
Andreas Eversberge6228b32012-07-03 13:36:03 +02001692 bitvec_free(ass_vec);
Andreas Eversberg6681bb82012-07-25 08:48:44 +02001693 talloc_free(mac_control_block);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001694
Andreas Eversberg802bb6e2012-08-06 11:15:05 +02001695 if (poll_ass_dl) {
1696 tbf->poll_state = GPRS_RLCMAC_POLL_SCHED;
1697 tbf->poll_fn = (fn + 13) % 2715648;
1698 tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_WAIT_ACK;
1699 } else {
1700 tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE;
1701 tbf_new_state(new_tbf, GPRS_RLCMAC_FLOW);
1702 tbf_assign_control_ts(new_tbf);
Andreas Eversbergcbcd1242012-08-07 15:48:21 +02001703 /* stop pending assignment timer */
1704 tbf_timer_stop(new_tbf);
1705
Andreas Eversberg802bb6e2012-08-06 11:15:05 +02001706 }
Andreas Eversbergb83e2a72012-10-07 15:26:00 +02001707 debug_diagram(tbf->diag, "send DL-ASS");
Andreas Eversberge6228b32012-07-03 13:36:03 +02001708
1709 return msg;
1710}
1711
Holger Hans Peter Freyther344ff482013-10-17 12:01:04 +02001712static void gprs_rlcmac_downlink_assignment(struct gprs_rlcmac_bts *bts,
1713 gprs_rlcmac_tbf *tbf, uint8_t poll,
Holger Hans Peter Freyther52c911b2013-08-24 18:30:54 +02001714 const char *imsi)
Andreas Eversberge6228b32012-07-03 13:36:03 +02001715{
Andreas Eversbergaafcbbb2012-09-27 09:20:45 +02001716 int plen;
1717
Andreas Eversbergb83e2a72012-10-07 15:26:00 +02001718 debug_diagram(tbf->diag, "IMM.ASS (PCH)");
Andreas Eversberge13fa2d2012-07-09 17:10:44 +02001719 LOGP(DRLCMAC, LOGL_INFO, "TX: START TFI: %u TLLI: 0x%08x Immediate Assignment Downlink (PCH)\n", tbf->tfi, tbf->tlli);
Andreas Eversberg7b045012012-07-05 07:38:49 +02001720 bitvec *immediate_assignment = bitvec_alloc(22); /* without plen */
1721 bitvec_unhex(immediate_assignment, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
Andreas Eversberge6228b32012-07-03 13:36:03 +02001722 /* use request reference that has maximum distance to current time,
1723 * so the assignment will not conflict with possible RACH requests. */
Holger Hans Peter Freytheree7a5352013-10-17 15:41:36 +02001724 plen = write_immediate_assignment(bts, immediate_assignment, 1, 125,
Andreas Eversbergaafcbbb2012-09-27 09:20:45 +02001725 (tbf->pdch[tbf->first_ts]->last_rts_fn + 21216) % 2715648, tbf->ta,
1726 tbf->arfcn, tbf->first_ts, tbf->tsc, tbf->tfi, 0, tbf->tlli, poll,
Andreas Eversbergafdd9e12012-10-07 17:08:55 +02001727 tbf->poll_fn, 0, bts->alpha, bts->gamma, -1);
Andreas Eversberge13fa2d2012-07-09 17:10:44 +02001728 pcu_l1if_tx_pch(immediate_assignment, plen, imsi);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001729 bitvec_free(immediate_assignment);
1730}
1731
1732/* depending on the current TBF, we assign on PACCH or AGCH */
Holger Hans Peter Freyther344ff482013-10-17 12:01:04 +02001733void gprs_rlcmac_trigger_downlink_assignment(struct gprs_rlcmac_bts *bts,
1734 struct gprs_rlcmac_tbf *tbf,
Holger Hans Peter Freyther52c911b2013-08-24 18:30:54 +02001735 struct gprs_rlcmac_tbf *old_tbf, const char *imsi)
Andreas Eversberge6228b32012-07-03 13:36:03 +02001736{
Andreas Eversberge6228b32012-07-03 13:36:03 +02001737#ifdef DEBUG_DL_ASS_IDLE
Andreas Eversberge13fa2d2012-07-09 17:10:44 +02001738 strncpy(debug_imsi, imsi);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001739 LOGP(DRLCMAC, LOGL_ERROR, "**** DEBUGGING DOWNLINK ASSIGNMENT ****\n");
1740#endif
1741
1742 /* stop pending timer */
1743 tbf_timer_stop(tbf);
1744
1745 /* check for downlink tbf: */
Andreas Eversberge6228b32012-07-03 13:36:03 +02001746 if (old_tbf) {
1747#ifdef DEBUG_DL_ASS_IDLE
1748 LOGP(DRLCMAC, LOGL_ERROR, "We must wait for current TBF to be "
1749 "released.\n");
1750 /* wait one second until assignment */
1751 tbf_timer_start(tbf, 1234, 1,0);
1752#else
Andreas Eversberg0e403092012-07-06 11:04:57 +02001753 LOGP(DRLCMAC, LOGL_DEBUG, "Send dowlink assignment on "
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001754 "PACCH, because %s TBF=%d exists for TLLI=0x%08x\n",
Andreas Eversberg7f5352c2012-07-23 18:20:36 +02001755 (old_tbf->direction == GPRS_RLCMAC_UL_TBF)
1756 ? "UL" : "DL", old_tbf->tfi, old_tbf->tlli);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001757 old_tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_SEND_ASS;
1758 /* use TA from old TBF */
1759 tbf->ta = old_tbf->ta;
1760 /* change state */
1761 tbf_new_state(tbf, GPRS_RLCMAC_ASSIGN);
Andreas Eversberg14db19e2012-08-06 15:03:03 +02001762 tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_PACCH);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001763 /* start timer */
1764 tbf_timer_start(tbf, 0, Tassign_pacch);
1765#endif
1766 } else {
Andreas Eversberge13fa2d2012-07-09 17:10:44 +02001767 LOGP(DRLCMAC, LOGL_DEBUG, "Send dowlink assignment for TBF=%d on PCH, no TBF exist (IMSI=%s)\n", tbf->tfi, imsi);
1768 if (!imsi || strlen(imsi) < 3) {
1769 LOGP(DRLCMAC, LOGL_ERROR, "No valid IMSI!\n");
1770 return;
1771 }
Andreas Eversberge6228b32012-07-03 13:36:03 +02001772 /* change state */
1773 tbf_new_state(tbf, GPRS_RLCMAC_ASSIGN);
Andreas Eversberg14db19e2012-08-06 15:03:03 +02001774 tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_CCCH);
Andreas Eversberga9be1542012-09-27 09:23:24 +02001775 strncpy(tbf->dir.dl.imsi, imsi, sizeof(tbf->dir.dl.imsi));
Andreas Eversberg7438df72012-07-23 18:04:49 +02001776 /* send immediate assignment */
Holger Hans Peter Freyther344ff482013-10-17 12:01:04 +02001777 gprs_rlcmac_downlink_assignment(bts, tbf, 0, imsi);
Andreas Eversberga9be1542012-09-27 09:23:24 +02001778 tbf->dir.dl.wait_confirm = 1;
1779 }
1780}
1781
1782int gprs_rlcmac_imm_ass_cnf(uint8_t *data, uint32_t fn)
1783{
1784 struct gprs_rlcmac_tbf *tbf;
1785 uint8_t plen;
1786 uint32_t tlli;
1787
1788 /* move to IA Rest Octets */
1789 plen = data[0] >> 2;
1790 data += 1 + plen;
1791
1792 if ((*data & 0xf0) != 0xd0) {
1793 LOGP(DRLCMAC, LOGL_ERROR, "Got IMM.ASS confirm, but rest "
1794 "octets do not start with bit sequence 'HH01' "
1795 "(Packet Downlink Assignment)\n");
1796 return -EINVAL;
1797 }
1798
1799 /* get TLLI from downlink assignment */
1800 tlli = (*data++) << 28;
1801 tlli |= (*data++) << 20;
1802 tlli |= (*data++) << 12;
1803 tlli |= (*data++) << 4;
1804 tlli |= (*data++) >> 4;
1805
1806 tbf = tbf_by_tlli(tlli, GPRS_RLCMAC_DL_TBF);
1807 if (!tbf) {
1808 LOGP(DRLCMAC, LOGL_ERROR, "Got IMM.ASS confirm, but TLLI=%08x "
1809 "does not exit\n", tlli);
1810 return -EINVAL;
1811 }
1812
1813 LOGP(DRLCMAC, LOGL_DEBUG, "Got IMM.ASS confirm for TLLI=%08x\n", tlli);
1814
1815 if (tbf->dir.dl.wait_confirm) {
Andreas Eversberge6228b32012-07-03 13:36:03 +02001816 tbf_timer_start(tbf, 0, Tassign_agch);
1817 }
Andreas Eversberga9be1542012-09-27 09:23:24 +02001818
1819 return 0;
1820}
Andreas Eversberge6228b32012-07-03 13:36:03 +02001821