blob: f2887b2a8dd2defb69cb8c510933d3afaf372491 [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 Freyther63f29d62013-10-19 19:04:03 +020025#include <encoding.h>
Holger Hans Peter Freyther86921282013-08-24 21:26:42 +020026#include <tbf.h>
Holger Hans Peter Freytherd11290b2013-10-26 17:32:04 +020027#include <rlc.h>
Andreas Eversberg66690dd2012-06-27 15:44:31 +020028
Holger Hans Peter Freyther7ce21eb2013-10-20 08:28:25 +020029static struct gprs_rlcmac_cs gprs_rlcmac_cs[] = {
30/* frame length data block max payload */
31 { 0, 0, 0 },
32 { 23, 23, 20 }, /* CS-1 */
33 { 34, 33, 30 }, /* CS-2 */
34 { 40, 39, 36 }, /* CS-3 */
35 { 54, 53, 50 }, /* CS-4 */
36};
37
38
Andreas Eversberg6681bb82012-07-25 08:48:44 +020039extern void *tall_pcu_ctx;
Andreas Eversberg66690dd2012-06-27 15:44:31 +020040
Andreas Eversbergf54a89e2012-07-16 11:56:11 +020041/* After sending these frames, we poll for ack/nack. */
Andreas Eversberg5f14bd92012-10-03 14:20:26 +020042#define POLL_ACK_AFTER_FRAMES 20
Andreas Eversberg66690dd2012-06-27 15:44:31 +020043
Andreas Eversberg802bb6e2012-08-06 11:15:05 +020044/* If acknowledgement to uplink/downlink assignmentshould be polled */
45#define POLLING_ASSIGNMENT_DL 1
46#define POLLING_ASSIGNMENT_UL 1
Andreas Eversberge6228b32012-07-03 13:36:03 +020047
Andreas Eversberg66690dd2012-06-27 15:44:31 +020048
Holger Hans Peter Freytherb65e08a2013-10-20 17:10:25 +020049static void gprs_rlcmac_downlink_assignment(
Holger Hans Peter Freyther344ff482013-10-17 12:01:04 +020050 gprs_rlcmac_tbf *tbf, uint8_t poll,
Holger Hans Peter Freyther52c911b2013-08-24 18:30:54 +020051 const char *imsi);
Andreas Eversberga9be1542012-09-27 09:23:24 +020052
Andreas Eversberg14db19e2012-08-06 15:03:03 +020053static int gprs_rlcmac_diag(struct gprs_rlcmac_tbf *tbf)
54{
Holger Hans Peter Freyther7380bab2013-10-16 18:09:19 +020055 return tbf->rlcmac_diag();
Andreas Eversberg14db19e2012-08-06 15:03:03 +020056}
57
Holger Hans Peter Freyther344ff482013-10-17 12:01:04 +020058int gprs_rlcmac_poll_timeout(struct gprs_rlcmac_bts *bts, struct gprs_rlcmac_tbf *tbf)
Andreas Eversberge6228b32012-07-03 13:36:03 +020059{
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +020060 LOGP(DRLCMAC, LOGL_NOTICE, "Poll timeout for %s TBF=%d\n",
61 (tbf->direction == GPRS_RLCMAC_UL_TBF) ? "UL" : "DL", tbf->tfi);
Andreas Eversberge6228b32012-07-03 13:36:03 +020062
63 tbf->poll_state = GPRS_RLCMAC_POLL_NONE;
64
65 if (tbf->ul_ack_state == GPRS_RLCMAC_UL_ACK_WAIT_ACK) {
Andreas Eversberg14db19e2012-08-06 15:03:03 +020066 if (!(tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_TO_UL_ACK))) {
67 LOGP(DRLCMAC, LOGL_NOTICE, "- Timeout for polling "
68 "PACKET CONTROL ACK for PACKET UPLINK ACK\n");
69 gprs_rlcmac_diag(tbf);
70 tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_TO_UL_ACK);
71 }
Andreas Eversberge6228b32012-07-03 13:36:03 +020072 tbf->ul_ack_state = GPRS_RLCMAC_UL_ACK_NONE;
Holger Hans Peter Freyther34bd8bd2013-10-19 21:10:38 +020073 debug_diagram(bts->bts, tbf->diag, "timeout UL-ACK");
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +020074 if (tbf->state_is(GPRS_RLCMAC_FINISHED)) {
Andreas Eversberge6228b32012-07-03 13:36:03 +020075 tbf->dir.ul.n3103++;
Andreas Eversbergdfa563c2012-07-06 08:13:59 +020076 if (tbf->dir.ul.n3103 == bts->n3103) {
Andreas Eversberg4b470ff2012-07-16 12:02:40 +020077 LOGP(DRLCMAC, LOGL_NOTICE,
78 "- N3103 exceeded\n");
Holger Hans Peter Freyther34bd8bd2013-10-19 21:10:38 +020079 debug_diagram(bts->bts, tbf->diag, "N3103 exceeded");
Andreas Eversberge6228b32012-07-03 13:36:03 +020080 tbf_new_state(tbf, GPRS_RLCMAC_RELEASING);
Andreas Eversbergdfa563c2012-07-06 08:13:59 +020081 tbf_timer_start(tbf, 3169, bts->t3169, 0);
Andreas Eversberge6228b32012-07-03 13:36:03 +020082 return 0;
83 }
84 /* reschedule UL ack */
85 tbf->ul_ack_state = GPRS_RLCMAC_UL_ACK_SEND_ACK;
86 }
87 } else
88 if (tbf->ul_ass_state == GPRS_RLCMAC_UL_ASS_WAIT_ACK) {
Andreas Eversberg14db19e2012-08-06 15:03:03 +020089 if (!(tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_TO_UL_ASS))) {
90 LOGP(DRLCMAC, LOGL_NOTICE, "- Timeout for polling "
91 "PACKET CONTROL ACK for PACKET UPLINK "
92 "ASSIGNMENT.\n");
93 gprs_rlcmac_diag(tbf);
94 tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_TO_UL_ASS);
95 }
Andreas Eversberge6228b32012-07-03 13:36:03 +020096 tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_NONE;
Holger Hans Peter Freytherb65e08a2013-10-20 17:10:25 +020097 debug_diagram(tbf->bts, tbf->diag, "timeout UL-ASS");
Andreas Eversberg802bb6e2012-08-06 11:15:05 +020098 tbf->n3105++;
99 if (tbf->n3105 == bts->n3105) {
100 LOGP(DRLCMAC, LOGL_NOTICE, "- N3105 exceeded\n");
Holger Hans Peter Freyther34bd8bd2013-10-19 21:10:38 +0200101 debug_diagram(bts->bts, tbf->diag, "N3105 exceeded");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200102 tbf_new_state(tbf, GPRS_RLCMAC_RELEASING);
Andreas Eversbergdfa563c2012-07-06 08:13:59 +0200103 tbf_timer_start(tbf, 3195, bts->t3195, 0);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200104 return 0;
105 }
Andreas Eversberg802bb6e2012-08-06 11:15:05 +0200106 /* reschedule UL assignment */
107 tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200108 } else
109 if (tbf->dl_ass_state == GPRS_RLCMAC_DL_ASS_WAIT_ACK) {
Andreas Eversberg14db19e2012-08-06 15:03:03 +0200110 if (!(tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_TO_DL_ASS))) {
111 LOGP(DRLCMAC, LOGL_NOTICE, "- Timeout for polling "
112 "PACKET CONTROL ACK for PACKET DOWNLINK "
113 "ASSIGNMENT.\n");
114 gprs_rlcmac_diag(tbf);
115 tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_TO_DL_ASS);
116 }
Andreas Eversberge6228b32012-07-03 13:36:03 +0200117 tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE;
Holger Hans Peter Freyther34bd8bd2013-10-19 21:10:38 +0200118 debug_diagram(bts->bts, tbf->diag, "timeout DL-ASS");
Andreas Eversberg802bb6e2012-08-06 11:15:05 +0200119 tbf->n3105++;
120 if (tbf->n3105 == bts->n3105) {
121 LOGP(DRLCMAC, LOGL_NOTICE, "- N3105 exceeded\n");
Holger Hans Peter Freyther34bd8bd2013-10-19 21:10:38 +0200122 debug_diagram(bts->bts, tbf->diag, "N3105 exceeded");
Andreas Eversberg802bb6e2012-08-06 11:15:05 +0200123 tbf_new_state(tbf, GPRS_RLCMAC_RELEASING);
124 tbf_timer_start(tbf, 3195, bts->t3195, 0);
125 return 0;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200126 }
Andreas Eversberg802bb6e2012-08-06 11:15:05 +0200127 /* reschedule DL assignment */
128 tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_SEND_ASS;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200129 } else
Andreas Eversberg802bb6e2012-08-06 11:15:05 +0200130 if (tbf->direction == GPRS_RLCMAC_DL_TBF) {
Andreas Eversberg14db19e2012-08-06 15:03:03 +0200131 if (!(tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_TO_DL_ACK))) {
132 LOGP(DRLCMAC, LOGL_NOTICE, "- Timeout for polling "
133 "PACKET DOWNLINK ACK.\n");
134 gprs_rlcmac_diag(tbf);
135 tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_TO_DL_ACK);
136 }
Holger Hans Peter Freyther34bd8bd2013-10-19 21:10:38 +0200137 debug_diagram(bts->bts, tbf->diag, "timeout DL-ACK");
Andreas Eversberg802bb6e2012-08-06 11:15:05 +0200138 tbf->n3105++;
139 if (tbf->n3105 == bts->n3105) {
Andreas Eversberg4b470ff2012-07-16 12:02:40 +0200140 LOGP(DRLCMAC, LOGL_NOTICE, "- N3105 exceeded\n");
Holger Hans Peter Freyther34bd8bd2013-10-19 21:10:38 +0200141 debug_diagram(bts->bts, tbf->diag, "N3105 exceeded");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200142 tbf_new_state(tbf, GPRS_RLCMAC_RELEASING);
143 tbf_timer_start(tbf, 3195, bts->t3195, 0);
144 return 0;
145 }
Andreas Eversberga9be1542012-09-27 09:23:24 +0200146 /* resend IMM.ASS on CCCH on timeout */
147 if ((tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))
148 && !(tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_DL_ACK))) {
149 LOGP(DRLCMAC, LOGL_DEBUG, "Re-send dowlink assignment "
150 "for TBF=%d on PCH (IMSI=%s)\n", tbf->tfi,
151 tbf->dir.dl.imsi);
152 /* send immediate assignment */
Holger Hans Peter Freytherb65e08a2013-10-20 17:10:25 +0200153 gprs_rlcmac_downlink_assignment(tbf, 0, tbf->dir.dl.imsi);
Andreas Eversberga9be1542012-09-27 09:23:24 +0200154 tbf->dir.dl.wait_confirm = 1;
155 }
Andreas Eversberg4b470ff2012-07-16 12:02:40 +0200156 } else
157 LOGP(DRLCMAC, LOGL_ERROR, "- Poll Timeout, but no event!\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200158
159 return 0;
160}
161
Andreas Eversberg07e97cf2012-08-07 16:00:56 +0200162static uint8_t get_ms_class_by_capability(MS_Radio_Access_capability_t *cap)
163{
164 int i;
165
166 for (i = 0; i < cap->Count_MS_RA_capability_value; i++) {
167 if (!cap->MS_RA_capability_value[i].u.Content.Exist_Multislot_capability)
168 continue;
169 if (!cap->MS_RA_capability_value[i].u.Content.Multislot_capability.Exist_GPRS_multislot_class)
170 continue;
171 return cap->MS_RA_capability_value[i].u.Content.Multislot_capability.GPRS_multislot_class;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200172 }
173
174 return 0;
175}
176
177/* Received Uplink RLC control block. */
Holger Hans Peter Freyther8d7a6322013-10-17 15:23:49 +0200178int gprs_rlcmac_rcv_control_block(struct gprs_rlcmac_bts *bts,
179 bitvec *rlc_block, uint8_t trx, uint8_t ts,
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200180 uint32_t fn)
Andreas Eversberge6228b32012-07-03 13:36:03 +0200181{
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200182 int8_t tfi = 0; /* must be signed */
Andreas Eversberge6228b32012-07-03 13:36:03 +0200183 uint32_t tlli = 0;
184 struct gprs_rlcmac_tbf *tbf;
Andreas Eversberga004e6a2013-05-13 16:45:21 +0200185 struct gprs_rlcmac_sba *sba;
Andreas Eversberg0f13c402012-07-16 11:59:23 +0200186 int rc;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200187
Andreas Eversberg6681bb82012-07-25 08:48:44 +0200188 RlcMacUplink_t * ul_control_block = (RlcMacUplink_t *)talloc_zero(tall_pcu_ctx, RlcMacUplink_t);
Andreas Eversberg0e403092012-07-06 11:04:57 +0200189 LOGP(DRLCMAC, LOGL_DEBUG, "+++++++++++++++++++++++++ RX : Uplink Control Block +++++++++++++++++++++++++\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200190 decode_gsm_rlcmac_uplink(rlc_block, ul_control_block);
Andreas Eversberg0e403092012-07-06 11:04:57 +0200191 LOGPC(DCSN1, LOGL_NOTICE, "\n");
192 LOGP(DRLCMAC, LOGL_DEBUG, "------------------------- RX : Uplink Control Block -------------------------\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200193 switch (ul_control_block->u.MESSAGE_TYPE) {
194 case MT_PACKET_CONTROL_ACK:
195 tlli = ul_control_block->u.Packet_Control_Acknowledgement.TLLI;
Holger Hans Peter Freyther34bd8bd2013-10-19 21:10:38 +0200196 tbf = bts->bts->tbf_by_poll_fn(fn, trx, ts);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200197 if (!tbf) {
198 LOGP(DRLCMAC, LOGL_NOTICE, "PACKET CONTROL ACK with "
Andreas Eversberg592e04a2012-07-15 06:25:37 +0200199 "unknown FN=%u TLL=0x%08x (TRX %d TS %d)\n",
200 fn, tlli, trx, ts);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200201 break;
202 }
203 tfi = tbf->tfi;
204 if (tlli != tbf->tlli) {
Andreas Eversberg0e403092012-07-06 11:04:57 +0200205 LOGP(DRLCMAC, LOGL_INFO, "Phone changed TLLI to "
Andreas Eversberge6228b32012-07-03 13:36:03 +0200206 "0x%08x\n", tlli);
207 tbf->tlli = tlli;
208 }
Andreas Eversberg0e403092012-07-06 11:04:57 +0200209 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 +0200210 tbf->poll_state = GPRS_RLCMAC_POLL_NONE;
211
212 /* check if this control ack belongs to packet uplink ack */
213 if (tbf->ul_ack_state == GPRS_RLCMAC_UL_ACK_WAIT_ACK) {
Andreas Eversberg0e403092012-07-06 11:04:57 +0200214 LOGP(DRLCMAC, LOGL_DEBUG, "TBF: [UPLINK] END TFI: %u TLLI: 0x%08x \n", tbf->tfi, tbf->tlli);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200215 tbf->ul_ack_state = GPRS_RLCMAC_UL_ACK_NONE;
Holger Hans Peter Freyther34bd8bd2013-10-19 21:10:38 +0200216 debug_diagram(bts->bts, tbf->diag, "got CTL-ACK (fin)");
Andreas Eversberg14db19e2012-08-06 15:03:03 +0200217 if ((tbf->state_flags &
218 (1 << GPRS_RLCMAC_FLAG_TO_UL_ACK))) {
219 tbf->state_flags &=
220 ~(1 << GPRS_RLCMAC_FLAG_TO_UL_ACK);
221 LOGP(DRLCMAC, LOGL_NOTICE, "Recovered uplink "
Andreas Eversbergb83e2a72012-10-07 15:26:00 +0200222 "ack for UL TBF=%d\n", tbf->tfi);
Andreas Eversberg14db19e2012-08-06 15:03:03 +0200223 }
Andreas Eversberge6228b32012-07-03 13:36:03 +0200224 tbf_free(tbf);
225 break;
226 }
227 if (tbf->dl_ass_state == GPRS_RLCMAC_DL_ASS_WAIT_ACK) {
Andreas Eversberg0e403092012-07-06 11:04:57 +0200228 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 +0200229 /* reset N3105 */
230 tbf->n3105 = 0;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200231 tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE;
Holger Hans Peter Freyther34bd8bd2013-10-19 21:10:38 +0200232 debug_diagram(bts->bts, tbf->diag, "got CTL-ACK DL-ASS");
Andreas Eversberg642c7d32012-07-23 17:58:55 +0200233 if (tbf->direction == GPRS_RLCMAC_UL_TBF)
Holger Hans Peter Freyther34bd8bd2013-10-19 21:10:38 +0200234 tbf = bts->bts->tbf_by_tlli(tbf->tlli,
Andreas Eversberg642c7d32012-07-23 17:58:55 +0200235 GPRS_RLCMAC_DL_TBF);
236 if (!tbf) {
237 LOGP(DRLCMAC, LOGL_ERROR, "Got ACK, but DL "
238 "TBF is gone\n");
239 break;
240 }
241 tbf_new_state(tbf, GPRS_RLCMAC_FLOW);
Andreas Eversbergcbcd1242012-08-07 15:48:21 +0200242 /* stop pending assignment timer */
243 tbf_timer_stop(tbf);
Andreas Eversberg14db19e2012-08-06 15:03:03 +0200244 if ((tbf->state_flags &
245 (1 << GPRS_RLCMAC_FLAG_TO_DL_ASS))) {
246 tbf->state_flags &=
247 ~(1 << GPRS_RLCMAC_FLAG_TO_DL_ASS);
248 LOGP(DRLCMAC, LOGL_NOTICE, "Recovered downlink "
Andreas Eversbergb83e2a72012-10-07 15:26:00 +0200249 "assignment for DL TBF=%d\n", tbf->tfi);
Andreas Eversberg14db19e2012-08-06 15:03:03 +0200250 }
Andreas Eversberg642c7d32012-07-23 17:58:55 +0200251 tbf_assign_control_ts(tbf);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200252 break;
253 }
254 if (tbf->ul_ass_state == GPRS_RLCMAC_UL_ASS_WAIT_ACK) {
Andreas Eversberg0e403092012-07-06 11:04:57 +0200255 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 +0200256 /* reset N3105 */
257 tbf->n3105 = 0;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200258 tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_NONE;
Holger Hans Peter Freyther34bd8bd2013-10-19 21:10:38 +0200259 debug_diagram(bts->bts, tbf->diag, "got CTL-AC UL-ASS");
Andreas Eversberg642c7d32012-07-23 17:58:55 +0200260 if (tbf->direction == GPRS_RLCMAC_DL_TBF)
Holger Hans Peter Freyther34bd8bd2013-10-19 21:10:38 +0200261 tbf = bts->bts->tbf_by_tlli(tbf->tlli,
Andreas Eversberg642c7d32012-07-23 17:58:55 +0200262 GPRS_RLCMAC_UL_TBF);
263 if (!tbf) {
264 LOGP(DRLCMAC, LOGL_ERROR, "Got ACK, but UL "
265 "TBF is gone\n");
266 break;
267 }
268 tbf_new_state(tbf, GPRS_RLCMAC_FLOW);
Andreas Eversberg14db19e2012-08-06 15:03:03 +0200269 if ((tbf->state_flags &
270 (1 << GPRS_RLCMAC_FLAG_TO_UL_ASS))) {
271 tbf->state_flags &=
272 ~(1 << GPRS_RLCMAC_FLAG_TO_UL_ASS);
273 LOGP(DRLCMAC, LOGL_NOTICE, "Recovered uplink "
Andreas Eversbergb83e2a72012-10-07 15:26:00 +0200274 "assignment for UL TBF=%d\n", tbf->tfi);
Andreas Eversberg14db19e2012-08-06 15:03:03 +0200275 }
Andreas Eversberg642c7d32012-07-23 17:58:55 +0200276 tbf_assign_control_ts(tbf);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200277 break;
278 }
279 LOGP(DRLCMAC, LOGL_ERROR, "Error: received PACET CONTROL ACK "
280 "at no request\n");
281 break;
282 case MT_PACKET_DOWNLINK_ACK_NACK:
283 tfi = ul_control_block->u.Packet_Downlink_Ack_Nack.DOWNLINK_TFI;
Holger Hans Peter Freyther34bd8bd2013-10-19 21:10:38 +0200284 tbf = bts->bts->tbf_by_poll_fn(fn, trx, ts);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200285 if (!tbf) {
286 LOGP(DRLCMAC, LOGL_NOTICE, "PACKET DOWNLINK ACK with "
Andreas Eversbergaafcd702012-10-07 15:33:31 +0200287 "unknown FN=%u TFI=%d (TRX %d TS %d)\n",
Andreas Eversberg592e04a2012-07-15 06:25:37 +0200288 fn, tfi, trx, ts);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200289 break;
290 }
Andreas Eversbergaafcd702012-10-07 15:33:31 +0200291 if (tbf->tfi != tfi) {
292 LOGP(DRLCMAC, LOGL_NOTICE, "PACKET DOWNLINK ACK with "
293 "wrong TFI=%d, ignoring!\n", tfi);
294 break;
295 }
Andreas Eversberg14db19e2012-08-06 15:03:03 +0200296 tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_DL_ACK);
297 if ((tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_TO_DL_ACK))) {
298 tbf->state_flags &= ~(1 << GPRS_RLCMAC_FLAG_TO_DL_ACK);
Andreas Eversbergaafcd702012-10-07 15:33:31 +0200299 LOGP(DRLCMAC, LOGL_NOTICE, "Recovered downlink ack "
300 "for DL TBF=%d\n", tbf->tfi);
Andreas Eversberg14db19e2012-08-06 15:03:03 +0200301 }
Andreas Eversberge6228b32012-07-03 13:36:03 +0200302 /* reset N3105 */
Andreas Eversberg802bb6e2012-08-06 11:15:05 +0200303 tbf->n3105 = 0;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200304 /* stop timer T3191 */
305 tbf_timer_stop(tbf);
306 tlli = tbf->tlli;
Andreas Eversberg0e403092012-07-06 11:04:57 +0200307 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 +0200308 tbf->poll_state = GPRS_RLCMAC_POLL_NONE;
Holger Hans Peter Freyther34bd8bd2013-10-19 21:10:38 +0200309 debug_diagram(bts->bts, tbf->diag, "got DL-ACK");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200310
Holger Hans Peter Freytherb65e08a2013-10-20 17:10:25 +0200311 rc = gprs_rlcmac_downlink_ack(tbf,
Andreas Eversberge6228b32012-07-03 13:36:03 +0200312 ul_control_block->u.Packet_Downlink_Ack_Nack.Ack_Nack_Description.FINAL_ACK_INDICATION,
313 ul_control_block->u.Packet_Downlink_Ack_Nack.Ack_Nack_Description.STARTING_SEQUENCE_NUMBER,
314 ul_control_block->u.Packet_Downlink_Ack_Nack.Ack_Nack_Description.RECEIVED_BLOCK_BITMAP);
Andreas Eversberg0f13c402012-07-16 11:59:23 +0200315 if (rc == 1) {
316 tbf_free(tbf);
317 break;
318 }
Andreas Eversberge6228b32012-07-03 13:36:03 +0200319 /* check for channel request */
320 if (ul_control_block->u.Packet_Downlink_Ack_Nack.Exist_Channel_Request_Description) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200321 LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF in ack "
322 "message, so we provide one:\n");
Holger Hans Peter Freyther96efa702013-09-29 07:44:39 +0200323 tbf_alloc_ul(bts, tbf->trx_no, tbf->ms_class, tbf->tlli, tbf->ta, tbf);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200324 /* schedule uplink assignment */
325 tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS;
326 }
327 break;
328 case MT_PACKET_RESOURCE_REQUEST:
329 if (ul_control_block->u.Packet_Resource_Request.ID.UnionType) {
330 tlli = ul_control_block->u.Packet_Resource_Request.ID.u.TLLI;
Holger Hans Peter Freyther34bd8bd2013-10-19 21:10:38 +0200331 tbf = bts->bts->tbf_by_tlli(tlli, GPRS_RLCMAC_UL_TBF);
Andreas Eversberg99a107d2012-09-27 09:21:52 +0200332 if (tbf) {
333 LOGP(DRLCMACUL, LOGL_NOTICE, "Got RACH from "
334 "TLLI=0x%08x while UL TBF=%d still "
335 "exists. Killing pending DL TBF\n",
336 tlli, tbf->tfi);
337 tbf_free(tbf);
338 tbf = NULL;
339 }
Andreas Eversberge6228b32012-07-03 13:36:03 +0200340 if (!tbf) {
Andreas Eversberg07e97cf2012-08-07 16:00:56 +0200341 uint8_t ms_class = 0;
Andreas Eversberg99a107d2012-09-27 09:21:52 +0200342 struct gprs_rlcmac_tbf *dl_tbf;
Andreas Eversberga004e6a2013-05-13 16:45:21 +0200343 uint8_t ta;
Andreas Eversberg99a107d2012-09-27 09:21:52 +0200344
Holger Hans Peter Freyther34bd8bd2013-10-19 21:10:38 +0200345 if ((dl_tbf = bts->bts->tbf_by_tlli(tlli, GPRS_RLCMAC_DL_TBF))) {
Andreas Eversberg99a107d2012-09-27 09:21:52 +0200346 LOGP(DRLCMACUL, LOGL_NOTICE, "Got RACH from "
347 "TLLI=0x%08x while DL TBF=%d still exists. "
348 "Killing pending DL TBF\n", tlli,
349 dl_tbf->tfi);
350 tbf_free(dl_tbf);
351 }
Andreas Eversberg07e97cf2012-08-07 16:00:56 +0200352 LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF "
353 "in packet ressource request of single "
354 "block, so we provide one:\n");
Holger Hans Peter Freythercedf8902013-10-19 20:47:12 +0200355 sba = bts->bts->sba()->find(trx, ts, fn);
Andreas Eversberga004e6a2013-05-13 16:45:21 +0200356 if (!sba) {
357 LOGP(DRLCMAC, LOGL_NOTICE, "MS requests UL TBF "
358 "in packet ressource request of single "
359 "block, but there is no resource request "
360 "scheduled!\n");
Holger Hans Peter Freyther111614a2013-10-19 20:04:57 +0200361 rc = bts->bts->timing_advance()->recall(tlli);
Andreas Eversberga004e6a2013-05-13 16:45:21 +0200362 if (rc >= 0)
363 ta = rc;
364 else
365 ta = 0;
366 } else {
367 ta = sba->ta;
Holger Hans Peter Freyther111614a2013-10-19 20:04:57 +0200368 bts->bts->timing_advance()->remember(tlli, ta);
Andreas Eversberga004e6a2013-05-13 16:45:21 +0200369 llist_del(&sba->list);
370 talloc_free(sba);
371 }
Andreas Eversberg07e97cf2012-08-07 16:00:56 +0200372 if (ul_control_block->u.Packet_Resource_Request.Exist_MS_Radio_Access_capability)
373 ms_class = get_ms_class_by_capability(&ul_control_block->u.Packet_Resource_Request.MS_Radio_Access_capability);
374 if (!ms_class)
375 LOGP(DRLCMAC, LOGL_NOTICE, "MS does not give us a class.\n");
Holger Hans Peter Freyther86921282013-08-24 21:26:42 +0200376 tbf = tbf_alloc_ul(bts, trx, ms_class, tlli, ta, NULL);
Andreas Eversberg07e97cf2012-08-07 16:00:56 +0200377 if (!tbf)
378 break;
379 /* set control ts to current MS's TS, until assignment complete */
380 LOGP(DRLCMAC, LOGL_DEBUG, "Change control TS to %d until assinment is complete.\n", ts);
381 tbf->control_ts = ts;
382 /* schedule uplink assignment */
383 tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS;
Holger Hans Peter Freyther34bd8bd2013-10-19 21:10:38 +0200384 debug_diagram(bts->bts, tbf->diag, "Res. REQ");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200385 break;
386 }
387 tfi = tbf->tfi;
388 } else {
389 if (ul_control_block->u.Packet_Resource_Request.ID.u.Global_TFI.UnionType) {
390 tfi = ul_control_block->u.Packet_Resource_Request.ID.u.Global_TFI.u.DOWNLINK_TFI;
Holger Hans Peter Freytherb67a8a32013-07-28 18:55:14 +0200391 tbf = tbf_by_tfi(bts, tfi, trx, GPRS_RLCMAC_DL_TBF);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200392 if (!tbf) {
Andreas Eversberg0e403092012-07-06 11:04:57 +0200393 LOGP(DRLCMAC, LOGL_NOTICE, "PACKET RESSOURCE REQ unknown downlink TBF=%d\n", tlli);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200394 break;
395 }
396 } else {
397 tfi = ul_control_block->u.Packet_Resource_Request.ID.u.Global_TFI.u.UPLINK_TFI;
Holger Hans Peter Freytherb67a8a32013-07-28 18:55:14 +0200398 tbf = tbf_by_tfi(bts, tfi, trx, GPRS_RLCMAC_UL_TBF);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200399 if (!tbf) {
Andreas Eversberg0e403092012-07-06 11:04:57 +0200400 LOGP(DRLCMAC, LOGL_NOTICE, "PACKET RESSOURCE REQ unknown uplink TBF=%d\n", tlli);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200401 break;
402 }
403 }
404 tlli = tbf->tlli;
405 }
Andreas Eversbergc8466f42012-07-15 19:34:53 +0200406 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 +0200407 break;
Andreas Eversberg050ace22013-03-16 16:22:02 +0100408 case MT_PACKET_MEASUREMENT_REPORT:
Holger Hans Peter Freythercedf8902013-10-19 20:47:12 +0200409 sba = bts->bts->sba()->find(trx, ts, fn);
Andreas Eversberga004e6a2013-05-13 16:45:21 +0200410 if (!sba) {
411 LOGP(DRLCMAC, LOGL_NOTICE, "MS send measurement "
412 "in packet ressource request of single "
413 "block, but there is no resource request "
414 "scheduled!\n");
415 } else {
Holger Hans Peter Freyther111614a2013-10-19 20:04:57 +0200416 bts->bts->timing_advance()->remember(ul_control_block->u.Packet_Measurement_Report.TLLI, sba->ta);
Andreas Eversberga004e6a2013-05-13 16:45:21 +0200417 llist_del(&sba->list);
418 talloc_free(sba);
419 }
Andreas Eversberg050ace22013-03-16 16:22:02 +0100420 gprs_rlcmac_meas_rep(&ul_control_block->u.Packet_Measurement_Report);
421 break;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200422 default:
Andreas Eversberg0e403092012-07-06 11:04:57 +0200423 LOGP(DRLCMAC, LOGL_NOTICE, "RX: [PCU <- BTS] unknown control block received\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200424 }
Andreas Eversberg6681bb82012-07-25 08:48:44 +0200425 talloc_free(ul_control_block);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200426 return 1;
427}
428
Andreas Eversberge13fa2d2012-07-09 17:10:44 +0200429#ifdef DEBUG_DL_ASS_IDLE
430 char debug_imsi[16];
431#endif
Andreas Eversberge6228b32012-07-03 13:36:03 +0200432
Andreas Eversberge6228b32012-07-03 13:36:03 +0200433/*
434 * UL data block flow
435 */
436
Holger Hans Peter Freytherb65e08a2013-10-20 17:10:25 +0200437struct msgb *gprs_rlcmac_send_uplink_ack(
Holger Hans Peter Freytherae947fc2013-10-17 13:29:03 +0200438 struct gprs_rlcmac_tbf *tbf,
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200439 uint32_t fn)
440{
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200441 int final = (tbf->state_is(GPRS_RLCMAC_FINISHED));
Holger Hans Peter Freytherb65e08a2013-10-20 17:10:25 +0200442 gprs_rlcmac_bts *bts = tbf->bts->bts_data();
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200443 struct msgb *msg;
444
Andreas Eversberg07e97cf2012-08-07 16:00:56 +0200445 if (final) {
446 if (tbf->poll_state != GPRS_RLCMAC_POLL_NONE) {
447 LOGP(DRLCMACUL, LOGL_DEBUG, "Polling is already "
448 "sheduled for TBF=%d, so we must wait for "
449 "final uplink ack...\n", tbf->tfi);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200450 return NULL;
Andreas Eversberg07e97cf2012-08-07 16:00:56 +0200451 }
Holger Hans Peter Freytherb65e08a2013-10-20 17:10:25 +0200452 if (tbf->bts->sba()->find(tbf->trx_no, tbf->control_ts, (fn + 13) % 2715648)) {
Andreas Eversberg07e97cf2012-08-07 16:00:56 +0200453 LOGP(DRLCMACUL, LOGL_DEBUG, "Polling is already "
454 "scheduled for single block allocation...\n");
455 return NULL;
456 }
Andreas Eversberge6228b32012-07-03 13:36:03 +0200457 }
458
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200459 msg = msgb_alloc(23, "rlcmac_ul_ack");
460 if (!msg)
461 return NULL;
462 bitvec *ack_vec = bitvec_alloc(23);
463 if (!ack_vec) {
464 msgb_free(msg);
465 return NULL;
466 }
467 bitvec_unhex(ack_vec,
468 "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
Andreas Eversberg6681bb82012-07-25 08:48:44 +0200469 RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)talloc_zero(tall_pcu_ctx, RlcMacDownlink_t);
Holger Hans Peter Freyther63f29d62013-10-19 19:04:03 +0200470 Encoding::write_packet_uplink_ack(bts, mac_control_block, tbf, final);
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +0400471 encode_gsm_rlcmac_downlink(ack_vec, mac_control_block);
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200472 bitvec_pack(ack_vec, msgb_put(msg, 23));
473 bitvec_free(ack_vec);
Andreas Eversberg6681bb82012-07-25 08:48:44 +0200474 talloc_free(mac_control_block);
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200475
Andreas Eversbergee31b782012-07-15 16:27:01 +0200476 /* now we must set this flag, so we are allowed to assign downlink
477 * TBF on PACCH. it is only allowed when TLLI is aknowledged. */
Andreas Eversberg08e93cd2012-07-26 08:13:06 +0200478 tbf->dir.ul.contention_resolution_done = 1;
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200479
480 if (final) {
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200481 tbf->poll_state = GPRS_RLCMAC_POLL_SCHED;
482 tbf->poll_fn = (fn + 13) % 2715648;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200483 /* waiting for final acknowledge */
484 tbf->ul_ack_state = GPRS_RLCMAC_UL_ACK_WAIT_ACK;
Andreas Eversberg08e93cd2012-07-26 08:13:06 +0200485 tbf->dir.ul.final_ack_sent = 1;
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200486 } else
Andreas Eversberge6228b32012-07-03 13:36:03 +0200487 tbf->ul_ack_state = GPRS_RLCMAC_UL_ACK_NONE;
Holger Hans Peter Freyther34bd8bd2013-10-19 21:10:38 +0200488 debug_diagram(bts->bts, tbf->diag, "send UL-ACK");
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200489
490 return msg;
491}
492
Andreas Eversberge6228b32012-07-03 13:36:03 +0200493struct msgb *gprs_rlcmac_send_packet_uplink_assignment(
494 struct gprs_rlcmac_tbf *tbf, uint32_t fn)
495{
496 struct msgb *msg;
497 struct gprs_rlcmac_tbf *new_tbf;
Holger Hans Peter Freytherb65e08a2013-10-20 17:10:25 +0200498 gprs_rlcmac_bts *bts = tbf->bts->bts_data();
Andreas Eversberge6228b32012-07-03 13:36:03 +0200499
Andreas Eversberg802bb6e2012-08-06 11:15:05 +0200500#if POLLING_ASSIGNMENT_UL == 1
Andreas Eversberge6228b32012-07-03 13:36:03 +0200501 if (tbf->poll_state != GPRS_RLCMAC_POLL_NONE) {
502 LOGP(DRLCMACUL, LOGL_DEBUG, "Polling is already "
503 "sheduled for TBF=%d, so we must wait for uplink "
504 "assignment...\n", tbf->tfi);
505 return NULL;
506 }
Holger Hans Peter Freytherb65e08a2013-10-20 17:10:25 +0200507 if (tbf->bts->sba()->find(tbf->trx_no, tbf->control_ts, (fn + 13) % 2715648)) {
Andreas Eversberg07e97cf2012-08-07 16:00:56 +0200508 LOGP(DRLCMACUL, LOGL_DEBUG, "Polling is already scheduled for "
509 "single block allocation...\n");
510 return NULL;
511 }
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200512#endif
Andreas Eversberge6228b32012-07-03 13:36:03 +0200513
514 /* on down TBF we get the uplink TBF to be assigned. */
515 if (tbf->direction == GPRS_RLCMAC_DL_TBF)
Holger Hans Peter Freytherb65e08a2013-10-20 17:10:25 +0200516 new_tbf = tbf->bts->tbf_by_tlli(tbf->tlli, GPRS_RLCMAC_UL_TBF);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200517 else
518 new_tbf = tbf;
519
520 if (!new_tbf) {
521 LOGP(DRLCMACUL, LOGL_ERROR, "We have a schedule for uplink "
522 "assignment at downlink TBF=%d, but there is no uplink "
523 "TBF\n", tbf->tfi);
524 tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_NONE;
525 return NULL;
526 }
527
528 msg = msgb_alloc(23, "rlcmac_ul_ass");
529 if (!msg)
530 return NULL;
Andreas Eversberg0e403092012-07-06 11:04:57 +0200531 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 +0200532 bitvec *ass_vec = bitvec_alloc(23);
533 if (!ass_vec) {
534 msgb_free(msg);
535 return NULL;
536 }
537 bitvec_unhex(ass_vec,
538 "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
Holger Hans Peter Freyther63f29d62013-10-19 19:04:03 +0200539 Encoding::write_packet_uplink_assignment(bts, ass_vec, tbf->tfi,
Andreas Eversberg07e97cf2012-08-07 16:00:56 +0200540 (tbf->direction == GPRS_RLCMAC_DL_TBF), tbf->tlli,
Andreas Eversbergaafcbbb2012-09-27 09:20:45 +0200541 tbf->tlli_valid, new_tbf, POLLING_ASSIGNMENT_UL, bts->alpha,
Andreas Eversbergafdd9e12012-10-07 17:08:55 +0200542 bts->gamma, -1);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200543 bitvec_pack(ass_vec, msgb_put(msg, 23));
Andreas Eversberg6681bb82012-07-25 08:48:44 +0200544 RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)talloc_zero(tall_pcu_ctx, RlcMacDownlink_t);
Andreas Eversberg0e403092012-07-06 11:04:57 +0200545 LOGP(DRLCMAC, LOGL_DEBUG, "+++++++++++++++++++++++++ TX : Packet Uplink Assignment +++++++++++++++++++++++++\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200546 decode_gsm_rlcmac_downlink(ass_vec, mac_control_block);
Andreas Eversberg0e403092012-07-06 11:04:57 +0200547 LOGPC(DCSN1, LOGL_NOTICE, "\n");
548 LOGP(DRLCMAC, LOGL_DEBUG, "------------------------- TX : Packet Uplink Assignment -------------------------\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200549 bitvec_free(ass_vec);
Andreas Eversberg6681bb82012-07-25 08:48:44 +0200550 talloc_free(mac_control_block);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200551
Andreas Eversberg802bb6e2012-08-06 11:15:05 +0200552#if POLLING_ASSIGNMENT_UL == 1
Andreas Eversberge6228b32012-07-03 13:36:03 +0200553 tbf->poll_state = GPRS_RLCMAC_POLL_SCHED;
554 tbf->poll_fn = (fn + 13) % 2715648;
555 tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_WAIT_ACK;
556#else
557 tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_NONE;
Andreas Eversberg642c7d32012-07-23 17:58:55 +0200558 tbf_new_state(new_tbf, GPRS_RLCMAC_FLOW);
559 tbf_assign_control_ts(new_tbf);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200560#endif
Holger Hans Peter Freyther34bd8bd2013-10-19 21:10:38 +0200561 debug_diagram(bts->bts, tbf->diag, "send UL-ASS");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200562
563 return msg;
564}
565
Holger Hans Peter Freytherb0250eb2013-10-17 13:46:19 +0200566int gprs_rlcmac_rcv_rach(struct gprs_rlcmac_bts *bts,
567 uint8_t ra, uint32_t Fn, int16_t qta)
Andreas Eversberge6228b32012-07-03 13:36:03 +0200568{
569 struct gprs_rlcmac_tbf *tbf;
Andreas Eversberg02d7cd22013-01-15 08:59:34 +0100570 uint8_t trx, ts = 0;
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200571 int8_t tfi; /* must be signed */
Andreas Eversberg07e97cf2012-08-07 16:00:56 +0200572 uint8_t sb = 0;
573 uint32_t sb_fn = 0;
574 int rc;
575 uint8_t plen;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200576
577 LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF on RACH, so we provide "
578 "one:\n");
Andreas Eversberg07e97cf2012-08-07 16:00:56 +0200579 if ((ra & 0xf8) == 0x70) {
580 LOGP(DRLCMAC, LOGL_DEBUG, "MS requests single block "
581 "allocation\n");
582 sb = 1;
583 } else if (bts->force_two_phase) {
584 LOGP(DRLCMAC, LOGL_DEBUG, "MS requests single phase access, "
585 "but we force two phase access\n");
586 sb = 1;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200587 }
Andreas Eversberge6228b32012-07-03 13:36:03 +0200588 if (qta < 0)
589 qta = 0;
590 if (qta > 252)
591 qta = 252;
Andreas Eversberg07e97cf2012-08-07 16:00:56 +0200592 if (sb) {
Holger Hans Peter Freythercedf8902013-10-19 20:47:12 +0200593 rc = bts->bts->sba()->alloc(&trx, &ts, &sb_fn, qta >> 2);
Andreas Eversberg07e97cf2012-08-07 16:00:56 +0200594 if (rc < 0)
595 return rc;
596 LOGP(DRLCMAC, LOGL_DEBUG, "RX: [PCU <- BTS] RACH qbit-ta=%d "
597 "ra=0x%02x, Fn=%d (%d,%d,%d)\n", qta, ra, Fn,
598 (Fn / (26 * 51)) % 32, Fn % 51, Fn % 26);
599 LOGP(DRLCMAC, LOGL_INFO, "TX: Immediate Assignment Uplink "
600 "(AGCH)\n");
601 } else {
602 // Create new TBF
Holger Hans Peter Freytherbcafdf82013-08-24 21:13:31 +0200603 #warning "Copy and pate with other routines.."
Holger Hans Peter Freytherd6bd91e2013-08-24 21:16:55 +0200604 tfi = tfi_find_free(bts, GPRS_RLCMAC_UL_TBF, &trx, -1);
Andreas Eversberg07e97cf2012-08-07 16:00:56 +0200605 if (tfi < 0) {
606 LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n");
607 /* FIXME: send reject */
608 return -EBUSY;
609 }
610 /* set class to 0, since we don't know the multislot class yet */
Holger Hans Peter Freytherb67a8a32013-07-28 18:55:14 +0200611 tbf = tbf_alloc(bts, NULL, GPRS_RLCMAC_UL_TBF, tfi, trx, 0, 1);
Andreas Eversberg07e97cf2012-08-07 16:00:56 +0200612 if (!tbf) {
613 LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n");
614 /* FIXME: send reject */
615 return -EBUSY;
616 }
617 tbf->ta = qta >> 2;
618 tbf_new_state(tbf, GPRS_RLCMAC_FLOW);
619 tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_CCCH);
620 tbf_timer_start(tbf, 3169, bts->t3169, 0);
621 LOGP(DRLCMAC, LOGL_DEBUG, "TBF: [UPLINK] START TFI: %u\n",
622 tbf->tfi);
623 LOGP(DRLCMAC, LOGL_DEBUG, "RX: [PCU <- BTS] TFI: %u RACH "
624 "qbit-ta=%d ra=0x%02x, Fn=%d (%d,%d,%d)\n", tbf->tfi,
625 qta, ra, Fn, (Fn / (26 * 51)) % 32, Fn % 51, Fn % 26);
626 LOGP(DRLCMAC, LOGL_INFO, "TX: START TFI: %u Immediate "
627 "Assignment Uplink (AGCH)\n", tbf->tfi);
628 }
Andreas Eversberg7b045012012-07-05 07:38:49 +0200629 bitvec *immediate_assignment = bitvec_alloc(22) /* without plen */;
Andreas Eversberg07e97cf2012-08-07 16:00:56 +0200630 bitvec_unhex(immediate_assignment,
631 "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
632 if (sb)
Holger Hans Peter Freyther63f29d62013-10-19 19:04:03 +0200633 plen = Encoding::write_immediate_assignment(bts, immediate_assignment, 0, ra,
Andreas Eversberg07e97cf2012-08-07 16:00:56 +0200634 Fn, qta >> 2, bts->trx[trx].arfcn, ts,
Andreas Eversbergaafcbbb2012-09-27 09:20:45 +0200635 bts->trx[trx].pdch[ts].tsc, 0, 0, 0, 0, sb_fn, 1,
Andreas Eversbergafdd9e12012-10-07 17:08:55 +0200636 bts->alpha, bts->gamma, -1);
Andreas Eversberg07e97cf2012-08-07 16:00:56 +0200637 else
Holger Hans Peter Freyther63f29d62013-10-19 19:04:03 +0200638 plen = Encoding::write_immediate_assignment(bts, immediate_assignment, 0, ra,
Andreas Eversberg07e97cf2012-08-07 16:00:56 +0200639 Fn, tbf->ta, tbf->arfcn, tbf->first_ts, tbf->tsc,
Andreas Eversbergaafcbbb2012-09-27 09:20:45 +0200640 tbf->tfi, tbf->dir.ul.usf[tbf->first_ts], 0, 0, 0, 0,
Andreas Eversbergafdd9e12012-10-07 17:08:55 +0200641 bts->alpha, bts->gamma, -1);
Andreas Eversberg7b045012012-07-05 07:38:49 +0200642 pcu_l1if_tx_agch(immediate_assignment, plen);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200643 bitvec_free(immediate_assignment);
644
645 return 0;
646}
647
648
Andreas Eversberge6228b32012-07-03 13:36:03 +0200649/* send DL data block
650 *
651 * The messages are fragmented and forwarded as data blocks.
652 */
653struct msgb *gprs_rlcmac_send_data_block_acknowledged(
Andreas Eversberg592e04a2012-07-15 06:25:37 +0200654 struct gprs_rlcmac_tbf *tbf, uint32_t fn, uint8_t ts)
Andreas Eversberge6228b32012-07-03 13:36:03 +0200655{
Andreas Eversberge6228b32012-07-03 13:36:03 +0200656 struct rlc_dl_header *rh;
657 struct rlc_li_field *li;
658 uint8_t block_length; /* total length of block, including spare bits */
659 uint8_t block_data; /* usable data of block, w/o spare bits, inc. MAC */
660 struct msgb *msg, *dl_msg;
661 uint8_t bsn;
662 uint16_t mod_sns = tbf->sns - 1;
663 uint16_t mod_sns_half = (tbf->sns >> 1) - 1;
664 uint16_t index;
665 uint8_t *delimiter, *data, *e_pointer;
666 uint8_t len;
667 uint16_t space, chunk;
Andreas Eversberg0c9b50c2012-10-07 15:50:51 +0200668 int first_fin_ack = 0;
Holger Hans Peter Freytherb65e08a2013-10-20 17:10:25 +0200669 gprs_rlcmac_bts *bts = tbf->bts->bts_data();
Andreas Eversberge6228b32012-07-03 13:36:03 +0200670
Andreas Eversberg0e403092012-07-06 11:04:57 +0200671 LOGP(DRLCMACDL, LOGL_DEBUG, "DL DATA TBF=%d downlink (V(A)==%d .. "
Andreas Eversberge6228b32012-07-03 13:36:03 +0200672 "V(S)==%d)\n", tbf->tfi, tbf->dir.dl.v_a, tbf->dir.dl.v_s);
673
674do_resend:
675 /* check if there is a block with negative acknowledgement */
676 for (bsn = tbf->dir.dl.v_a; bsn != tbf->dir.dl.v_s;
677 bsn = (bsn + 1) & mod_sns) {
678 index = (bsn & mod_sns_half);
679 if (tbf->dir.dl.v_b[index] == 'N'
680 || tbf->dir.dl.v_b[index] == 'X') {
681 LOGP(DRLCMACDL, LOGL_DEBUG, "- Resending BSN %d\n",
682 bsn);
683 /* re-send block with negative aknowlegement */
684 tbf->dir.dl.v_b[index] = 'U'; /* unacked */
685 goto tx_block;
686 }
687 }
688
689 /* if the window has stalled, or transfer is complete,
690 * send an unacknowledged block */
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200691 if (tbf->state_is(GPRS_RLCMAC_FINISHED)
Andreas Eversberge6228b32012-07-03 13:36:03 +0200692 || ((tbf->dir.dl.v_s - tbf->dir.dl.v_a) & mod_sns) == tbf->ws) {
693 int resend = 0;
694
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200695 if (tbf->state_is(GPRS_RLCMAC_FINISHED))
Andreas Eversberge6228b32012-07-03 13:36:03 +0200696 LOGP(DRLCMACDL, LOGL_DEBUG, "- Restarting at BSN %d, "
697 "because all blocks have been transmitted.\n",
698 tbf->dir.dl.v_a);
699 else
Andreas Eversberg4b470ff2012-07-16 12:02:40 +0200700 LOGP(DRLCMACDL, LOGL_NOTICE, "- Restarting at BSN %d, "
Andreas Eversberge6228b32012-07-03 13:36:03 +0200701 "because all window is stalled.\n",
702 tbf->dir.dl.v_a);
703 /* If V(S) == V(A) and finished state, we would have received
704 * acknowledgement of all transmitted block. In this case we
705 * would have transmitted the final block, and received ack
706 * from MS. But in this case we did not receive the final ack
707 * indication from MS. This should never happen if MS works
708 * correctly. */
709 if (tbf->dir.dl.v_s == tbf->dir.dl.v_a) {
Andreas Eversberg0c9b50c2012-10-07 15:50:51 +0200710 LOGP(DRLCMACDL, LOGL_DEBUG, "- MS acked all blocks, "
711 "so we re-transmit final block!\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200712 /* we just send final block again */
713 index = ((tbf->dir.dl.v_s - 1) & mod_sns_half);
714 goto tx_block;
715 }
716
717 /* cycle through all unacked blocks */
718 for (bsn = tbf->dir.dl.v_a; bsn != tbf->dir.dl.v_s;
719 bsn = (bsn + 1) & mod_sns) {
720 index = (bsn & mod_sns_half);
721 if (tbf->dir.dl.v_b[index] == 'U') {
722 /* mark to be re-send */
723 tbf->dir.dl.v_b[index] = 'X';
724 resend++;
725 }
726 }
727 /* At this point there should be at leasst one unacked block
728 * to be resent. If not, this is an software error. */
729 if (resend == 0) {
730 LOGP(DRLCMACDL, LOGL_ERROR, "Software error: "
731 "There are no unacknowledged blocks, but V(A) "
732 " != V(S). PLEASE FIX!\n");
733 /* we just send final block again */
734 index = ((tbf->dir.dl.v_s - 1) & mod_sns_half);
735 goto tx_block;
736 }
737 goto do_resend;
738 }
739
740 LOGP(DRLCMACDL, LOGL_DEBUG, "- Sending new block at BSN %d\n",
741 tbf->dir.dl.v_s);
742
743 /* now we still have untransmitted LLC data, so we fill mac block */
744 index = tbf->dir.dl.v_s & mod_sns_half;
745 data = tbf->rlc_block[index];
Holger Hans Peter Freytherb65e08a2013-10-20 17:10:25 +0200746#warning "Selection of the CS doesn't belong here"
Andreas Eversberg3b1332c2012-10-03 14:20:53 +0200747 if (tbf->cs == 0) {
Andreas Eversberg499ff412012-10-03 14:21:36 +0200748 tbf->cs = bts->initial_cs_dl;
Andreas Eversberg3b1332c2012-10-03 14:20:53 +0200749 if (tbf->cs < 1 || tbf->cs > 4)
750 tbf->cs = 1;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200751 }
Andreas Eversberg3b1332c2012-10-03 14:20:53 +0200752 block_length = gprs_rlcmac_cs[tbf->cs].block_length;
753 block_data = gprs_rlcmac_cs[tbf->cs].block_data;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200754 memset(data, 0x2b, block_data); /* spare bits will be left 0 */
755 rh = (struct rlc_dl_header *)data;
756 rh->pt = 0; /* Data Block */
757 rh->rrbp = rh->s_p = 0; /* Polling, set later, if required */
758 rh->usf = 7; /* will be set at scheduler */
759 rh->pr = 0; /* FIXME: power reduction */
760 rh->tfi = tbf->tfi; /* TFI */
761 rh->fbi = 0; /* Final Block Indicator, set late, if true */
762 rh->bsn = tbf->dir.dl.v_s; /* Block Sequence Number */
763 rh->e = 0; /* Extension bit, maybe set later */
764 e_pointer = data + 2; /* points to E of current chunk */
765 data += 3;
766 delimiter = data; /* where next length header would be stored */
767 space = block_data - 3;
768 while (1) {
769 chunk = tbf->llc_length - tbf->llc_index;
770 /* if chunk will exceed block limit */
771 if (chunk > space) {
772 LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d "
773 "larger than space (%d) left in block: copy "
774 "only remaining space, and we are done\n",
775 chunk, space);
776 /* block is filled, so there is no extension */
777 *e_pointer |= 0x01;
778 /* fill only space */
779 memcpy(data, tbf->llc_frame + tbf->llc_index, space);
780 /* incement index */
781 tbf->llc_index += space;
782 /* return data block as message */
783 break;
784 }
785 /* if FINAL chunk would fit precisely in space left */
786 if (chunk == space && llist_empty(&tbf->llc_queue)) {
787 LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d "
788 "would exactly fit into space (%d): because "
789 "this is a final block, we don't add length "
790 "header, and we are done\n", chunk, space);
Andreas Eversberg0e403092012-07-06 11:04:57 +0200791 LOGP(DRLCMACDL, LOGL_INFO, "Complete DL frame for "
792 "TBF=%d that fits precisely in last block: "
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200793 "len=%d\n", tbf->tfi, tbf->llc_length);
Andreas Eversberg050ace22013-03-16 16:22:02 +0100794 gprs_rlcmac_dl_bw(tbf, tbf->llc_length);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200795 /* block is filled, so there is no extension */
796 *e_pointer |= 0x01;
797 /* fill space */
798 memcpy(data, tbf->llc_frame + tbf->llc_index, space);
799 /* reset LLC frame */
800 tbf->llc_index = tbf->llc_length = 0;
801 /* final block */
802 rh->fbi = 1; /* we indicate final block */
803 tbf_new_state(tbf, GPRS_RLCMAC_FINISHED);
804 /* return data block as message */
805 break;
806 }
807 /* if chunk would fit exactly in space left */
808 if (chunk == space) {
809 LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d "
810 "would exactly fit into space (%d): add length "
811 "header with LI=0, to make frame extend to "
812 "next block, and we are done\n", chunk, space);
813 /* make space for delimiter */
814 if (delimiter != data)
815 memcpy(delimiter + 1, delimiter,
816 data - delimiter);
817 data++;
818 space--;
819 /* add LI with 0 length */
820 li = (struct rlc_li_field *)delimiter;
821 li->e = 1; /* not more extension */
822 li->m = 0; /* shall be set to 0, in case of li = 0 */
823 li->li = 0; /* chunk fills the complete space */
824 // no need to set e_pointer nor increase delimiter
825 /* fill only space, which is 1 octet less than chunk */
826 memcpy(data, tbf->llc_frame + tbf->llc_index, space);
827 /* incement index */
828 tbf->llc_index += space;
829 /* return data block as message */
830 break;
831 }
832 LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d is less "
833 "than remaining space (%d): add length header to "
834 "to delimit LLC frame\n", chunk, space);
835 /* the LLC frame chunk ends in this block */
836 /* make space for delimiter */
837 if (delimiter != data)
838 memcpy(delimiter + 1, delimiter, data - delimiter);
839 data++;
840 space--;
841 /* add LI to delimit frame */
842 li = (struct rlc_li_field *)delimiter;
843 li->e = 0; /* Extension bit, maybe set later */
844 li->m = 0; /* will be set later, if there is more LLC data */
845 li->li = chunk; /* length of chunk */
846 e_pointer = delimiter; /* points to E of current delimiter */
847 delimiter++;
848 /* copy (rest of) LLC frame to space */
849 memcpy(data, tbf->llc_frame + tbf->llc_index, chunk);
850 data += chunk;
851 space -= chunk;
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200852 LOGP(DRLCMACDL, LOGL_INFO, "Complete DL frame for TBF=%d: "
853 "len=%d\n", tbf->tfi, tbf->llc_length);
Andreas Eversberg050ace22013-03-16 16:22:02 +0100854 gprs_rlcmac_dl_bw(tbf, tbf->llc_length);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200855 /* reset LLC frame */
856 tbf->llc_index = tbf->llc_length = 0;
857 /* dequeue next LLC frame, if any */
Holger Hans Peter Freyther1702f102013-10-20 08:44:02 +0200858 msg = tbf->llc_dequeue(gprs_bssgp_pcu_current_bctx());
Andreas Eversberge6228b32012-07-03 13:36:03 +0200859 if (msg) {
Andreas Eversberg0e403092012-07-06 11:04:57 +0200860 LOGP(DRLCMACDL, LOGL_INFO, "- Dequeue next LLC for "
861 "TBF=%d (len=%d)\n", tbf->tfi, msg->len);
Holger Hans Peter Freyther1702f102013-10-20 08:44:02 +0200862 tbf->update_llc_frame(msg);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200863 msgb_free(msg);
864 }
865 /* if we have more data and we have space left */
866 if (space > 0 && tbf->llc_length) {
867 li->m = 1; /* we indicate more frames to follow */
868 continue;
869 }
870 /* if we don't have more LLC frames */
871 if (!tbf->llc_length) {
Andreas Eversberg0e403092012-07-06 11:04:57 +0200872 LOGP(DRLCMACDL, LOGL_DEBUG, "-- Final block, so we "
Andreas Eversberge6228b32012-07-03 13:36:03 +0200873 "done.\n");
874 li->e = 1; /* we cannot extend */
875 rh->fbi = 1; /* we indicate final block */
Andreas Eversberg5f14bd92012-10-03 14:20:26 +0200876 first_fin_ack = 1;
Andreas Eversbergf54a89e2012-07-16 11:56:11 +0200877 /* + 1 indicates: first final ack */
Andreas Eversberge6228b32012-07-03 13:36:03 +0200878 tbf_new_state(tbf, GPRS_RLCMAC_FINISHED);
879 break;
880 }
881 /* we have no space left */
Andreas Eversberg0e403092012-07-06 11:04:57 +0200882 LOGP(DRLCMACDL, LOGL_DEBUG, "-- No space left, so we are "
Andreas Eversberge6228b32012-07-03 13:36:03 +0200883 "done.\n");
884 li->e = 1; /* we cannot extend */
885 break;
886 }
887 LOGP(DRLCMACDL, LOGL_DEBUG, "data block: %s\n",
888 osmo_hexdump(tbf->rlc_block[index], block_length));
889 tbf->rlc_block_len[index] = block_length;
890 /* raise send state and set ack state array */
891 tbf->dir.dl.v_b[index] = 'U'; /* unacked */
892 tbf->dir.dl.v_s = (tbf->dir.dl.v_s + 1) & mod_sns; /* inc send state */
893
894tx_block:
895 /* from this point on, new block is sent or old block is resent */
896
897 /* get data and header from current block */
898 data = tbf->rlc_block[index];
899 len = tbf->rlc_block_len[index];
900 rh = (struct rlc_dl_header *)data;
901
Andreas Eversberge6228b32012-07-03 13:36:03 +0200902 /* Clear Polling, if still set in history buffer */
903 rh->s_p = 0;
904
Andreas Eversbergf54a89e2012-07-16 11:56:11 +0200905 /* poll after POLL_ACK_AFTER_FRAMES frames, or when final block is tx.
906 */
Andreas Eversberg5f14bd92012-10-03 14:20:26 +0200907 if (tbf->dir.dl.tx_counter >= POLL_ACK_AFTER_FRAMES || first_fin_ack) {
908 if (first_fin_ack) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200909 LOGP(DRLCMACDL, LOGL_DEBUG, "- Scheduling Ack/Nack "
Andreas Eversberg5f14bd92012-10-03 14:20:26 +0200910 "polling, because first final block sent.\n");
Andreas Eversberg5e043da2012-07-15 06:51:30 +0200911 } else {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200912 LOGP(DRLCMACDL, LOGL_DEBUG, "- Scheduling Ack/Nack "
913 "polling, because %d blocks sent.\n",
Andreas Eversbergf54a89e2012-07-16 11:56:11 +0200914 POLL_ACK_AFTER_FRAMES);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200915 }
Andreas Eversberg5e043da2012-07-15 06:51:30 +0200916 /* scheduling not possible, because: */
Andreas Eversberge6228b32012-07-03 13:36:03 +0200917 if (tbf->poll_state != GPRS_RLCMAC_POLL_NONE)
Andreas Eversberg5e043da2012-07-15 06:51:30 +0200918 LOGP(DRLCMAC, LOGL_DEBUG, "Polling is already "
Andreas Eversberge6228b32012-07-03 13:36:03 +0200919 "sheduled for TBF=%d, so we must wait for "
920 "requesting downlink ack\n", tbf->tfi);
Andreas Eversberg5e043da2012-07-15 06:51:30 +0200921 else if (tbf->control_ts != ts)
922 LOGP(DRLCMAC, LOGL_DEBUG, "Polling cannot be "
923 "sheduled in this TS %d, waiting for "
924 "TS %d\n", ts, tbf->control_ts);
Holger Hans Peter Freytherb65e08a2013-10-20 17:10:25 +0200925 else if (tbf->bts->sba()->find(tbf->trx_no, ts, (fn + 13) % 2715648))
Andreas Eversberg07e97cf2012-08-07 16:00:56 +0200926 LOGP(DRLCMAC, LOGL_DEBUG, "Polling cannot be "
927 "sheduled, because single block alllocation "
928 "already exists\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200929 else {
Andreas Eversbergee31b782012-07-15 16:27:01 +0200930 LOGP(DRLCMAC, LOGL_DEBUG, "Polling sheduled in this "
931 "TS %d\n", ts);
Andreas Eversberg5f14bd92012-10-03 14:20:26 +0200932 tbf->dir.dl.tx_counter = 0;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200933 /* start timer whenever we send the final block */
934 if (rh->fbi == 1)
Andreas Eversbergdfa563c2012-07-06 08:13:59 +0200935 tbf_timer_start(tbf, 3191, bts->t3191, 0);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200936
937 /* schedule polling */
938 tbf->poll_state = GPRS_RLCMAC_POLL_SCHED;
939 tbf->poll_fn = (fn + 13) % 2715648;
940
Andreas Eversbergb83e2a72012-10-07 15:26:00 +0200941#ifdef DEBUG_DIAGRAM
Holger Hans Peter Freyther34bd8bd2013-10-19 21:10:38 +0200942 debug_diagram(bts->bts, tbf->diag, "poll DL-ACK");
Andreas Eversbergb83e2a72012-10-07 15:26:00 +0200943 if (first_fin_ack)
Holger Hans Peter Freyther34bd8bd2013-10-19 21:10:38 +0200944 debug_diagram(bts->bts, tbf->diag, "(is first FINAL)");
Andreas Eversbergb83e2a72012-10-07 15:26:00 +0200945 if (rh->fbi)
Holger Hans Peter Freyther34bd8bd2013-10-19 21:10:38 +0200946 debug_diagram(bts->bts, tbf->diag, "(FBI is set)");
Andreas Eversbergb83e2a72012-10-07 15:26:00 +0200947#endif
948
Andreas Eversberge6228b32012-07-03 13:36:03 +0200949 /* set polling in header */
950 rh->rrbp = 0; /* N+13 */
951 rh->s_p = 1; /* Polling */
Andreas Eversberg5e043da2012-07-15 06:51:30 +0200952
953 /* Increment TX-counter */
954 tbf->dir.dl.tx_counter++;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200955 }
Andreas Eversberg5e043da2012-07-15 06:51:30 +0200956 } else {
957 /* Increment TX-counter */
958 tbf->dir.dl.tx_counter++;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200959 }
960
961 /* return data block as message */
962 dl_msg = msgb_alloc(len, "rlcmac_dl_data");
963 if (!dl_msg)
964 return NULL;
965 memcpy(msgb_put(dl_msg, len), data, len);
966
967 return dl_msg;
968}
969
Holger Hans Peter Freytherb65e08a2013-10-20 17:10:25 +0200970int gprs_rlcmac_downlink_ack(
Holger Hans Peter Freyther344ff482013-10-17 12:01:04 +0200971 struct gprs_rlcmac_tbf *tbf, uint8_t final,
Andreas Eversberge6228b32012-07-03 13:36:03 +0200972 uint8_t ssn, uint8_t *rbb)
973{
974 char show_rbb[65], show_v_b[RLC_MAX_SNS + 1];
975 uint16_t mod_sns = tbf->sns - 1;
976 uint16_t mod_sns_half = (tbf->sns >> 1) - 1;
977 int i; /* must be signed */
978 int16_t dist; /* must be signed */
979 uint8_t bit;
980 uint16_t bsn;
981 struct msgb *msg;
Andreas Eversberg050ace22013-03-16 16:22:02 +0100982 uint16_t lost = 0, received = 0;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200983
Andreas Eversberg0e403092012-07-06 11:04:57 +0200984 LOGP(DRLCMACDL, LOGL_DEBUG, "TBF=%d downlink acknowledge\n",
Andreas Eversberge6228b32012-07-03 13:36:03 +0200985 tbf->tfi);
986
987 if (!final) {
988 /* show received array in debug (bit 64..1) */
989 for (i = 63; i >= 0; i--) {
990 bit = (rbb[i >> 3] >> (7 - (i&7))) & 1;
991 show_rbb[i] = (bit) ? '1' : 'o';
992 }
993 show_rbb[64] = '\0';
994 LOGP(DRLCMACDL, LOGL_DEBUG, "- ack: (BSN=%d)\"%s\""
Andreas Eversberg4b470ff2012-07-16 12:02:40 +0200995 "(BSN=%d) 1=ACK o=NACK\n", (ssn - 64) & mod_sns,
996 show_rbb, (ssn - 1) & mod_sns);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200997
998 /* apply received array to receive state (SSN-64..SSN-1) */
999 /* calculate distance of ssn from V(S) */
1000 dist = (tbf->dir.dl.v_s - ssn) & mod_sns;
1001 /* check if distance is less than distance V(A)..V(S) */
Andreas Eversberg050ace22013-03-16 16:22:02 +01001002 if (dist >= ((tbf->dir.dl.v_s - tbf->dir.dl.v_a) & mod_sns)) {
Andreas Eversberg0f13c402012-07-16 11:59:23 +02001003 /* this might happpen, if the downlink assignment
1004 * was not received by ms and the ack refers
1005 * to previous TBF
1006 * FIXME: we should implement polling for
1007 * control ack!*/
1008 LOGP(DRLCMACDL, LOGL_NOTICE, "- ack range is out of "
1009 "V(A)..V(S) range (DL TBF=%d) Free TFB!\n",
1010 tbf->tfi);
1011 return 1; /* indicate to free TBF */
Andreas Eversberge6228b32012-07-03 13:36:03 +02001012 }
Andreas Eversberg050ace22013-03-16 16:22:02 +01001013 /* SSN - 1 is in range V(A)..V(S)-1 */
1014 for (i = 63, bsn = (ssn - 1) & mod_sns;
1015 i >= 0 && bsn != ((tbf->dir.dl.v_a - 1) & mod_sns);
1016 i--, bsn = (bsn - 1) & mod_sns) {
1017 bit = (rbb[i >> 3] >> (7 - (i&7))) & 1;
1018 if (bit) {
1019 LOGP(DRLCMACDL, LOGL_DEBUG, "- got "
1020 "ack for BSN=%d\n", bsn);
1021 if (tbf->dir.dl.v_b[bsn & mod_sns_half]
1022 != 'A')
1023 received++;
1024 tbf->dir.dl.v_b[bsn & mod_sns_half] = 'A';
1025 } else {
1026 LOGP(DRLCMACDL, LOGL_DEBUG, "- got "
1027 "NACK for BSN=%d\n", bsn);
1028 tbf->dir.dl.v_b[bsn & mod_sns_half] = 'N';
1029 lost++;
1030 }
1031 }
1032 /* report lost and received packets */
1033 gprs_rlcmac_received_lost(tbf, received, lost);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001034
1035 /* raise V(A), if possible */
1036 for (i = 0, bsn = tbf->dir.dl.v_a; bsn != tbf->dir.dl.v_s;
1037 i++, bsn = (bsn + 1) & mod_sns) {
1038 if (tbf->dir.dl.v_b[bsn & mod_sns_half] == 'A') {
1039 tbf->dir.dl.v_b[bsn & mod_sns_half] = 'I';
1040 /* mark invalid */
1041 tbf->dir.dl.v_a = (tbf->dir.dl.v_a + 1)
1042 & mod_sns;
1043 } else
1044 break;
1045 }
1046
1047 /* show receive state array in debug (V(A)..V(S)-1) */
1048 for (i = 0, bsn = tbf->dir.dl.v_a; bsn != tbf->dir.dl.v_s;
1049 i++, bsn = (bsn + 1) & mod_sns) {
1050 show_v_b[i] = tbf->dir.dl.v_b[bsn & mod_sns_half];
1051 if (show_v_b[i] == 0)
1052 show_v_b[i] = ' ';
1053 }
1054 show_v_b[i] = '\0';
1055 LOGP(DRLCMACDL, LOGL_DEBUG, "- V(B): (V(A)=%d)\"%s\""
1056 "(V(S)-1=%d) A=Acked N=Nacked U=Unacked "
1057 "X=Resend-Unacked\n", tbf->dir.dl.v_a, show_v_b,
1058 (tbf->dir.dl.v_s - 1) & mod_sns);
1059
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +02001060 if (tbf->state_is(GPRS_RLCMAC_FINISHED)
Andreas Eversberg6664a902012-07-15 06:52:19 +02001061 && tbf->dir.dl.v_s == tbf->dir.dl.v_a) {
Andreas Eversberg0c9b50c2012-10-07 15:50:51 +02001062 LOGP(DRLCMACDL, LOGL_NOTICE, "Received acknowledge of "
1063 "all blocks, but without final ack "
1064 "inidcation (don't worry)\n");
1065 }
1066 return 0;
Andreas Eversbergb83e2a72012-10-07 15:26:00 +02001067 }
Andreas Eversberge6228b32012-07-03 13:36:03 +02001068
Andreas Eversberg0c9b50c2012-10-07 15:50:51 +02001069 LOGP(DRLCMACDL, LOGL_DEBUG, "- Final ACK received.\n");
Holger Hans Peter Freytherb65e08a2013-10-20 17:10:25 +02001070 debug_diagram(tbf->bts, tbf->diag, "got Final ACK");
Andreas Eversberg050ace22013-03-16 16:22:02 +01001071 /* range V(A)..V(S)-1 */
1072 for (bsn = tbf->dir.dl.v_a; bsn != tbf->dir.dl.v_s;
1073 bsn = (bsn + 1) & mod_sns) {
1074 if (tbf->dir.dl.v_b[bsn & mod_sns_half] != 'A')
1075 received++;
1076 }
1077
1078 /* report all outstanding packets as received */
1079 gprs_rlcmac_received_lost(tbf, received, lost);
Andreas Eversberg0c9b50c2012-10-07 15:50:51 +02001080
Andreas Eversberge6228b32012-07-03 13:36:03 +02001081 /* check for LLC PDU in the LLC Queue */
Holger Hans Peter Freyther1702f102013-10-20 08:44:02 +02001082 msg = tbf->llc_dequeue(gprs_bssgp_pcu_current_bctx());
Andreas Eversberge6228b32012-07-03 13:36:03 +02001083 if (!msg) {
Andreas Eversberge6228b32012-07-03 13:36:03 +02001084 /* no message, start T3193, change state to RELEASE */
1085 LOGP(DRLCMACDL, LOGL_DEBUG, "- No new message, so we "
1086 "release.\n");
Andreas Eversbergb3c6f6c2012-07-06 07:40:08 +02001087 /* start T3193 */
Holger Hans Peter Freyther34bd8bd2013-10-19 21:10:38 +02001088 debug_diagram(bts->bts, tbf->diag, "start T3193");
Holger Hans Peter Freytherb65e08a2013-10-20 17:10:25 +02001089 tbf_timer_start(tbf, 3193,
1090 tbf->bts->bts_data()->t3193_msec / 1000,
1091 (tbf->bts->bts_data()->t3193_msec % 1000) * 1000);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001092 tbf_new_state(tbf, GPRS_RLCMAC_WAIT_RELEASE);
1093
1094 return 0;
1095 }
Holger Hans Peter Freyther1702f102013-10-20 08:44:02 +02001096 #warning "Copy and paste on the sender path"
1097 tbf->update_llc_frame(msg);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001098 msgb_free(msg);
1099
1100 /* we have a message, so we trigger downlink assignment, and there
1101 * set the state to ASSIGN. also we set old_downlink, because we
1102 * re-use this tbf. */
1103 LOGP(DRLCMAC, LOGL_DEBUG, "Trigger dowlink assignment on PACCH, "
1104 "because another LLC PDU has arrived in between\n");
1105 memset(&tbf->dir.dl, 0, sizeof(tbf->dir.dl)); /* reset RLC states */
Andreas Eversberga9be1542012-09-27 09:23:24 +02001106 tbf->state_flags &= GPRS_RLCMAC_FLAG_TO_MASK; /* keep TO flags */
1107 tbf->state_flags &= ~(1 << GPRS_RLCMAC_FLAG_CCCH);
Holger Hans Peter Freyther9f0c1d22013-10-19 21:24:34 +02001108 tbf_update(tbf);
Holger Hans Peter Freytherb65e08a2013-10-20 17:10:25 +02001109 gprs_rlcmac_trigger_downlink_assignment(tbf, tbf, NULL);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001110
1111 return 0;
1112}
1113
1114
1115struct msgb *gprs_rlcmac_send_packet_downlink_assignment(
1116 struct gprs_rlcmac_tbf *tbf, uint32_t fn)
1117{
1118 struct msgb *msg;
1119 struct gprs_rlcmac_tbf *new_tbf;
Holger Hans Peter Freytherb65e08a2013-10-20 17:10:25 +02001120 gprs_rlcmac_bts *bts = tbf->bts->bts_data();
Andreas Eversberg802bb6e2012-08-06 11:15:05 +02001121 int poll_ass_dl = POLLING_ASSIGNMENT_DL;
Andreas Eversberge6228b32012-07-03 13:36:03 +02001122
Andreas Eversberg802bb6e2012-08-06 11:15:05 +02001123 if (poll_ass_dl && tbf->direction == GPRS_RLCMAC_DL_TBF
1124 && tbf->control_ts != tbf->first_common_ts) {
1125 LOGP(DRLCMAC, LOGL_NOTICE, "Cannot poll for downlink "
Andreas Eversbergf01929b2012-10-08 12:40:49 +02001126 "assigment, because MS cannot reply. (control TS=%d, "
1127 "first common TS=%d)\n", tbf->control_ts,
1128 tbf->first_common_ts);
Andreas Eversberg802bb6e2012-08-06 11:15:05 +02001129 poll_ass_dl = 0;
Andreas Eversberge6228b32012-07-03 13:36:03 +02001130 }
Andreas Eversberg802bb6e2012-08-06 11:15:05 +02001131 if (poll_ass_dl) {
1132 if (tbf->poll_state != GPRS_RLCMAC_POLL_NONE) {
1133 LOGP(DRLCMAC, LOGL_DEBUG, "Polling is already sheduled "
1134 "for TBF=%d, so we must wait for downlink "
1135 "assignment...\n", tbf->tfi);
1136 return NULL;
1137 }
Holger Hans Peter Freytherb65e08a2013-10-20 17:10:25 +02001138 if (tbf->bts->sba()->find(tbf->trx_no, tbf->control_ts, (fn + 13) % 2715648)) {
Andreas Eversberg07e97cf2012-08-07 16:00:56 +02001139 LOGP(DRLCMACUL, LOGL_DEBUG, "Polling is already "
1140 "scheduled for single block allocation...\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +02001141 return NULL;
Andreas Eversberg07e97cf2012-08-07 16:00:56 +02001142 }
Andreas Eversberge6228b32012-07-03 13:36:03 +02001143 }
1144
1145 /* on uplink TBF we get the downlink TBF to be assigned. */
Andreas Eversbergee31b782012-07-15 16:27:01 +02001146 if (tbf->direction == GPRS_RLCMAC_UL_TBF) {
1147 /* be sure to check first, if contention resolution is done,
1148 * otherwise we cannot send the assignment yet */
Andreas Eversberg08e93cd2012-07-26 08:13:06 +02001149 if (!tbf->dir.ul.contention_resolution_done) {
Andreas Eversberg7f5352c2012-07-23 18:20:36 +02001150 LOGP(DRLCMAC, LOGL_DEBUG, "Cannot assign DL TBF now, "
Andreas Eversbergee31b782012-07-15 16:27:01 +02001151 "because contention resolution is not "
1152 "finished.\n");
1153 return NULL;
1154 }
Holger Hans Peter Freytherb65e08a2013-10-20 17:10:25 +02001155 new_tbf = tbf->bts->tbf_by_tlli(tbf->tlli, GPRS_RLCMAC_DL_TBF);
Andreas Eversbergee31b782012-07-15 16:27:01 +02001156 } else
Andreas Eversberge6228b32012-07-03 13:36:03 +02001157 new_tbf = tbf;
1158 if (!new_tbf) {
1159 LOGP(DRLCMACDL, LOGL_ERROR, "We have a schedule for downlink "
1160 "assignment at uplink TBF=%d, but there is no downlink "
1161 "TBF\n", tbf->tfi);
1162 tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE;
1163 return NULL;
1164 }
1165
1166 msg = msgb_alloc(23, "rlcmac_dl_ass");
1167 if (!msg)
1168 return NULL;
1169 bitvec *ass_vec = bitvec_alloc(23);
1170 if (!ass_vec) {
1171 msgb_free(msg);
1172 return NULL;
1173 }
1174 bitvec_unhex(ass_vec,
1175 "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
Andreas Eversberg0e403092012-07-06 11:04:57 +02001176 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 +02001177 RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)talloc_zero(tall_pcu_ctx, RlcMacDownlink_t);
Holger Hans Peter Freyther63f29d62013-10-19 19:04:03 +02001178 Encoding::write_packet_downlink_assignment(mac_control_block, tbf->tfi,
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001179 (tbf->direction == GPRS_RLCMAC_DL_TBF), new_tbf,
Andreas Eversbergafdd9e12012-10-07 17:08:55 +02001180 poll_ass_dl, bts->alpha, bts->gamma, -1, 0);
Andreas Eversberg0e403092012-07-06 11:04:57 +02001181 LOGP(DRLCMAC, LOGL_DEBUG, "+++++++++++++++++++++++++ TX : Packet Downlink Assignment +++++++++++++++++++++++++\n");
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001182 encode_gsm_rlcmac_downlink(ass_vec, mac_control_block);
Andreas Eversberg0e403092012-07-06 11:04:57 +02001183 LOGPC(DCSN1, LOGL_NOTICE, "\n");
1184 LOGP(DRLCMAC, LOGL_DEBUG, "------------------------- TX : Packet Downlink Assignment -------------------------\n");
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001185 bitvec_pack(ass_vec, msgb_put(msg, 23));
Andreas Eversberge6228b32012-07-03 13:36:03 +02001186 bitvec_free(ass_vec);
Andreas Eversberg6681bb82012-07-25 08:48:44 +02001187 talloc_free(mac_control_block);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001188
Andreas Eversberg802bb6e2012-08-06 11:15:05 +02001189 if (poll_ass_dl) {
1190 tbf->poll_state = GPRS_RLCMAC_POLL_SCHED;
1191 tbf->poll_fn = (fn + 13) % 2715648;
1192 tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_WAIT_ACK;
1193 } else {
1194 tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE;
1195 tbf_new_state(new_tbf, GPRS_RLCMAC_FLOW);
1196 tbf_assign_control_ts(new_tbf);
Andreas Eversbergcbcd1242012-08-07 15:48:21 +02001197 /* stop pending assignment timer */
1198 tbf_timer_stop(new_tbf);
1199
Andreas Eversberg802bb6e2012-08-06 11:15:05 +02001200 }
Holger Hans Peter Freyther34bd8bd2013-10-19 21:10:38 +02001201 debug_diagram(bts->bts, tbf->diag, "send DL-ASS");
Andreas Eversberge6228b32012-07-03 13:36:03 +02001202
1203 return msg;
1204}
1205
Holger Hans Peter Freytherb65e08a2013-10-20 17:10:25 +02001206static void gprs_rlcmac_downlink_assignment(
Holger Hans Peter Freyther344ff482013-10-17 12:01:04 +02001207 gprs_rlcmac_tbf *tbf, uint8_t poll,
Holger Hans Peter Freyther52c911b2013-08-24 18:30:54 +02001208 const char *imsi)
Andreas Eversberge6228b32012-07-03 13:36:03 +02001209{
Holger Hans Peter Freytherb65e08a2013-10-20 17:10:25 +02001210 gprs_rlcmac_bts *bts = tbf->bts->bts_data();
Andreas Eversbergaafcbbb2012-09-27 09:20:45 +02001211 int plen;
1212
Holger Hans Peter Freyther34bd8bd2013-10-19 21:10:38 +02001213 debug_diagram(bts->bts, tbf->diag, "IMM.ASS (PCH)");
Andreas Eversberge13fa2d2012-07-09 17:10:44 +02001214 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 +02001215 bitvec *immediate_assignment = bitvec_alloc(22); /* without plen */
1216 bitvec_unhex(immediate_assignment, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
Andreas Eversberge6228b32012-07-03 13:36:03 +02001217 /* use request reference that has maximum distance to current time,
1218 * so the assignment will not conflict with possible RACH requests. */
Holger Hans Peter Freyther63f29d62013-10-19 19:04:03 +02001219 plen = Encoding::write_immediate_assignment(bts, immediate_assignment, 1, 125,
Andreas Eversbergaafcbbb2012-09-27 09:20:45 +02001220 (tbf->pdch[tbf->first_ts]->last_rts_fn + 21216) % 2715648, tbf->ta,
1221 tbf->arfcn, tbf->first_ts, tbf->tsc, tbf->tfi, 0, tbf->tlli, poll,
Andreas Eversbergafdd9e12012-10-07 17:08:55 +02001222 tbf->poll_fn, 0, bts->alpha, bts->gamma, -1);
Andreas Eversberge13fa2d2012-07-09 17:10:44 +02001223 pcu_l1if_tx_pch(immediate_assignment, plen, imsi);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001224 bitvec_free(immediate_assignment);
1225}
1226
1227/* depending on the current TBF, we assign on PACCH or AGCH */
Holger Hans Peter Freytherb65e08a2013-10-20 17:10:25 +02001228void gprs_rlcmac_trigger_downlink_assignment(
Holger Hans Peter Freyther344ff482013-10-17 12:01:04 +02001229 struct gprs_rlcmac_tbf *tbf,
Holger Hans Peter Freyther52c911b2013-08-24 18:30:54 +02001230 struct gprs_rlcmac_tbf *old_tbf, const char *imsi)
Andreas Eversberge6228b32012-07-03 13:36:03 +02001231{
Andreas Eversberge6228b32012-07-03 13:36:03 +02001232#ifdef DEBUG_DL_ASS_IDLE
Andreas Eversberge13fa2d2012-07-09 17:10:44 +02001233 strncpy(debug_imsi, imsi);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001234 LOGP(DRLCMAC, LOGL_ERROR, "**** DEBUGGING DOWNLINK ASSIGNMENT ****\n");
1235#endif
1236
1237 /* stop pending timer */
1238 tbf_timer_stop(tbf);
1239
1240 /* check for downlink tbf: */
Andreas Eversberge6228b32012-07-03 13:36:03 +02001241 if (old_tbf) {
1242#ifdef DEBUG_DL_ASS_IDLE
1243 LOGP(DRLCMAC, LOGL_ERROR, "We must wait for current TBF to be "
1244 "released.\n");
1245 /* wait one second until assignment */
1246 tbf_timer_start(tbf, 1234, 1,0);
1247#else
Andreas Eversberg0e403092012-07-06 11:04:57 +02001248 LOGP(DRLCMAC, LOGL_DEBUG, "Send dowlink assignment on "
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001249 "PACCH, because %s TBF=%d exists for TLLI=0x%08x\n",
Andreas Eversberg7f5352c2012-07-23 18:20:36 +02001250 (old_tbf->direction == GPRS_RLCMAC_UL_TBF)
1251 ? "UL" : "DL", old_tbf->tfi, old_tbf->tlli);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001252 old_tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_SEND_ASS;
1253 /* use TA from old TBF */
1254 tbf->ta = old_tbf->ta;
1255 /* change state */
1256 tbf_new_state(tbf, GPRS_RLCMAC_ASSIGN);
Andreas Eversberg14db19e2012-08-06 15:03:03 +02001257 tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_PACCH);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001258 /* start timer */
1259 tbf_timer_start(tbf, 0, Tassign_pacch);
1260#endif
1261 } else {
Andreas Eversberge13fa2d2012-07-09 17:10:44 +02001262 LOGP(DRLCMAC, LOGL_DEBUG, "Send dowlink assignment for TBF=%d on PCH, no TBF exist (IMSI=%s)\n", tbf->tfi, imsi);
1263 if (!imsi || strlen(imsi) < 3) {
1264 LOGP(DRLCMAC, LOGL_ERROR, "No valid IMSI!\n");
1265 return;
1266 }
Andreas Eversberge6228b32012-07-03 13:36:03 +02001267 /* change state */
1268 tbf_new_state(tbf, GPRS_RLCMAC_ASSIGN);
Andreas Eversberg14db19e2012-08-06 15:03:03 +02001269 tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_CCCH);
Andreas Eversberga9be1542012-09-27 09:23:24 +02001270 strncpy(tbf->dir.dl.imsi, imsi, sizeof(tbf->dir.dl.imsi));
Andreas Eversberg7438df72012-07-23 18:04:49 +02001271 /* send immediate assignment */
Holger Hans Peter Freytherb65e08a2013-10-20 17:10:25 +02001272 gprs_rlcmac_downlink_assignment(tbf, 0, imsi);
Andreas Eversberga9be1542012-09-27 09:23:24 +02001273 tbf->dir.dl.wait_confirm = 1;
1274 }
1275}
1276
Holger Hans Peter Freyther34bd8bd2013-10-19 21:10:38 +02001277int gprs_rlcmac_imm_ass_cnf(BTS *bts, uint8_t *data, uint32_t fn)
Andreas Eversberga9be1542012-09-27 09:23:24 +02001278{
1279 struct gprs_rlcmac_tbf *tbf;
1280 uint8_t plen;
1281 uint32_t tlli;
1282
1283 /* move to IA Rest Octets */
1284 plen = data[0] >> 2;
1285 data += 1 + plen;
1286
1287 if ((*data & 0xf0) != 0xd0) {
1288 LOGP(DRLCMAC, LOGL_ERROR, "Got IMM.ASS confirm, but rest "
1289 "octets do not start with bit sequence 'HH01' "
1290 "(Packet Downlink Assignment)\n");
1291 return -EINVAL;
1292 }
1293
1294 /* get TLLI from downlink assignment */
1295 tlli = (*data++) << 28;
1296 tlli |= (*data++) << 20;
1297 tlli |= (*data++) << 12;
1298 tlli |= (*data++) << 4;
1299 tlli |= (*data++) >> 4;
1300
Holger Hans Peter Freyther34bd8bd2013-10-19 21:10:38 +02001301 tbf = bts->tbf_by_tlli(tlli, GPRS_RLCMAC_DL_TBF);
Andreas Eversberga9be1542012-09-27 09:23:24 +02001302 if (!tbf) {
1303 LOGP(DRLCMAC, LOGL_ERROR, "Got IMM.ASS confirm, but TLLI=%08x "
1304 "does not exit\n", tlli);
1305 return -EINVAL;
1306 }
1307
1308 LOGP(DRLCMAC, LOGL_DEBUG, "Got IMM.ASS confirm for TLLI=%08x\n", tlli);
1309
1310 if (tbf->dir.dl.wait_confirm) {
Andreas Eversberge6228b32012-07-03 13:36:03 +02001311 tbf_timer_start(tbf, 0, Tassign_agch);
1312 }
Andreas Eversberga9be1542012-09-27 09:23:24 +02001313
1314 return 0;
1315}
Andreas Eversberge6228b32012-07-03 13:36:03 +02001316