blob: 10bc017708d2500a824cc6ce359a42222ddf3eaf [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>
Andreas Eversberg66690dd2012-06-27 15:44:31 +020024
Andreas Eversbergf54a89e2012-07-16 11:56:11 +020025/* After receiving these frames, we send ack/nack. */
26#define SEND_ACK_AFTER_FRAMES 20
27
28/* After sending these frames, we poll for ack/nack. */
29#define POLL_ACK_AFTER_FRAMES 10
Andreas Eversberg66690dd2012-06-27 15:44:31 +020030
Andreas Eversberge6228b32012-07-03 13:36:03 +020031/* If acknowledgement to uplink/downlin assignmentshould be polled */
32#define POLLING_ASSIGNMENT 0
33
Andreas Eversberg66690dd2012-06-27 15:44:31 +020034extern "C" {
35/* TS 04.60 10.2.2 */
Andreas Eversberge6228b32012-07-03 13:36:03 +020036struct rlc_ul_header {
Andreas Eversberg66690dd2012-06-27 15:44:31 +020037 uint8_t r:1,
38 si:1,
39 cv:4,
40 pt:2;
41 uint8_t ti:1,
42 tfi:5,
43 pi:1,
44 spare:1;
45 uint8_t e:1,
46 bsn:7;
47} __attribute__ ((packed));
48
Andreas Eversberge6228b32012-07-03 13:36:03 +020049struct rlc_dl_header {
50 uint8_t usf:3,
51 s_p:1,
52 rrbp:2,
53 pt:2;
54 uint8_t fbi:1,
55 tfi:5,
56 pr:2;
57 uint8_t e:1,
58 bsn:7;
59} __attribute__ ((packed));
60
Andreas Eversberg66690dd2012-06-27 15:44:31 +020061struct rlc_li_field {
62 uint8_t e:1,
63 m:1,
64 li:6;
65} __attribute__ ((packed));
66}
67
Andreas Eversberge6228b32012-07-03 13:36:03 +020068int gprs_rlcmac_poll_timeout(struct gprs_rlcmac_tbf *tbf)
69{
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +020070 LOGP(DRLCMAC, LOGL_NOTICE, "Poll timeout for %s TBF=%d\n",
71 (tbf->direction == GPRS_RLCMAC_UL_TBF) ? "UL" : "DL", tbf->tfi);
Andreas Eversberge6228b32012-07-03 13:36:03 +020072
73 tbf->poll_state = GPRS_RLCMAC_POLL_NONE;
74
75 if (tbf->ul_ack_state == GPRS_RLCMAC_UL_ACK_WAIT_ACK) {
Andreas Eversberg4b470ff2012-07-16 12:02:40 +020076 LOGP(DRLCMAC, LOGL_NOTICE, "- Timeout for polling PACKET "
Andreas Eversberge6228b32012-07-03 13:36:03 +020077 "CONTROL ACK for PACKET UPLINK ACK\n");
78 tbf->ul_ack_state = GPRS_RLCMAC_UL_ACK_NONE;
79 if (tbf->state == GPRS_RLCMAC_FINISHED) {
Andreas Eversbergdfa563c2012-07-06 08:13:59 +020080 struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
81
Andreas Eversberge6228b32012-07-03 13:36:03 +020082 tbf->dir.ul.n3103++;
Andreas Eversbergdfa563c2012-07-06 08:13:59 +020083 if (tbf->dir.ul.n3103 == bts->n3103) {
Andreas Eversberg4b470ff2012-07-16 12:02:40 +020084 LOGP(DRLCMAC, LOGL_NOTICE,
85 "- N3103 exceeded\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +020086 tbf_new_state(tbf, GPRS_RLCMAC_RELEASING);
Andreas Eversbergdfa563c2012-07-06 08:13:59 +020087 tbf_timer_start(tbf, 3169, bts->t3169, 0);
Andreas Eversberge6228b32012-07-03 13:36:03 +020088 return 0;
89 }
90 /* reschedule UL ack */
91 tbf->ul_ack_state = GPRS_RLCMAC_UL_ACK_SEND_ACK;
92 }
93 } else
94 if (tbf->ul_ass_state == GPRS_RLCMAC_UL_ASS_WAIT_ACK) {
Andreas Eversberg4b470ff2012-07-16 12:02:40 +020095 LOGP(DRLCMAC, LOGL_NOTICE, "- Timeout for polling PACKET "
Andreas Eversberge6228b32012-07-03 13:36:03 +020096 "CONTROL ACK for PACKET UPLINK ASSIGNMENT.\n");
97 tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_NONE;
98 } else
99 if (tbf->dl_ass_state == GPRS_RLCMAC_DL_ASS_WAIT_ACK) {
Andreas Eversberg4b470ff2012-07-16 12:02:40 +0200100 LOGP(DRLCMAC, LOGL_NOTICE, "- Timeout for polling PACKET "
Andreas Eversberge6228b32012-07-03 13:36:03 +0200101 "CONTROL ACK for PACKET DOWNLINK ASSIGNMENT.\n");
102 tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE;
103 /* in case out downlink assigment failed: */
104 if (tbf->state == GPRS_RLCMAC_ASSIGN) {
Andreas Eversberg4b470ff2012-07-16 12:02:40 +0200105 LOGP(DRLCMAC, LOGL_NOTICE, "- Assignment failed\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200106 tbf_free(tbf);
107 }
108 } else
109 if (tbf->direction == GPRS_RLCMAC_DL_TBF)
110 {
Andreas Eversbergdfa563c2012-07-06 08:13:59 +0200111 struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
112
Andreas Eversberg4b470ff2012-07-16 12:02:40 +0200113 LOGP(DRLCMAC, LOGL_NOTICE, "- Timeout for polling PACKET "
Andreas Eversberge6228b32012-07-03 13:36:03 +0200114 " DOWNLINK ACK.\n");
115 tbf->dir.dl.n3105++;
Andreas Eversbergdfa563c2012-07-06 08:13:59 +0200116 if (tbf->dir.dl.n3105 == bts->n3105) {
Andreas Eversberg4b470ff2012-07-16 12:02:40 +0200117 LOGP(DRLCMAC, LOGL_NOTICE, "- N3105 exceeded\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200118 tbf_new_state(tbf, GPRS_RLCMAC_RELEASING);
Andreas Eversbergdfa563c2012-07-06 08:13:59 +0200119 tbf_timer_start(tbf, 3195, bts->t3195, 0);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200120 return 0;
121 }
Andreas Eversberg4b470ff2012-07-16 12:02:40 +0200122 } else
123 LOGP(DRLCMAC, LOGL_ERROR, "- Poll Timeout, but no event!\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200124
125 return 0;
126}
127
128/* Received Uplink RLC control block. */
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200129int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts,
130 uint32_t fn)
Andreas Eversberge6228b32012-07-03 13:36:03 +0200131{
Andreas Eversbergc8466f42012-07-15 19:34:53 +0200132 struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200133 int8_t tfi = 0; /* must be signed */
Andreas Eversberge6228b32012-07-03 13:36:03 +0200134 uint32_t tlli = 0;
135 struct gprs_rlcmac_tbf *tbf;
Andreas Eversberg0f13c402012-07-16 11:59:23 +0200136 int rc;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200137
138 RlcMacUplink_t * ul_control_block = (RlcMacUplink_t *)malloc(sizeof(RlcMacUplink_t));
Andreas Eversberg0e403092012-07-06 11:04:57 +0200139 LOGP(DRLCMAC, LOGL_DEBUG, "+++++++++++++++++++++++++ RX : Uplink Control Block +++++++++++++++++++++++++\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200140 decode_gsm_rlcmac_uplink(rlc_block, ul_control_block);
Andreas Eversberg0e403092012-07-06 11:04:57 +0200141 LOGPC(DCSN1, LOGL_NOTICE, "\n");
142 LOGP(DRLCMAC, LOGL_DEBUG, "------------------------- RX : Uplink Control Block -------------------------\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200143 switch (ul_control_block->u.MESSAGE_TYPE) {
144 case MT_PACKET_CONTROL_ACK:
145 tlli = ul_control_block->u.Packet_Control_Acknowledgement.TLLI;
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200146 tbf = tbf_by_poll_fn(fn, trx, ts);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200147 if (!tbf) {
148 LOGP(DRLCMAC, LOGL_NOTICE, "PACKET CONTROL ACK with "
Andreas Eversberg592e04a2012-07-15 06:25:37 +0200149 "unknown FN=%u TLL=0x%08x (TRX %d TS %d)\n",
150 fn, tlli, trx, ts);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200151 break;
152 }
153 tfi = tbf->tfi;
154 if (tlli != tbf->tlli) {
Andreas Eversberg0e403092012-07-06 11:04:57 +0200155 LOGP(DRLCMAC, LOGL_INFO, "Phone changed TLLI to "
Andreas Eversberge6228b32012-07-03 13:36:03 +0200156 "0x%08x\n", tlli);
157 tbf->tlli = tlli;
158 }
Andreas Eversberg0e403092012-07-06 11:04:57 +0200159 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 +0200160 tbf->poll_state = GPRS_RLCMAC_POLL_NONE;
161
162 /* check if this control ack belongs to packet uplink ack */
163 if (tbf->ul_ack_state == GPRS_RLCMAC_UL_ACK_WAIT_ACK) {
Andreas Eversberg0e403092012-07-06 11:04:57 +0200164 LOGP(DRLCMAC, LOGL_DEBUG, "TBF: [UPLINK] END TFI: %u TLLI: 0x%08x \n", tbf->tfi, tbf->tlli);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200165 tbf->ul_ack_state = GPRS_RLCMAC_UL_ACK_NONE;
166 tbf_free(tbf);
167 break;
168 }
169 if (tbf->dl_ass_state == GPRS_RLCMAC_DL_ASS_WAIT_ACK) {
Andreas Eversberg0e403092012-07-06 11:04:57 +0200170 LOGP(DRLCMAC, LOGL_DEBUG, "TBF: [UPLINK] DOWNLINK ASSIGNED TFI: %u TLLI: 0x%08x \n", tbf->tfi, tbf->tlli);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200171 tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE;
172 break;
173 }
174 if (tbf->ul_ass_state == GPRS_RLCMAC_UL_ASS_WAIT_ACK) {
Andreas Eversberg0e403092012-07-06 11:04:57 +0200175 LOGP(DRLCMAC, LOGL_DEBUG, "TBF: [DOWNLINK] UPLINK ASSIGNED TFI: %u TLLI: 0x%08x \n", tbf->tfi, tbf->tlli);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200176 tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_NONE;
177 break;
178 }
179 LOGP(DRLCMAC, LOGL_ERROR, "Error: received PACET CONTROL ACK "
180 "at no request\n");
181 break;
182 case MT_PACKET_DOWNLINK_ACK_NACK:
183 tfi = ul_control_block->u.Packet_Downlink_Ack_Nack.DOWNLINK_TFI;
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200184 tbf = tbf_by_poll_fn(fn, trx, ts);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200185 if (!tbf) {
186 LOGP(DRLCMAC, LOGL_NOTICE, "PACKET DOWNLINK ACK with "
Andreas Eversberg592e04a2012-07-15 06:25:37 +0200187 "unknown FN=%u TBF=%d (TRX %d TS %d)\n",
188 fn, tfi, trx, ts);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200189 break;
190 }
191 /* reset N3105 */
192 tbf->dir.dl.n3105 = 0;
193 /* stop timer T3191 */
194 tbf_timer_stop(tbf);
195 tlli = tbf->tlli;
Andreas Eversberg0e403092012-07-06 11:04:57 +0200196 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 +0200197 tbf->poll_state = GPRS_RLCMAC_POLL_NONE;
198
Andreas Eversberg0f13c402012-07-16 11:59:23 +0200199 rc = gprs_rlcmac_downlink_ack(tbf,
Andreas Eversberge6228b32012-07-03 13:36:03 +0200200 ul_control_block->u.Packet_Downlink_Ack_Nack.Ack_Nack_Description.FINAL_ACK_INDICATION,
201 ul_control_block->u.Packet_Downlink_Ack_Nack.Ack_Nack_Description.STARTING_SEQUENCE_NUMBER,
202 ul_control_block->u.Packet_Downlink_Ack_Nack.Ack_Nack_Description.RECEIVED_BLOCK_BITMAP);
Andreas Eversberg0f13c402012-07-16 11:59:23 +0200203 if (rc == 1) {
204 tbf_free(tbf);
205 break;
206 }
Andreas Eversberge6228b32012-07-03 13:36:03 +0200207 /* check for channel request */
208 if (ul_control_block->u.Packet_Downlink_Ack_Nack.Exist_Channel_Request_Description) {
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200209 uint8_t trx, ts;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200210 struct gprs_rlcmac_tbf *ul_tbf;
211
212 LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF in ack "
213 "message, so we provide one:\n");
214uplink_request:
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200215 /* create new TBF, use sme TRX as DL TBF */
216 tfi = tfi_alloc(GPRS_RLCMAC_UL_TBF, &trx, &ts, tbf->trx, tbf->first_ts);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200217 if (tfi < 0) {
218 LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n");
219 /* FIXME: send reject */
220 break;
221 }
Andreas Eversbergf298fa82012-07-13 14:50:57 +0200222 /* use multislot class of downlink TBF */
Andreas Eversberg592e04a2012-07-15 06:25:37 +0200223 ul_tbf = tbf_alloc(tbf, GPRS_RLCMAC_UL_TBF, tfi, trx,
224 ts, tbf->ms_class, 0);
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200225 if (!ul_tbf) {
226 LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200227 /* FIXME: send reject */
228 break;
229 }
Andreas Eversberge6228b32012-07-03 13:36:03 +0200230 ul_tbf->tlli = tbf->tlli;
Andreas Eversbergee31b782012-07-15 16:27:01 +0200231 ul_tbf->tlli_valid = 1; /* no contention resolution */
Andreas Eversberg67a19762012-07-15 19:35:46 +0200232 ul_tbf->contention_resolution_done = 1;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200233 ul_tbf->ta = tbf->ta; /* use current TA */
Andreas Eversberge6228b32012-07-03 13:36:03 +0200234 tbf_new_state(ul_tbf, GPRS_RLCMAC_FLOW);
Andreas Eversbergdfa563c2012-07-06 08:13:59 +0200235 tbf_timer_start(ul_tbf, 3169, bts->t3169, 0);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200236 /* schedule uplink assignment */
237 tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS;
238 }
239 break;
240 case MT_PACKET_RESOURCE_REQUEST:
241 if (ul_control_block->u.Packet_Resource_Request.ID.UnionType) {
242 tlli = ul_control_block->u.Packet_Resource_Request.ID.u.TLLI;
243 tbf = tbf_by_tlli(tlli, GPRS_RLCMAC_UL_TBF);
244 if (!tbf) {
245 LOGP(DRLCMAC, LOGL_NOTICE, "PACKET RESSOURCE REQ unknown uplink TLLI=0x%08x\n", tlli);
246 break;
247 }
248 tfi = tbf->tfi;
249 } else {
250 if (ul_control_block->u.Packet_Resource_Request.ID.u.Global_TFI.UnionType) {
251 tfi = ul_control_block->u.Packet_Resource_Request.ID.u.Global_TFI.u.DOWNLINK_TFI;
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200252 tbf = tbf_by_tfi(tfi, trx, ts, GPRS_RLCMAC_DL_TBF);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200253 if (!tbf) {
Andreas Eversberg0e403092012-07-06 11:04:57 +0200254 LOGP(DRLCMAC, LOGL_NOTICE, "PACKET RESSOURCE REQ unknown downlink TBF=%d\n", tlli);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200255 break;
256 }
257 } else {
258 tfi = ul_control_block->u.Packet_Resource_Request.ID.u.Global_TFI.u.UPLINK_TFI;
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200259 tbf = tbf_by_tfi(tfi, trx, ts, GPRS_RLCMAC_UL_TBF);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200260 if (!tbf) {
Andreas Eversberg0e403092012-07-06 11:04:57 +0200261 LOGP(DRLCMAC, LOGL_NOTICE, "PACKET RESSOURCE REQ unknown uplink TBF=%d\n", tlli);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200262 break;
263 }
264 }
265 tlli = tbf->tlli;
266 }
Andreas Eversbergc8466f42012-07-15 19:34:53 +0200267 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 +0200268 break;
269 default:
Andreas Eversberg0e403092012-07-06 11:04:57 +0200270 LOGP(DRLCMAC, LOGL_NOTICE, "RX: [PCU <- BTS] unknown control block received\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200271 }
272 free(ul_control_block);
273 return 1;
274}
275
Andreas Eversberge13fa2d2012-07-09 17:10:44 +0200276#ifdef DEBUG_DL_ASS_IDLE
277 char debug_imsi[16];
278#endif
Andreas Eversberge6228b32012-07-03 13:36:03 +0200279
280void tbf_timer_cb(void *_tbf)
281{
282 struct gprs_rlcmac_tbf *tbf = (struct gprs_rlcmac_tbf *)_tbf;
283
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200284 LOGP(DRLCMAC, LOGL_DEBUG, "%s TBF=%d timer %u expired.\n",
285 (tbf->direction == GPRS_RLCMAC_UL_TBF) ? "UL" : "DL", tbf->tfi,
Andreas Eversberge6228b32012-07-03 13:36:03 +0200286 tbf->T);
287
288 tbf->num_T_exp++;
289
290 switch (tbf->T) {
291#ifdef DEBUG_DL_ASS_IDLE
292 case 1234:
Andreas Eversberge13fa2d2012-07-09 17:10:44 +0200293 gprs_rlcmac_trigger_downlink_assignment(tbf, 0, debug_imsi);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200294 break;
295#endif
296 case 0: /* assignment */
297 /* change state to FLOW, so scheduler will start transmission */
Andreas Eversberg592e04a2012-07-15 06:25:37 +0200298 if (tbf->state == GPRS_RLCMAC_ASSIGN) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200299 tbf_new_state(tbf, GPRS_RLCMAC_FLOW);
Andreas Eversberg592e04a2012-07-15 06:25:37 +0200300 tbf_assign_control_ts(tbf);
301 } else
Andreas Eversberge6228b32012-07-03 13:36:03 +0200302 LOGP(DRLCMAC, LOGL_ERROR, "Error: TBF is not in assign "
303 "state\n");
304 break;
305 case 3169:
306 case 3191:
Andreas Eversberge6228b32012-07-03 13:36:03 +0200307 case 3195:
Andreas Eversberg0e403092012-07-06 11:04:57 +0200308 LOGP(DRLCMAC, LOGL_NOTICE, "TBF T%d timeout during "
309 "transsmission\n", tbf->T);
310 /* fall through */
311 case 3193:
Andreas Eversberge6228b32012-07-03 13:36:03 +0200312 LOGP(DRLCMAC, LOGL_DEBUG, "TBF will be freed due to timeout\n");
313 /* free TBF */
314 tbf_free(tbf);
315 break;
316 default:
317 LOGP(DRLCMAC, LOGL_ERROR, "Timer expired in unknown mode: %u\n",
318 tbf->T);
319 }
320}
321
322/*
323 * UL data block flow
324 */
325
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200326/* get TLLI from received UL data block */
327static int tlli_from_ul_data(uint8_t *data, uint8_t len, uint32_t *tlli)
328{
Andreas Eversberge6228b32012-07-03 13:36:03 +0200329 struct rlc_ul_header *rh = (struct rlc_ul_header *)data;
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200330 struct rlc_li_field *li;
331 uint8_t e;
332
333 if (!rh->ti)
334 return -EINVAL;
335
336 data += 3;
337 len -= 3;
338 e = rh->e;
339 /* if E is not set (LI follows) */
340 while (!e) {
341 if (!len) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200342 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA LI extended, "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200343 "but no more data\n");
344 return -EINVAL;
345 }
346 /* get new E */
347 li = (struct rlc_li_field *)data;
348 if (li->e == 0) /* if LI==0, E is interpreted as '1' */
349 e = 1;
350 else
351 e = li->e;
352 data++;
353 len--;
354 }
355 if (len < 4) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200356 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA TLLI out of frame "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200357 "border\n");
358 return -EINVAL;
359 }
360 *tlli = ntohl(*((uint32_t *)data));
361
362 return 0;
363}
364
365/* Store received block data in LLC message(s) and forward to SGSN if complete.
366 */
367static int gprs_rlcmac_assemble_llc(struct gprs_rlcmac_tbf *tbf, uint8_t *data,
368 uint8_t len)
369{
Andreas Eversberge6228b32012-07-03 13:36:03 +0200370 struct rlc_ul_header *rh = (struct rlc_ul_header *)data;
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200371 uint8_t e, m;
372 struct rlc_li_field *li;
373 uint8_t frame_offset[16], offset = 0, chunk;
374 int i, frames = 0;
375
Andreas Eversberge6228b32012-07-03 13:36:03 +0200376 LOGP(DRLCMACUL, LOGL_DEBUG, "- Assembling frames: (len=%d)\n", len);
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200377
378 data += 3;
379 len -= 3;
380 e = rh->e; /* if extended */
381 m = 1; /* more frames, that means: the first frame */
382
383 /* Parse frame offsets from length indicator(s), if any. */
384 while (1) {
385 if (frames == (int)sizeof(frame_offset)) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200386 LOGP(DRLCMACUL, LOGL_ERROR, "Too many frames in "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200387 "block\n");
388 return -EINVAL;
389 }
390 frame_offset[frames++] = offset;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200391 LOGP(DRLCMACUL, LOGL_DEBUG, "-- Frame %d starts at offset "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200392 "%d\n", frames, offset);
393 if (!len)
394 break;
395 /* M == 0 and E == 0 is not allowed in this version. */
396 if (!m && !e) {
Andreas Eversberg0e403092012-07-06 11:04:57 +0200397 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA TBF=%d "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200398 "ignored, because M='0' and E='0'.\n",
399 tbf->tfi);
400 return 0;
401 }
402 /* no more frames in this segment */
403 if (e) {
404 break;
405 }
406 /* There is a new frame and an LI that delimits it. */
407 if (m) {
408 li = (struct rlc_li_field *)data;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200409 LOGP(DRLCMACUL, LOGL_DEBUG, "-- Delimiter len=%d\n",
410 li->li);
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200411 /* Special case: LI == 0
412 * If the last segment would fit precisely into the
413 * rest of the RLC MAC block, there would be no way
414 * to delimit that this segment ends and is not
415 * continued in the next block.
416 * The special LI (0) is used to force the segment to
417 * extend into the next block, so it is delimited there.
418 * This LI must be skipped. Also it is the last LI.
419 */
420 if (li->li == 0) {
421 data++;
422 len--;
423 m = 1; /* M is ignored, we know there is more */
424 break; /* handle E as '1', so we break! */
425 }
426 e = li->e;
427 m = li->m;
428 offset += li->li;
429 data++;
430 len--;
431 continue;
432 }
433 }
434 if (!m) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200435 LOGP(DRLCMACUL, LOGL_DEBUG, "- Last frame carries spare "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200436 "data\n");
437 }
438
Andreas Eversberge6228b32012-07-03 13:36:03 +0200439 LOGP(DRLCMACUL, LOGL_DEBUG, "- Data length after length fields: %d\n",
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200440 len);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200441 /* TLLI */
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200442 if (rh->ti) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200443 if (len < 4) {
444 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA TLLI out of "
445 "frame border\n");
446 return -EINVAL;
447 }
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200448 data += 4;
449 len -= 4;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200450 LOGP(DRLCMACUL, LOGL_DEBUG, "- Length after skipping TLLI: "
451 "%d\n", len);
452 }
453
454 /* PFI */
455 if (rh->pi) {
456 LOGP(DRLCMACUL, LOGL_ERROR, "ERROR: PFI not supported, "
457 "please disable in SYSTEM INFORMATION\n");
458 if (len < 1) {
459 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA PFI out of "
460 "frame border\n");
461 return -EINVAL;
462 }
463 data++;
464 len--;
465 LOGP(DRLCMACUL, LOGL_DEBUG, "- Length after skipping PFI: "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200466 "%d\n", len);
467 }
468
469 /* Now we have:
470 * - a list of frames offsets: frame_offset[]
471 * - number of frames: i
472 * - m == 0: Last frame carries spare data (end of TBF).
473 */
474
475 /* Check if last offset would exceed frame. */
476 if (offset > len) {
Andreas Eversberg0e403092012-07-06 11:04:57 +0200477 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA TBF=%d ignored, "
478 "because LI delimits data that exceeds block size.\n",
479 tbf->tfi);
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200480 return -EINVAL;
481 }
482
483 /* create LLC frames */
484 for (i = 0; i < frames; i++) {
485 /* last frame ? */
486 if (i == frames - 1) {
487 /* no more data in last frame */
488 if (!m)
489 break;
490 /* data until end of frame */
491 chunk = len - frame_offset[i];
492 } else {
493 /* data until next frame */
494 chunk = frame_offset[i + 1] - frame_offset[i];
495 }
Andreas Eversberge6228b32012-07-03 13:36:03 +0200496 LOGP(DRLCMACUL, LOGL_DEBUG, "-- Appending chunk (len=%d) to "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200497 "frame at %d.\n", chunk, tbf->llc_index);
498 if (tbf->llc_index + chunk > LLC_MAX_LEN) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200499 LOGP(DRLCMACUL, LOGL_NOTICE, "LLC frame exceeds "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200500 "maximum size.\n");
501 chunk = LLC_MAX_LEN - tbf->llc_index;
502 }
503 memcpy(tbf->llc_frame + tbf->llc_index, data + frame_offset[i],
504 chunk);
505 tbf->llc_index += chunk;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200506 /* not last frame. */
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200507 if (i != frames - 1) {
508 /* send frame to SGSN */
Andreas Eversberge6228b32012-07-03 13:36:03 +0200509 LOGP(DRLCMACUL, LOGL_INFO, "Complete UL frame for "
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200510 "TBF=%d: len=%d\n", tbf->tfi, tbf->llc_index);
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200511 gprs_rlcmac_tx_ul_ud(tbf);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200512 tbf->llc_index = 0; /* reset frame space */
513 /* also check if CV==0, because the frame may fill up the
514 * block precisely, then it is also complete. normally the
515 * frame would be extended into the next block with a 0-length
516 * delimiter added to this block. */
517 } else if (rh->cv == 0) {
518 /* send frame to SGSN */
519 LOGP(DRLCMACUL, LOGL_INFO, "Complete UL frame for "
Andreas Eversberg0e403092012-07-06 11:04:57 +0200520 "TBF=%d that fits precisely in last block: "
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200521 "len=%d\n", tbf->tfi, tbf->llc_index);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200522 gprs_rlcmac_tx_ul_ud(tbf);
523 tbf->llc_index = 0; /* reset frame space */
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200524 }
525 }
526
527 return 0;
528}
529
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200530struct msgb *gprs_rlcmac_send_uplink_ack(struct gprs_rlcmac_tbf *tbf,
531 uint32_t fn)
532{
533 int final = (tbf->state == GPRS_RLCMAC_FINISHED);
534 struct msgb *msg;
535
Andreas Eversberge6228b32012-07-03 13:36:03 +0200536 if (final && tbf->poll_state != GPRS_RLCMAC_POLL_NONE) {
537 LOGP(DRLCMACUL, LOGL_DEBUG, "Polling is already "
538 "sheduled for TBF=%d, so we must wait for final uplink "
539 "ack...\n", tbf->tfi);
540 return NULL;
541 }
542
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200543 msg = msgb_alloc(23, "rlcmac_ul_ack");
544 if (!msg)
545 return NULL;
546 bitvec *ack_vec = bitvec_alloc(23);
547 if (!ack_vec) {
548 msgb_free(msg);
549 return NULL;
550 }
551 bitvec_unhex(ack_vec,
552 "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +0400553 RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)malloc(sizeof(RlcMacDownlink_t));
554 write_packet_uplink_ack(mac_control_block, tbf, final);
555 encode_gsm_rlcmac_downlink(ack_vec, mac_control_block);
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200556 bitvec_pack(ack_vec, msgb_put(msg, 23));
557 bitvec_free(ack_vec);
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +0400558 free(mac_control_block);
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200559
Andreas Eversbergee31b782012-07-15 16:27:01 +0200560 /* now we must set this flag, so we are allowed to assign downlink
561 * TBF on PACCH. it is only allowed when TLLI is aknowledged. */
562 tbf->contention_resolution_done = 1;
563
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200564 if (final) {
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200565 tbf->poll_state = GPRS_RLCMAC_POLL_SCHED;
566 tbf->poll_fn = (fn + 13) % 2715648;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200567 /* waiting for final acknowledge */
568 tbf->ul_ack_state = GPRS_RLCMAC_UL_ACK_WAIT_ACK;
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200569 } else
Andreas Eversberge6228b32012-07-03 13:36:03 +0200570 tbf->ul_ack_state = GPRS_RLCMAC_UL_ACK_NONE;
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200571
572 return msg;
573}
574
575/* receive UL data block
576 *
577 * The blocks are defragmented and forwarded as LLC frames, if complete.
578 */
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200579int gprs_rlcmac_rcv_data_block_acknowledged(uint8_t trx, uint8_t ts,
580 uint8_t *data, uint8_t len)
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200581{
Andreas Eversbergdfa563c2012-07-06 08:13:59 +0200582 struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200583 struct gprs_rlcmac_tbf *tbf;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200584 struct rlc_ul_header *rh = (struct rlc_ul_header *)data;
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200585 uint16_t mod_sns, mod_sns_half, offset_v_q, offset_v_r, index;
586 int rc;
587
Andreas Eversbergdfa563c2012-07-06 08:13:59 +0200588 switch (len) {
589 case 54:
590 /* omitting spare bits */
591 len = 53;
592 break;
593 case 40:
594 /* omitting spare bits */
595 len = 39;
596 break;
597 case 34:
598 /* omitting spare bits */
599 len = 33;
600 break;
601 case 23:
602 break;
603 default:
604 LOGP(DRLCMACUL, LOGL_ERROR, "Dropping data block with invalid"
605 "length: %d)\n", len);
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200606 return -EINVAL;
607 }
608
609 /* find TBF inst from given TFI */
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200610 tbf = tbf_by_tfi(rh->tfi, trx, ts, GPRS_RLCMAC_UL_TBF);
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200611 if (!tbf) {
Andreas Eversberg0e403092012-07-06 11:04:57 +0200612 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA unknown TBF=%d\n",
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200613 rh->tfi);
614 return 0;
615 }
616
Andreas Eversberg0e403092012-07-06 11:04:57 +0200617 LOGP(DRLCMACUL, LOGL_DEBUG, "UL DATA TBF=%d received (V(Q)=%d .. "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200618 "V(R)=%d)\n", rh->tfi, tbf->dir.ul.v_q, tbf->dir.ul.v_r);
619
620 /* get TLLI */
621 if (!tbf->tlli_valid) {
622 /* no TLLI yet */
623 if (!rh->ti) {
Andreas Eversberg0e403092012-07-06 11:04:57 +0200624 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA TBF=%d without "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200625 "TLLI, but no TLLI received yet\n", rh->tfi);
626 return 0;
627 }
628 rc = tlli_from_ul_data(data, len, &tbf->tlli);
629 if (rc) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200630 LOGP(DRLCMACUL, LOGL_NOTICE, "Failed to decode TLLI "
Andreas Eversberg0e403092012-07-06 11:04:57 +0200631 "of UL DATA TBF=%d.\n", rh->tfi);
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200632 return 0;
633 }
634 tbf->tlli_valid = 1;
Andreas Eversberg0e403092012-07-06 11:04:57 +0200635 LOGP(DRLCMACUL, LOGL_INFO, "Decoded premier TLLI=0x%08x of "
636 "UL DATA TBF=%d.\n", tbf->tlli, rh->tfi);
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200637 /* already have TLLI, but we stille get another one */
638 } else if (rh->ti) {
639 uint32_t tlli;
640 rc = tlli_from_ul_data(data, len, &tlli);
641 if (rc) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200642 LOGP(DRLCMACUL, LOGL_NOTICE, "Failed to decode TLLI "
Andreas Eversberg0e403092012-07-06 11:04:57 +0200643 "of UL DATA TBF=%d.\n", rh->tfi);
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200644 return 0;
645 }
646 if (tlli != tbf->tlli) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200647 LOGP(DRLCMACUL, LOGL_NOTICE, "TLLI mismatch on UL "
Andreas Eversberg0e403092012-07-06 11:04:57 +0200648 "DATA TBF=%d. (Ignoring due to contention "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200649 "resolution)\n", rh->tfi);
650 return 0;
651 }
652 }
653
654 mod_sns = tbf->sns - 1;
655 mod_sns_half = (tbf->sns >> 1) - 1;
656
657 /* restart T3169 */
Andreas Eversbergdfa563c2012-07-06 08:13:59 +0200658 tbf_timer_start(tbf, 3169, bts->t3169, 0);
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200659
660 /* Increment RX-counter */
661 tbf->dir.ul.rx_counter++;
662
663 /* current block relative to lowest unreceived block */
664 offset_v_q = (rh->bsn - tbf->dir.ul.v_q) & mod_sns;
665 /* If out of window (may happen if blocks below V(Q) are received
666 * again. */
667 if (offset_v_q >= tbf->ws) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200668 LOGP(DRLCMACUL, LOGL_DEBUG, "- BSN %d out of window "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200669 "%d..%d (it's normal)\n", rh->bsn, tbf->dir.ul.v_q,
670 (tbf->dir.ul.v_q + tbf->ws - 1) & mod_sns);
671 return 0;
672 }
673 /* Write block to buffer and set receive state array. */
674 index = rh->bsn & mod_sns_half; /* memory index of block */
675 memcpy(tbf->rlc_block[index], data, len); /* Copy block. */
676 tbf->rlc_block_len[index] = len;
677 tbf->dir.ul.v_n[index] = 'R'; /* Mark received block. */
Andreas Eversberge6228b32012-07-03 13:36:03 +0200678 LOGP(DRLCMACUL, LOGL_DEBUG, "- BSN %d storing in window (%d..%d)\n",
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200679 rh->bsn, tbf->dir.ul.v_q,
680 (tbf->dir.ul.v_q + tbf->ws - 1) & mod_sns);
681 /* Raise V(R) to highest received sequence number not received. */
682 offset_v_r = (rh->bsn + 1 - tbf->dir.ul.v_r) & mod_sns;
683 if (offset_v_r < (tbf->sns >> 1)) { /* Positive offset, so raise. */
684 while (offset_v_r--) {
685 if (offset_v_r) /* all except the received block */
686 tbf->dir.ul.v_n[tbf->dir.ul.v_r & mod_sns_half]
687 = 'N'; /* Mark block as not received */
688 tbf->dir.ul.v_r = (tbf->dir.ul.v_r + 1) & mod_sns;
689 /* Inc V(R). */
690 }
Andreas Eversberge6228b32012-07-03 13:36:03 +0200691 LOGP(DRLCMACUL, LOGL_DEBUG, "- Raising V(R) to %d\n",
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200692 tbf->dir.ul.v_r);
693 }
694
695 /* Raise V(Q) if possible, and retrieve LLC frames from blocks.
696 * This is looped until there is a gap (non received block) or
697 * the window is empty.*/
698 while (tbf->dir.ul.v_q != tbf->dir.ul.v_r && tbf->dir.ul.v_n[
699 (index = tbf->dir.ul.v_q & mod_sns_half)] == 'R') {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200700 LOGP(DRLCMACUL, LOGL_DEBUG, "- Taking block %d out, raising "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200701 "V(Q) to %d\n", tbf->dir.ul.v_q,
702 (tbf->dir.ul.v_q + 1) & mod_sns);
703 /* get LLC data from block */
704 gprs_rlcmac_assemble_llc(tbf, tbf->rlc_block[index],
705 tbf->rlc_block_len[index]);
706 /* raise V(Q), because block already received */
707 tbf->dir.ul.v_q = (tbf->dir.ul.v_q + 1) & mod_sns;
708 }
709
710 /* Check CV of last frame in buffer */
711 if (tbf->state == GPRS_RLCMAC_FLOW /* still in flow state */
712 && tbf->dir.ul.v_q == tbf->dir.ul.v_r) { /* if complete */
Andreas Eversberge6228b32012-07-03 13:36:03 +0200713 struct rlc_ul_header *last_rh = (struct rlc_ul_header *)
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200714 tbf->rlc_block[(tbf->dir.ul.v_r - 1) & mod_sns_half];
Andreas Eversberge6228b32012-07-03 13:36:03 +0200715 LOGP(DRLCMACUL, LOGL_DEBUG, "- No gaps in received block, "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200716 "last block: BSN=%d CV=%d\n", last_rh->bsn,
717 last_rh->cv);
718 if (last_rh->cv == 0) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200719 LOGP(DRLCMACUL, LOGL_DEBUG, "- Finished with UL "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200720 "TBF\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200721 tbf_new_state(tbf, GPRS_RLCMAC_FINISHED);
722 /* Reset N3103 counter. */
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200723 tbf->dir.ul.n3103 = 0;
724 }
725 }
726
727 /* If TLLI is included or if we received half of the window, we send
728 * an ack/nack */
Andreas Eversberge6228b32012-07-03 13:36:03 +0200729 if (rh->si || rh->ti || tbf->state == GPRS_RLCMAC_FINISHED
Andreas Eversbergf54a89e2012-07-16 11:56:11 +0200730 || (tbf->dir.ul.rx_counter % SEND_ACK_AFTER_FRAMES) == 0) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200731 if (rh->si) {
Andreas Eversbergf54a89e2012-07-16 11:56:11 +0200732 LOGP(DRLCMACUL, LOGL_NOTICE, "- Scheduling Ack/Nack, "
Andreas Eversberge6228b32012-07-03 13:36:03 +0200733 "because MS is stalled.\n");
734 }
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200735 if (rh->ti) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200736 LOGP(DRLCMACUL, LOGL_DEBUG, "- Scheduling Ack/Nack, "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200737 "because TLLI is included.\n");
738 }
739 if (tbf->state == GPRS_RLCMAC_FINISHED) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200740 LOGP(DRLCMACUL, LOGL_DEBUG, "- Scheduling Ack/Nack, "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200741 "because last block has CV==0.\n");
742 }
Andreas Eversbergf54a89e2012-07-16 11:56:11 +0200743 if ((tbf->dir.ul.rx_counter % SEND_ACK_AFTER_FRAMES) == 0) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200744 LOGP(DRLCMACUL, LOGL_DEBUG, "- Scheduling Ack/Nack, "
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200745 "because %d frames received.\n",
Andreas Eversbergf54a89e2012-07-16 11:56:11 +0200746 SEND_ACK_AFTER_FRAMES);
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200747 }
Andreas Eversberge6228b32012-07-03 13:36:03 +0200748 if (tbf->ul_ack_state == GPRS_RLCMAC_UL_ACK_NONE) {
749 /* trigger sending at next RTS */
750 tbf->ul_ack_state = GPRS_RLCMAC_UL_ACK_SEND_ACK;
751 } else {
752 /* already triggered */
753 LOGP(DRLCMACUL, LOGL_DEBUG, "- Sending Ack/Nack is "
754 "already triggered, don't schedule!\n");
755 }
Andreas Eversberg66690dd2012-06-27 15:44:31 +0200756 }
757
758 return 0;
759}
760
Andreas Eversberge6228b32012-07-03 13:36:03 +0200761struct msgb *gprs_rlcmac_send_packet_uplink_assignment(
762 struct gprs_rlcmac_tbf *tbf, uint32_t fn)
763{
764 struct msgb *msg;
765 struct gprs_rlcmac_tbf *new_tbf;
766
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200767#if POLLING_ASSIGNMENT == 1
Andreas Eversberge6228b32012-07-03 13:36:03 +0200768 if (tbf->poll_state != GPRS_RLCMAC_POLL_NONE) {
769 LOGP(DRLCMACUL, LOGL_DEBUG, "Polling is already "
770 "sheduled for TBF=%d, so we must wait for uplink "
771 "assignment...\n", tbf->tfi);
772 return NULL;
773 }
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200774#endif
Andreas Eversberge6228b32012-07-03 13:36:03 +0200775
776 /* on down TBF we get the uplink TBF to be assigned. */
777 if (tbf->direction == GPRS_RLCMAC_DL_TBF)
778 new_tbf = tbf_by_tlli(tbf->tlli, GPRS_RLCMAC_UL_TBF);
779 else
780 new_tbf = tbf;
781
782 if (!new_tbf) {
783 LOGP(DRLCMACUL, LOGL_ERROR, "We have a schedule for uplink "
784 "assignment at downlink TBF=%d, but there is no uplink "
785 "TBF\n", tbf->tfi);
786 tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_NONE;
787 return NULL;
788 }
789
790 msg = msgb_alloc(23, "rlcmac_ul_ass");
791 if (!msg)
792 return NULL;
Andreas Eversberg0e403092012-07-06 11:04:57 +0200793 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 +0200794 bitvec *ass_vec = bitvec_alloc(23);
795 if (!ass_vec) {
796 msgb_free(msg);
797 return NULL;
798 }
799 bitvec_unhex(ass_vec,
800 "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
801 write_packet_uplink_assignment(ass_vec, tbf->tfi,
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200802 (tbf->direction == GPRS_RLCMAC_DL_TBF), 0, 0, new_tbf,
803 POLLING_ASSIGNMENT);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200804 bitvec_pack(ass_vec, msgb_put(msg, 23));
805 RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)malloc(sizeof(RlcMacDownlink_t));
Andreas Eversberg0e403092012-07-06 11:04:57 +0200806 LOGP(DRLCMAC, LOGL_DEBUG, "+++++++++++++++++++++++++ TX : Packet Uplink Assignment +++++++++++++++++++++++++\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200807 decode_gsm_rlcmac_downlink(ass_vec, mac_control_block);
Andreas Eversberg0e403092012-07-06 11:04:57 +0200808 LOGPC(DCSN1, LOGL_NOTICE, "\n");
809 LOGP(DRLCMAC, LOGL_DEBUG, "------------------------- TX : Packet Uplink Assignment -------------------------\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200810 bitvec_free(ass_vec);
811
812#if POLLING_ASSIGNMENT == 1
813 FIXME process does not work, also the acknowledgement is not checked.
814 tbf->poll_state = GPRS_RLCMAC_POLL_SCHED;
815 tbf->poll_fn = (fn + 13) % 2715648;
816 tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_WAIT_ACK;
817#else
818 tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_NONE;
819#endif
820
821 return msg;
822}
823
824int gprs_rlcmac_rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta)
825{
Andreas Eversbergdfa563c2012-07-06 08:13:59 +0200826 struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200827 struct gprs_rlcmac_tbf *tbf;
828 uint8_t trx, ts;
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200829 int8_t tfi; /* must be signed */
Andreas Eversberge6228b32012-07-03 13:36:03 +0200830
831 LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF on RACH, so we provide "
832 "one:\n");
833 // Create new TBF
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200834 tfi = tfi_alloc(GPRS_RLCMAC_UL_TBF, &trx, &ts, -1, -1);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200835 if (tfi < 0) {
836 LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n");
837 /* FIXME: send reject */
838 return -EBUSY;
839 }
Andreas Eversbergf298fa82012-07-13 14:50:57 +0200840 /* set class to 0, since we don't know the multislot class yet */
Andreas Eversberg592e04a2012-07-15 06:25:37 +0200841 tbf = tbf_alloc(NULL, GPRS_RLCMAC_UL_TBF, tfi, trx, ts, 0, 1);
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200842 if (!tbf) {
843 LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200844 /* FIXME: send reject */
845 return -EBUSY;
846 }
Andreas Eversberge6228b32012-07-03 13:36:03 +0200847 if (qta < 0)
848 qta = 0;
849 if (qta > 252)
850 qta = 252;
851 tbf->ta = qta >> 2;
Andreas Eversberge6228b32012-07-03 13:36:03 +0200852 tbf_new_state(tbf, GPRS_RLCMAC_FLOW);
Andreas Eversbergdfa563c2012-07-06 08:13:59 +0200853 tbf_timer_start(tbf, 3169, bts->t3169, 0);
Andreas Eversberg0e403092012-07-06 11:04:57 +0200854 LOGP(DRLCMAC, LOGL_DEBUG, "TBF: [UPLINK] START TFI: %u\n", tbf->tfi);
855 LOGP(DRLCMAC, LOGL_DEBUG, "RX: [PCU <- BTS] TFI: %u RACH qbit-ta=%d ra=%d, Fn=%d (%d,%d,%d)\n", tbf->tfi, qta, ra, Fn, (Fn / (26 * 51)) % 32, Fn % 51, Fn % 26);
856 LOGP(DRLCMAC, LOGL_INFO, "TX: START TFI: %u Immediate Assignment Uplink (AGCH)\n", tbf->tfi);
Andreas Eversberg7b045012012-07-05 07:38:49 +0200857 bitvec *immediate_assignment = bitvec_alloc(22) /* without plen */;
858 bitvec_unhex(immediate_assignment, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +0200859 int plen = write_immediate_assignment(immediate_assignment, 0, ra, Fn, tbf->ta, tbf->arfcn, tbf->first_ts, tbf->tsc, tbf->tfi, tbf->dir.ul.usf[tbf->first_ts], 0, 0, 0);
Andreas Eversberg7b045012012-07-05 07:38:49 +0200860 pcu_l1if_tx_agch(immediate_assignment, plen);
Andreas Eversberge6228b32012-07-03 13:36:03 +0200861 bitvec_free(immediate_assignment);
862
863 return 0;
864}
865
866
867/*
868 * DL data block flow
869 */
870
871/* send DL data block
872 *
873 * The messages are fragmented and forwarded as data blocks.
874 */
875struct msgb *gprs_rlcmac_send_data_block_acknowledged(
Andreas Eversberg592e04a2012-07-15 06:25:37 +0200876 struct gprs_rlcmac_tbf *tbf, uint32_t fn, uint8_t ts)
Andreas Eversberge6228b32012-07-03 13:36:03 +0200877{
878 struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
879 struct rlc_dl_header *rh;
880 struct rlc_li_field *li;
881 uint8_t block_length; /* total length of block, including spare bits */
882 uint8_t block_data; /* usable data of block, w/o spare bits, inc. MAC */
883 struct msgb *msg, *dl_msg;
884 uint8_t bsn;
885 uint16_t mod_sns = tbf->sns - 1;
886 uint16_t mod_sns_half = (tbf->sns >> 1) - 1;
887 uint16_t index;
888 uint8_t *delimiter, *data, *e_pointer;
889 uint8_t len;
890 uint16_t space, chunk;
891
Andreas Eversberg0e403092012-07-06 11:04:57 +0200892 LOGP(DRLCMACDL, LOGL_DEBUG, "DL DATA TBF=%d downlink (V(A)==%d .. "
Andreas Eversberge6228b32012-07-03 13:36:03 +0200893 "V(S)==%d)\n", tbf->tfi, tbf->dir.dl.v_a, tbf->dir.dl.v_s);
894
895do_resend:
896 /* check if there is a block with negative acknowledgement */
897 for (bsn = tbf->dir.dl.v_a; bsn != tbf->dir.dl.v_s;
898 bsn = (bsn + 1) & mod_sns) {
899 index = (bsn & mod_sns_half);
900 if (tbf->dir.dl.v_b[index] == 'N'
901 || tbf->dir.dl.v_b[index] == 'X') {
902 LOGP(DRLCMACDL, LOGL_DEBUG, "- Resending BSN %d\n",
903 bsn);
904 /* re-send block with negative aknowlegement */
905 tbf->dir.dl.v_b[index] = 'U'; /* unacked */
906 goto tx_block;
907 }
908 }
909
910 /* if the window has stalled, or transfer is complete,
911 * send an unacknowledged block */
912 if (tbf->state == GPRS_RLCMAC_FINISHED
913 || ((tbf->dir.dl.v_s - tbf->dir.dl.v_a) & mod_sns) == tbf->ws) {
914 int resend = 0;
915
916 if (tbf->state == GPRS_RLCMAC_FINISHED)
917 LOGP(DRLCMACDL, LOGL_DEBUG, "- Restarting at BSN %d, "
918 "because all blocks have been transmitted.\n",
919 tbf->dir.dl.v_a);
920 else
Andreas Eversberg4b470ff2012-07-16 12:02:40 +0200921 LOGP(DRLCMACDL, LOGL_NOTICE, "- Restarting at BSN %d, "
Andreas Eversberge6228b32012-07-03 13:36:03 +0200922 "because all window is stalled.\n",
923 tbf->dir.dl.v_a);
924 /* If V(S) == V(A) and finished state, we would have received
925 * acknowledgement of all transmitted block. In this case we
926 * would have transmitted the final block, and received ack
927 * from MS. But in this case we did not receive the final ack
928 * indication from MS. This should never happen if MS works
929 * correctly. */
930 if (tbf->dir.dl.v_s == tbf->dir.dl.v_a) {
Andreas Eversberg6664a902012-07-15 06:52:19 +0200931 LOGP(DRLCMACDL, LOGL_ERROR, "- MS acked all block, "
932 "but we still transmitting!\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +0200933 /* we just send final block again */
934 index = ((tbf->dir.dl.v_s - 1) & mod_sns_half);
935 goto tx_block;
936 }
937
938 /* cycle through all unacked blocks */
939 for (bsn = tbf->dir.dl.v_a; bsn != tbf->dir.dl.v_s;
940 bsn = (bsn + 1) & mod_sns) {
941 index = (bsn & mod_sns_half);
942 if (tbf->dir.dl.v_b[index] == 'U') {
943 /* mark to be re-send */
944 tbf->dir.dl.v_b[index] = 'X';
945 resend++;
946 }
947 }
948 /* At this point there should be at leasst one unacked block
949 * to be resent. If not, this is an software error. */
950 if (resend == 0) {
951 LOGP(DRLCMACDL, LOGL_ERROR, "Software error: "
952 "There are no unacknowledged blocks, but V(A) "
953 " != V(S). PLEASE FIX!\n");
954 /* we just send final block again */
955 index = ((tbf->dir.dl.v_s - 1) & mod_sns_half);
956 goto tx_block;
957 }
958 goto do_resend;
959 }
960
961 LOGP(DRLCMACDL, LOGL_DEBUG, "- Sending new block at BSN %d\n",
962 tbf->dir.dl.v_s);
963
964 /* now we still have untransmitted LLC data, so we fill mac block */
965 index = tbf->dir.dl.v_s & mod_sns_half;
966 data = tbf->rlc_block[index];
Andreas Eversbergb3c6f6c2012-07-06 07:40:08 +0200967 switch (bts->initial_cs) {
Andreas Eversberge6228b32012-07-03 13:36:03 +0200968 case 2: /* CS-2 */
969 block_length = 34;
970 block_data = 33;
971 break;
972 case 3: /* CS-3 */
973 block_length = 40;
974 block_data = 39;
975 break;
976 case 4: /* CS-4 */
977 block_length = 54;
978 block_data = 53;
979 break;
980 default: /* CS-1 */
981 block_length = 23;
982 block_data = 23;
983 }
984 memset(data, 0x2b, block_data); /* spare bits will be left 0 */
985 rh = (struct rlc_dl_header *)data;
986 rh->pt = 0; /* Data Block */
987 rh->rrbp = rh->s_p = 0; /* Polling, set later, if required */
988 rh->usf = 7; /* will be set at scheduler */
989 rh->pr = 0; /* FIXME: power reduction */
990 rh->tfi = tbf->tfi; /* TFI */
991 rh->fbi = 0; /* Final Block Indicator, set late, if true */
992 rh->bsn = tbf->dir.dl.v_s; /* Block Sequence Number */
993 rh->e = 0; /* Extension bit, maybe set later */
994 e_pointer = data + 2; /* points to E of current chunk */
995 data += 3;
996 delimiter = data; /* where next length header would be stored */
997 space = block_data - 3;
998 while (1) {
999 chunk = tbf->llc_length - tbf->llc_index;
1000 /* if chunk will exceed block limit */
1001 if (chunk > space) {
1002 LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d "
1003 "larger than space (%d) left in block: copy "
1004 "only remaining space, and we are done\n",
1005 chunk, space);
1006 /* block is filled, so there is no extension */
1007 *e_pointer |= 0x01;
1008 /* fill only space */
1009 memcpy(data, tbf->llc_frame + tbf->llc_index, space);
1010 /* incement index */
1011 tbf->llc_index += space;
1012 /* return data block as message */
1013 break;
1014 }
1015 /* if FINAL chunk would fit precisely in space left */
1016 if (chunk == space && llist_empty(&tbf->llc_queue)) {
1017 LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d "
1018 "would exactly fit into space (%d): because "
1019 "this is a final block, we don't add length "
1020 "header, and we are done\n", chunk, space);
Andreas Eversberg0e403092012-07-06 11:04:57 +02001021 LOGP(DRLCMACDL, LOGL_INFO, "Complete DL frame for "
1022 "TBF=%d that fits precisely in last block: "
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001023 "len=%d\n", tbf->tfi, tbf->llc_length);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001024 /* block is filled, so there is no extension */
1025 *e_pointer |= 0x01;
1026 /* fill space */
1027 memcpy(data, tbf->llc_frame + tbf->llc_index, space);
1028 /* reset LLC frame */
1029 tbf->llc_index = tbf->llc_length = 0;
1030 /* final block */
1031 rh->fbi = 1; /* we indicate final block */
1032 tbf_new_state(tbf, GPRS_RLCMAC_FINISHED);
1033 /* return data block as message */
1034 break;
1035 }
1036 /* if chunk would fit exactly in space left */
1037 if (chunk == space) {
1038 LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d "
1039 "would exactly fit into space (%d): add length "
1040 "header with LI=0, to make frame extend to "
1041 "next block, and we are done\n", chunk, space);
1042 /* make space for delimiter */
1043 if (delimiter != data)
1044 memcpy(delimiter + 1, delimiter,
1045 data - delimiter);
1046 data++;
1047 space--;
1048 /* add LI with 0 length */
1049 li = (struct rlc_li_field *)delimiter;
1050 li->e = 1; /* not more extension */
1051 li->m = 0; /* shall be set to 0, in case of li = 0 */
1052 li->li = 0; /* chunk fills the complete space */
1053 // no need to set e_pointer nor increase delimiter
1054 /* fill only space, which is 1 octet less than chunk */
1055 memcpy(data, tbf->llc_frame + tbf->llc_index, space);
1056 /* incement index */
1057 tbf->llc_index += space;
1058 /* return data block as message */
1059 break;
1060 }
1061 LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d is less "
1062 "than remaining space (%d): add length header to "
1063 "to delimit LLC frame\n", chunk, space);
1064 /* the LLC frame chunk ends in this block */
1065 /* make space for delimiter */
1066 if (delimiter != data)
1067 memcpy(delimiter + 1, delimiter, data - delimiter);
1068 data++;
1069 space--;
1070 /* add LI to delimit frame */
1071 li = (struct rlc_li_field *)delimiter;
1072 li->e = 0; /* Extension bit, maybe set later */
1073 li->m = 0; /* will be set later, if there is more LLC data */
1074 li->li = chunk; /* length of chunk */
1075 e_pointer = delimiter; /* points to E of current delimiter */
1076 delimiter++;
1077 /* copy (rest of) LLC frame to space */
1078 memcpy(data, tbf->llc_frame + tbf->llc_index, chunk);
1079 data += chunk;
1080 space -= chunk;
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001081 LOGP(DRLCMACDL, LOGL_INFO, "Complete DL frame for TBF=%d: "
1082 "len=%d\n", tbf->tfi, tbf->llc_length);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001083 /* reset LLC frame */
1084 tbf->llc_index = tbf->llc_length = 0;
1085 /* dequeue next LLC frame, if any */
1086 msg = msgb_dequeue(&tbf->llc_queue);
1087 if (msg) {
Andreas Eversberg0e403092012-07-06 11:04:57 +02001088 LOGP(DRLCMACDL, LOGL_INFO, "- Dequeue next LLC for "
1089 "TBF=%d (len=%d)\n", tbf->tfi, msg->len);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001090 memcpy(tbf->llc_frame, msg->data, msg->len);
1091 tbf->llc_length = msg->len;
1092 msgb_free(msg);
1093 }
1094 /* if we have more data and we have space left */
1095 if (space > 0 && tbf->llc_length) {
1096 li->m = 1; /* we indicate more frames to follow */
1097 continue;
1098 }
1099 /* if we don't have more LLC frames */
1100 if (!tbf->llc_length) {
Andreas Eversberg0e403092012-07-06 11:04:57 +02001101 LOGP(DRLCMACDL, LOGL_DEBUG, "-- Final block, so we "
Andreas Eversberge6228b32012-07-03 13:36:03 +02001102 "done.\n");
1103 li->e = 1; /* we cannot extend */
1104 rh->fbi = 1; /* we indicate final block */
Andreas Eversbergf54a89e2012-07-16 11:56:11 +02001105 tbf->dir.dl.tx_counter = POLL_ACK_AFTER_FRAMES + 1;
1106 /* + 1 indicates: first final ack */
Andreas Eversberge6228b32012-07-03 13:36:03 +02001107 tbf_new_state(tbf, GPRS_RLCMAC_FINISHED);
1108 break;
1109 }
1110 /* we have no space left */
Andreas Eversberg0e403092012-07-06 11:04:57 +02001111 LOGP(DRLCMACDL, LOGL_DEBUG, "-- No space left, so we are "
Andreas Eversberge6228b32012-07-03 13:36:03 +02001112 "done.\n");
1113 li->e = 1; /* we cannot extend */
1114 break;
1115 }
1116 LOGP(DRLCMACDL, LOGL_DEBUG, "data block: %s\n",
1117 osmo_hexdump(tbf->rlc_block[index], block_length));
1118 tbf->rlc_block_len[index] = block_length;
1119 /* raise send state and set ack state array */
1120 tbf->dir.dl.v_b[index] = 'U'; /* unacked */
1121 tbf->dir.dl.v_s = (tbf->dir.dl.v_s + 1) & mod_sns; /* inc send state */
1122
1123tx_block:
1124 /* from this point on, new block is sent or old block is resent */
1125
1126 /* get data and header from current block */
1127 data = tbf->rlc_block[index];
1128 len = tbf->rlc_block_len[index];
1129 rh = (struct rlc_dl_header *)data;
1130
Andreas Eversberge6228b32012-07-03 13:36:03 +02001131 /* Clear Polling, if still set in history buffer */
1132 rh->s_p = 0;
1133
Andreas Eversbergf54a89e2012-07-16 11:56:11 +02001134 /* poll after POLL_ACK_AFTER_FRAMES frames, or when final block is tx.
1135 */
1136 if (tbf->dir.dl.tx_counter >= POLL_ACK_AFTER_FRAMES) {
1137 if (tbf->dir.dl.tx_counter > POLL_ACK_AFTER_FRAMES) {
1138 /* if rx_counter is POLL_ACK_AFTER_FRAMES + 1, this
Andreas Eversberg5e043da2012-07-15 06:51:30 +02001139 * indicates: poll caused by final ack. */
Andreas Eversberge6228b32012-07-03 13:36:03 +02001140 LOGP(DRLCMACDL, LOGL_DEBUG, "- Scheduling Ack/Nack "
1141 "polling, because final block sent.\n");
Andreas Eversberg5e043da2012-07-15 06:51:30 +02001142 } else {
Andreas Eversberge6228b32012-07-03 13:36:03 +02001143 LOGP(DRLCMACDL, LOGL_DEBUG, "- Scheduling Ack/Nack "
1144 "polling, because %d blocks sent.\n",
Andreas Eversbergf54a89e2012-07-16 11:56:11 +02001145 POLL_ACK_AFTER_FRAMES);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001146 }
Andreas Eversberg5e043da2012-07-15 06:51:30 +02001147 tbf->dir.dl.tx_counter = 0;
1148 /* scheduling not possible, because: */
Andreas Eversberge6228b32012-07-03 13:36:03 +02001149 if (tbf->poll_state != GPRS_RLCMAC_POLL_NONE)
Andreas Eversberg5e043da2012-07-15 06:51:30 +02001150 LOGP(DRLCMAC, LOGL_DEBUG, "Polling is already "
Andreas Eversberge6228b32012-07-03 13:36:03 +02001151 "sheduled for TBF=%d, so we must wait for "
1152 "requesting downlink ack\n", tbf->tfi);
Andreas Eversberg5e043da2012-07-15 06:51:30 +02001153 else if (tbf->control_ts != ts)
1154 LOGP(DRLCMAC, LOGL_DEBUG, "Polling cannot be "
1155 "sheduled in this TS %d, waiting for "
1156 "TS %d\n", ts, tbf->control_ts);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001157 else {
Andreas Eversbergee31b782012-07-15 16:27:01 +02001158 LOGP(DRLCMAC, LOGL_DEBUG, "Polling sheduled in this "
1159 "TS %d\n", ts);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001160 /* start timer whenever we send the final block */
1161 if (rh->fbi == 1)
Andreas Eversbergdfa563c2012-07-06 08:13:59 +02001162 tbf_timer_start(tbf, 3191, bts->t3191, 0);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001163
1164 /* schedule polling */
1165 tbf->poll_state = GPRS_RLCMAC_POLL_SCHED;
1166 tbf->poll_fn = (fn + 13) % 2715648;
1167
1168 /* set polling in header */
1169 rh->rrbp = 0; /* N+13 */
1170 rh->s_p = 1; /* Polling */
Andreas Eversberg5e043da2012-07-15 06:51:30 +02001171
1172 /* Increment TX-counter */
1173 tbf->dir.dl.tx_counter++;
Andreas Eversberge6228b32012-07-03 13:36:03 +02001174 }
Andreas Eversberg5e043da2012-07-15 06:51:30 +02001175 } else {
1176 /* Increment TX-counter */
1177 tbf->dir.dl.tx_counter++;
Andreas Eversberge6228b32012-07-03 13:36:03 +02001178 }
1179
1180 /* return data block as message */
1181 dl_msg = msgb_alloc(len, "rlcmac_dl_data");
1182 if (!dl_msg)
1183 return NULL;
1184 memcpy(msgb_put(dl_msg, len), data, len);
1185
1186 return dl_msg;
1187}
1188
1189int gprs_rlcmac_downlink_ack(struct gprs_rlcmac_tbf *tbf, uint8_t final,
1190 uint8_t ssn, uint8_t *rbb)
1191{
1192 char show_rbb[65], show_v_b[RLC_MAX_SNS + 1];
1193 uint16_t mod_sns = tbf->sns - 1;
1194 uint16_t mod_sns_half = (tbf->sns >> 1) - 1;
1195 int i; /* must be signed */
1196 int16_t dist; /* must be signed */
1197 uint8_t bit;
1198 uint16_t bsn;
1199 struct msgb *msg;
1200
Andreas Eversberg0e403092012-07-06 11:04:57 +02001201 LOGP(DRLCMACDL, LOGL_DEBUG, "TBF=%d downlink acknowledge\n",
Andreas Eversberge6228b32012-07-03 13:36:03 +02001202 tbf->tfi);
1203
1204 if (!final) {
1205 /* show received array in debug (bit 64..1) */
1206 for (i = 63; i >= 0; i--) {
1207 bit = (rbb[i >> 3] >> (7 - (i&7))) & 1;
1208 show_rbb[i] = (bit) ? '1' : 'o';
1209 }
1210 show_rbb[64] = '\0';
1211 LOGP(DRLCMACDL, LOGL_DEBUG, "- ack: (BSN=%d)\"%s\""
Andreas Eversberg4b470ff2012-07-16 12:02:40 +02001212 "(BSN=%d) 1=ACK o=NACK\n", (ssn - 64) & mod_sns,
1213 show_rbb, (ssn - 1) & mod_sns);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001214
1215 /* apply received array to receive state (SSN-64..SSN-1) */
1216 /* calculate distance of ssn from V(S) */
1217 dist = (tbf->dir.dl.v_s - ssn) & mod_sns;
1218 /* check if distance is less than distance V(A)..V(S) */
1219 if (dist < ((tbf->dir.dl.v_s - tbf->dir.dl.v_a) & mod_sns)) {
1220 /* SSN - 1 is in range V(A)..V(S)-1 */
1221 for (i = 63, bsn = (ssn - 1) & mod_sns;
1222 i >= 0 && bsn != ((tbf->dir.dl.v_a - 1) & mod_sns);
1223 i--, bsn = (bsn - 1) & mod_sns) {
1224 bit = (rbb[i >> 3] >> (7 - (i&7))) & 1;
1225 if (bit) {
1226 LOGP(DRLCMACDL, LOGL_DEBUG, "- got "
1227 "ack for BSN=%d\n", bsn);
1228 tbf->dir.dl.v_b[bsn & mod_sns_half]
1229 = 'A';
1230 } else {
1231 LOGP(DRLCMACDL, LOGL_DEBUG, "- got "
1232 "NACK for BSN=%d\n", bsn);
1233 tbf->dir.dl.v_b[bsn & mod_sns_half]
1234 = 'N';
1235 }
1236 }
1237 } else {
Andreas Eversberg0f13c402012-07-16 11:59:23 +02001238 /* this might happpen, if the downlink assignment
1239 * was not received by ms and the ack refers
1240 * to previous TBF
1241 * FIXME: we should implement polling for
1242 * control ack!*/
1243 LOGP(DRLCMACDL, LOGL_NOTICE, "- ack range is out of "
1244 "V(A)..V(S) range (DL TBF=%d) Free TFB!\n",
1245 tbf->tfi);
1246 return 1; /* indicate to free TBF */
Andreas Eversberge6228b32012-07-03 13:36:03 +02001247 }
1248
1249 /* raise V(A), if possible */
1250 for (i = 0, bsn = tbf->dir.dl.v_a; bsn != tbf->dir.dl.v_s;
1251 i++, bsn = (bsn + 1) & mod_sns) {
1252 if (tbf->dir.dl.v_b[bsn & mod_sns_half] == 'A') {
1253 tbf->dir.dl.v_b[bsn & mod_sns_half] = 'I';
1254 /* mark invalid */
1255 tbf->dir.dl.v_a = (tbf->dir.dl.v_a + 1)
1256 & mod_sns;
1257 } else
1258 break;
1259 }
1260
1261 /* show receive state array in debug (V(A)..V(S)-1) */
1262 for (i = 0, bsn = tbf->dir.dl.v_a; bsn != tbf->dir.dl.v_s;
1263 i++, bsn = (bsn + 1) & mod_sns) {
1264 show_v_b[i] = tbf->dir.dl.v_b[bsn & mod_sns_half];
1265 if (show_v_b[i] == 0)
1266 show_v_b[i] = ' ';
1267 }
1268 show_v_b[i] = '\0';
1269 LOGP(DRLCMACDL, LOGL_DEBUG, "- V(B): (V(A)=%d)\"%s\""
1270 "(V(S)-1=%d) A=Acked N=Nacked U=Unacked "
1271 "X=Resend-Unacked\n", tbf->dir.dl.v_a, show_v_b,
1272 (tbf->dir.dl.v_s - 1) & mod_sns);
1273
Andreas Eversberg6664a902012-07-15 06:52:19 +02001274 if (tbf->state == GPRS_RLCMAC_FINISHED
1275 && tbf->dir.dl.v_s == tbf->dir.dl.v_a) {
1276 LOGP(DRLCMACDL, LOGL_NOTICE, "Received final block, "
Andreas Eversberg4b470ff2012-07-16 12:02:40 +02001277 "but without final ack inidcation\n");
Andreas Eversberg6664a902012-07-15 06:52:19 +02001278 } else
1279 return 0;
Andreas Eversberg4b470ff2012-07-16 12:02:40 +02001280 } else
1281 LOGP(DRLCMACDL, LOGL_DEBUG, "- Final ACK received.\n");
Andreas Eversberge6228b32012-07-03 13:36:03 +02001282
1283 /* check for LLC PDU in the LLC Queue */
1284 msg = msgb_dequeue(&tbf->llc_queue);
1285 if (!msg) {
1286 struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
1287
1288 /* no message, start T3193, change state to RELEASE */
1289 LOGP(DRLCMACDL, LOGL_DEBUG, "- No new message, so we "
1290 "release.\n");
Andreas Eversbergb3c6f6c2012-07-06 07:40:08 +02001291 /* start T3193 */
Andreas Eversbergdfa563c2012-07-06 08:13:59 +02001292 tbf_timer_start(tbf, 3193, bts->t3193_msec / 1000,
1293 bts->t3193_msec & 1000);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001294 tbf_new_state(tbf, GPRS_RLCMAC_WAIT_RELEASE);
1295
1296 return 0;
1297 }
1298 memcpy(tbf->llc_frame, msg->data, msg->len);
1299 tbf->llc_length = msg->len;
1300 msgb_free(msg);
1301
1302 /* we have a message, so we trigger downlink assignment, and there
1303 * set the state to ASSIGN. also we set old_downlink, because we
1304 * re-use this tbf. */
1305 LOGP(DRLCMAC, LOGL_DEBUG, "Trigger dowlink assignment on PACCH, "
1306 "because another LLC PDU has arrived in between\n");
1307 memset(&tbf->dir.dl, 0, sizeof(tbf->dir.dl)); /* reset RLC states */
Andreas Eversberg592e04a2012-07-15 06:25:37 +02001308 tbf_update(tbf);
Andreas Eversberge13fa2d2012-07-09 17:10:44 +02001309 gprs_rlcmac_trigger_downlink_assignment(tbf, 1, NULL);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001310
1311 return 0;
1312}
1313
1314
1315struct msgb *gprs_rlcmac_send_packet_downlink_assignment(
1316 struct gprs_rlcmac_tbf *tbf, uint32_t fn)
1317{
1318 struct msgb *msg;
1319 struct gprs_rlcmac_tbf *new_tbf;
1320
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001321#if POLLING_ASSIGNMENT == 1
Andreas Eversberge6228b32012-07-03 13:36:03 +02001322 if (tbf->poll_state != GPRS_RLCMAC_POLL_NONE) {
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001323 LOGP(DRLCMAC, LOGL_DEBUG, "Polling is already "
Andreas Eversberge6228b32012-07-03 13:36:03 +02001324 "sheduled for TBF=%d, so we must wait for downlink "
1325 "assignment...\n", tbf->tfi);
1326 return NULL;
1327 }
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001328#endif
Andreas Eversberge6228b32012-07-03 13:36:03 +02001329
1330 /* on uplink TBF we get the downlink TBF to be assigned. */
Andreas Eversbergee31b782012-07-15 16:27:01 +02001331 if (tbf->direction == GPRS_RLCMAC_UL_TBF) {
1332 /* be sure to check first, if contention resolution is done,
1333 * otherwise we cannot send the assignment yet */
1334 if (!tbf->contention_resolution_done) {
1335 LOGP(DRLCMAC, LOGL_NOTICE, "Cannot assign DL TBF now, "
1336 "because contention resolution is not "
1337 "finished.\n");
1338 return NULL;
1339 }
Andreas Eversberge6228b32012-07-03 13:36:03 +02001340 new_tbf = tbf_by_tlli(tbf->tlli, GPRS_RLCMAC_DL_TBF);
Andreas Eversbergee31b782012-07-15 16:27:01 +02001341 } else
Andreas Eversberge6228b32012-07-03 13:36:03 +02001342 new_tbf = tbf;
1343 if (!new_tbf) {
1344 LOGP(DRLCMACDL, LOGL_ERROR, "We have a schedule for downlink "
1345 "assignment at uplink TBF=%d, but there is no downlink "
1346 "TBF\n", tbf->tfi);
1347 tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE;
1348 return NULL;
1349 }
1350
1351 msg = msgb_alloc(23, "rlcmac_dl_ass");
1352 if (!msg)
1353 return NULL;
1354 bitvec *ass_vec = bitvec_alloc(23);
1355 if (!ass_vec) {
1356 msgb_free(msg);
1357 return NULL;
1358 }
1359 bitvec_unhex(ass_vec,
1360 "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
Andreas Eversberg0e403092012-07-06 11:04:57 +02001361 LOGP(DRLCMAC, LOGL_INFO, "TBF: START TFI: %u TLLI: 0x%08x Packet Downlink Assignment (PACCH)\n", new_tbf->tfi, new_tbf->tlli);
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001362 RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)malloc(sizeof(RlcMacDownlink_t));
1363 write_packet_downlink_assignment(mac_control_block, tbf->tfi,
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001364 (tbf->direction == GPRS_RLCMAC_DL_TBF), new_tbf,
Andreas Eversberge6228b32012-07-03 13:36:03 +02001365 POLLING_ASSIGNMENT);
Andreas Eversberg0e403092012-07-06 11:04:57 +02001366 LOGP(DRLCMAC, LOGL_DEBUG, "+++++++++++++++++++++++++ TX : Packet Downlink Assignment +++++++++++++++++++++++++\n");
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001367 encode_gsm_rlcmac_downlink(ass_vec, mac_control_block);
Andreas Eversberg0e403092012-07-06 11:04:57 +02001368 LOGPC(DCSN1, LOGL_NOTICE, "\n");
1369 LOGP(DRLCMAC, LOGL_DEBUG, "------------------------- TX : Packet Downlink Assignment -------------------------\n");
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001370 bitvec_pack(ass_vec, msgb_put(msg, 23));
Andreas Eversberge6228b32012-07-03 13:36:03 +02001371 bitvec_free(ass_vec);
Ivan Kluchnikovef7f28c2012-07-12 14:49:15 +04001372 free(mac_control_block);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001373
1374#if POLLING_ASSIGNMENT == 1
1375 tbf->poll_state = GPRS_RLCMAC_POLL_SCHED;
1376 tbf->poll_fn = (fn + 13) % 2715648;
1377 tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_WAIT_ACK;
1378#else
1379 tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE;
1380#endif
1381
1382 return msg;
1383}
1384
Andreas Eversberge13fa2d2012-07-09 17:10:44 +02001385static void gprs_rlcmac_downlink_assignment(gprs_rlcmac_tbf *tbf, uint8_t poll,
1386 char *imsi)
Andreas Eversberge6228b32012-07-03 13:36:03 +02001387{
Andreas Eversberge13fa2d2012-07-09 17:10:44 +02001388 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 +02001389 bitvec *immediate_assignment = bitvec_alloc(22); /* without plen */
1390 bitvec_unhex(immediate_assignment, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
Andreas Eversberge6228b32012-07-03 13:36:03 +02001391 /* use request reference that has maximum distance to current time,
1392 * so the assignment will not conflict with possible RACH requests. */
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001393 int plen = write_immediate_assignment(immediate_assignment, 1, 125, (tbf->pdch[tbf->first_ts]->last_rts_fn + 21216) % 2715648, tbf->ta, tbf->arfcn, tbf->first_ts, tbf->tsc, tbf->tfi, 0, tbf->tlli, poll, tbf->poll_fn);
Andreas Eversberge13fa2d2012-07-09 17:10:44 +02001394 pcu_l1if_tx_pch(immediate_assignment, plen, imsi);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001395 bitvec_free(immediate_assignment);
1396}
1397
1398/* depending on the current TBF, we assign on PACCH or AGCH */
1399void gprs_rlcmac_trigger_downlink_assignment(gprs_rlcmac_tbf *tbf,
Andreas Eversberge13fa2d2012-07-09 17:10:44 +02001400 uint8_t old_downlink, char *imsi)
Andreas Eversberge6228b32012-07-03 13:36:03 +02001401{
1402 gprs_rlcmac_tbf *old_tbf;
1403
1404#ifdef DEBUG_DL_ASS_IDLE
Andreas Eversberge13fa2d2012-07-09 17:10:44 +02001405 strncpy(debug_imsi, imsi);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001406 LOGP(DRLCMAC, LOGL_ERROR, "**** DEBUGGING DOWNLINK ASSIGNMENT ****\n");
1407#endif
1408
1409 /* stop pending timer */
1410 tbf_timer_stop(tbf);
1411
1412 /* check for downlink tbf: */
1413 if (old_downlink)
1414 old_tbf = tbf_by_tlli(tbf->tlli, GPRS_RLCMAC_DL_TBF);
1415 else
1416 old_tbf = tbf_by_tlli(tbf->tlli, GPRS_RLCMAC_UL_TBF);
Andreas Eversberg67e4f2f2012-07-15 19:36:49 +02001417 if (old_tbf && (old_tbf->state != GPRS_RLCMAC_FINISHED ||
1418 old_tbf->ul_ack_state != GPRS_RLCMAC_UL_ACK_WAIT_ACK)) {
Andreas Eversberge6228b32012-07-03 13:36:03 +02001419#ifdef DEBUG_DL_ASS_IDLE
1420 LOGP(DRLCMAC, LOGL_ERROR, "We must wait for current TBF to be "
1421 "released.\n");
1422 /* wait one second until assignment */
1423 tbf_timer_start(tbf, 1234, 1,0);
1424#else
Andreas Eversberg0e403092012-07-06 11:04:57 +02001425 LOGP(DRLCMAC, LOGL_DEBUG, "Send dowlink assignment on "
Andreas Eversbergb0c7ea72012-07-13 14:46:03 +02001426 "PACCH, because %s TBF=%d exists for TLLI=0x%08x\n",
1427 (old_tbf->direction == GPRS_RLCMAC_UL_TBF) ? "UL" : "DL",
Andreas Eversberg0e403092012-07-06 11:04:57 +02001428 old_tbf->tfi, old_tbf->tlli);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001429 old_tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_SEND_ASS;
1430 /* use TA from old TBF */
1431 tbf->ta = old_tbf->ta;
1432 /* change state */
1433 tbf_new_state(tbf, GPRS_RLCMAC_ASSIGN);
1434 /* start timer */
1435 tbf_timer_start(tbf, 0, Tassign_pacch);
1436#endif
1437 } else {
Andreas Eversberge13fa2d2012-07-09 17:10:44 +02001438 LOGP(DRLCMAC, LOGL_DEBUG, "Send dowlink assignment for TBF=%d on PCH, no TBF exist (IMSI=%s)\n", tbf->tfi, imsi);
1439 if (!imsi || strlen(imsi) < 3) {
1440 LOGP(DRLCMAC, LOGL_ERROR, "No valid IMSI!\n");
1441 return;
1442 }
Andreas Eversberge6228b32012-07-03 13:36:03 +02001443 /* send immediate assignment */
Andreas Eversberge13fa2d2012-07-09 17:10:44 +02001444 gprs_rlcmac_downlink_assignment(tbf, 0, imsi);
Andreas Eversberge6228b32012-07-03 13:36:03 +02001445 /* change state */
1446 tbf_new_state(tbf, GPRS_RLCMAC_ASSIGN);
1447 /* start timer */
1448 tbf_timer_start(tbf, 0, Tassign_agch);
1449 }
1450 }
1451