blob: 9baa1cd037efbc83516c23d6da60afb57c00c5e2 [file] [log] [blame]
Daniel Willmannca102af2014-08-08 12:14:12 +02001/* Copied from tbf.cpp
2 *
3 * Copyright (C) 2012 Ivan Klyuchnikov
4 * Copyright (C) 2012 Andreas Eversberg <jolly@eversberg.eu>
5 * Copyright (C) 2013 by Holger Hans Peter Freyther
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#include <bts.h>
23#include <tbf.h>
24#include <rlc.h>
25#include <gprs_rlcmac.h>
26#include <gprs_debug.h>
27#include <gprs_bssgp_pcu.h>
28#include <decoding.h>
29
30extern "C" {
31#include <osmocom/core/msgb.h>
32#include <osmocom/core/talloc.h>
33}
34
35#include <errno.h>
36#include <string.h>
37
38/* After sending these frames, we poll for ack/nack. */
39#define POLL_ACK_AFTER_FRAMES 20
40
41
42static const struct gprs_rlcmac_cs gprs_rlcmac_cs[] = {
43/* frame length data block max payload */
44 { 0, 0, 0 },
45 { 23, 23, 20 }, /* CS-1 */
46 { 34, 33, 30 }, /* CS-2 */
47 { 40, 39, 36 }, /* CS-3 */
48 { 54, 53, 50 }, /* CS-4 */
49};
50
51extern "C" {
52int bssgp_tx_llc_discarded(struct bssgp_bvc_ctx *bctx, uint32_t tlli,
53 uint8_t num_frames, uint32_t num_octets);
54}
55
56static inline void tbf_update_ms_class(struct gprs_rlcmac_tbf *tbf,
57 const uint8_t ms_class)
58{
59 if (!tbf->ms_class && ms_class)
60 tbf->ms_class = ms_class;
61}
62
63int gprs_rlcmac_dl_tbf::append_data(const uint8_t ms_class,
64 const uint16_t pdu_delay_csec,
65 const uint8_t *data, const uint16_t len)
66{
67 LOGP(DRLCMAC, LOGL_INFO, "%s append\n", tbf_name(this));
68 if (state_is(GPRS_RLCMAC_WAIT_RELEASE)) {
69 LOGP(DRLCMAC, LOGL_DEBUG,
70 "%s in WAIT RELEASE state "
71 "(T3193), so reuse TBF\n", tbf_name(this));
72 tbf_update_ms_class(this, ms_class);
73 reuse_tbf(data, len);
Jacob Erlbeckc4952092015-03-24 11:04:19 +010074 } else if (!have_data()) {
75 m_llc.put_frame(data, len);
76 bts->llc_frame_sched();
77 tbf_update_ms_class(this, ms_class);
Daniel Willmannca102af2014-08-08 12:14:12 +020078 } else {
79 /* the TBF exists, so we must write it in the queue
80 * we prepend lifetime in front of PDU */
81 struct timeval *tv;
82 struct msgb *llc_msg = msgb_alloc(len + sizeof(*tv) * 2,
83 "llc_pdu_queue");
84 if (!llc_msg)
85 return -ENOMEM;
86 tv = (struct timeval *)msgb_put(llc_msg, sizeof(*tv));
87 gprs_llc::calc_pdu_lifetime(bts, pdu_delay_csec, tv);
88 tv = (struct timeval *)msgb_put(llc_msg, sizeof(*tv));
89 gettimeofday(tv, NULL);
90 memcpy(msgb_put(llc_msg, len), data, len);
91 m_llc.enqueue(llc_msg);
92 tbf_update_ms_class(this, ms_class);
93 }
94
95 return 0;
96}
97
98static struct gprs_rlcmac_dl_tbf *tbf_lookup_dl(BTS *bts,
99 const uint32_t tlli, const char *imsi)
100{
101 /* TODO: look up by IMSI first, then tlli, then old_tlli */
102 return bts->dl_tbf_by_tlli(tlli);
103}
104
105static int tbf_new_dl_assignment(struct gprs_rlcmac_bts *bts,
106 const char *imsi,
107 const uint32_t tlli, const uint8_t ms_class,
108 const uint8_t *data, const uint16_t len)
109{
110 uint8_t trx, ta, ss;
111 int8_t use_trx;
112 struct gprs_rlcmac_ul_tbf *ul_tbf, *old_ul_tbf;
113 struct gprs_rlcmac_dl_tbf *dl_tbf;
114 int8_t tfi; /* must be signed */
115 int rc;
116
117 /* check for uplink data, so we copy our informations */
118#warning "Do the same look up for IMSI, TLLI and OLD_TLLI"
119#warning "Refactor the below lines... into a new method"
120 ul_tbf = bts->bts->ul_tbf_by_tlli(tlli);
121 if (ul_tbf && ul_tbf->m_contention_resolution_done
122 && !ul_tbf->m_final_ack_sent) {
123 use_trx = ul_tbf->trx->trx_no;
124 ta = ul_tbf->ta;
125 ss = 0;
126 old_ul_tbf = ul_tbf;
127 } else {
128 use_trx = -1;
129 /* we already have an uplink TBF, so we use that TA */
130 if (ul_tbf)
131 ta = ul_tbf->ta;
132 else {
133 /* recall TA */
134 rc = bts->bts->timing_advance()->recall(tlli);
135 if (rc < 0) {
136 LOGP(DRLCMAC, LOGL_NOTICE, "TA unknown"
137 ", assuming 0\n");
138 ta = 0;
139 } else
140 ta = rc;
141 }
142 ss = 1; /* PCH assignment only allows one timeslot */
143 old_ul_tbf = NULL;
144 }
145
146 // Create new TBF (any TRX)
147#warning "Copy and paste with alloc_ul_tbf"
148 tfi = bts->bts->tfi_find_free(GPRS_RLCMAC_DL_TBF, &trx, use_trx);
149 if (tfi < 0) {
150 LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH resource\n");
151 /* FIXME: send reject */
152 return -EBUSY;
153 }
154 /* set number of downlink slots according to multislot class */
155 dl_tbf = tbf_alloc_dl_tbf(bts, ul_tbf, tfi, trx, ms_class, ss);
156 if (!dl_tbf) {
157 LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH resource\n");
158 /* FIXME: send reject */
159 return -EBUSY;
160 }
161 dl_tbf->m_tlli = tlli;
162 dl_tbf->m_tlli_valid = 1;
163 dl_tbf->ta = ta;
164
165 LOGP(DRLCMAC, LOGL_DEBUG, "%s [DOWNLINK] START\n", tbf_name(dl_tbf));
166
167 /* new TBF, so put first frame */
168 dl_tbf->m_llc.put_frame(data, len);
169 dl_tbf->bts->llc_frame_sched();
170
171 /* Store IMSI for later look-up and PCH retransmission */
172 dl_tbf->assign_imsi(imsi);
173
174 /* trigger downlink assignment and set state to ASSIGN.
175 * we don't use old_downlink, so the possible uplink is used
176 * to trigger downlink assignment. if there is no uplink,
177 * AGCH is used. */
178 dl_tbf->bts->trigger_dl_ass(dl_tbf, old_ul_tbf, imsi);
179 return 0;
180}
181
182/**
183 * TODO: split into unit test-able parts...
184 */
185int gprs_rlcmac_dl_tbf::handle(struct gprs_rlcmac_bts *bts,
186 const uint32_t tlli, const char *imsi,
187 const uint8_t ms_class, const uint16_t delay_csec,
188 const uint8_t *data, const uint16_t len)
189{
190 struct gprs_rlcmac_dl_tbf *dl_tbf;
191
192 /* check for existing TBF */
193 dl_tbf = tbf_lookup_dl(bts->bts, tlli, imsi);
194 if (dl_tbf) {
195 int rc = dl_tbf->append_data(ms_class, delay_csec, data, len);
196 if (rc >= 0)
197 dl_tbf->assign_imsi(imsi);
198 return rc;
199 }
200
201 return tbf_new_dl_assignment(bts, imsi, tlli, ms_class, data, len);
202}
203
204struct msgb *gprs_rlcmac_dl_tbf::llc_dequeue(bssgp_bvc_ctx *bctx)
205{
206 struct msgb *msg;
207 struct timeval *tv, tv_now;
208 uint32_t octets = 0, frames = 0;
209
210 gettimeofday(&tv_now, NULL);
211
212 while ((msg = m_llc.dequeue())) {
213 tv = (struct timeval *)msg->data;
214 msgb_pull(msg, sizeof(*tv));
215 msgb_pull(msg, sizeof(*tv));
216
217 if (gprs_llc::is_frame_expired(&tv_now, tv)) {
218 LOGP(DRLCMACDL, LOGL_NOTICE, "%s Discarding LLC PDU "
219 "because lifetime limit reached. Queue size %zu\n",
220 tbf_name(this), m_llc.m_queue_size);
221 bts->llc_timedout_frame();
222 frames++;
223 octets += msg->len;
224 msgb_free(msg);
225 continue;
226 }
227 break;
228 }
229
230 if (frames) {
231 if (frames > 0xff)
232 frames = 0xff;
233 if (octets > 0xffffff)
234 octets = 0xffffff;
235 bssgp_tx_llc_discarded(bctx, m_tlli, frames, octets);
236 }
237
238 return msg;
239}
240
241/*
242 * Create DL data block
243 * The messages are fragmented and forwarded as data blocks.
244 */
245struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(uint32_t fn, uint8_t ts)
246{
247 LOGP(DRLCMACDL, LOGL_DEBUG, "%s downlink (V(A)==%d .. "
248 "V(S)==%d)\n", tbf_name(this),
249 m_window.v_a(), m_window.v_s());
250
251do_resend:
252 /* check if there is a block with negative acknowledgement */
253 int resend_bsn = m_window.resend_needed();
254 if (resend_bsn >= 0) {
255 LOGP(DRLCMACDL, LOGL_DEBUG, "- Resending BSN %d\n", resend_bsn);
256 /* re-send block with negative aknowlegement */
257 m_window.m_v_b.mark_unacked(resend_bsn);
258 bts->rlc_resent();
Jacob Erlbeck7c444152015-03-12 12:08:54 +0100259 return create_dl_acked_block(fn, ts, resend_bsn);
Daniel Willmannca102af2014-08-08 12:14:12 +0200260 }
261
262 /* if the window has stalled, or transfer is complete,
263 * send an unacknowledged block */
Jacob Erlbeck95340242015-03-19 13:22:07 +0100264 if (state_is(GPRS_RLCMAC_FINISHED)) {
265 LOGP(DRLCMACDL, LOGL_DEBUG, "- Restarting at BSN %d, "
266 "because all blocks have been transmitted.\n",
267 m_window.v_a());
268 bts->rlc_restarted();
269 } else if (dl_window_stalled()) {
270 LOGP(DRLCMACDL, LOGL_NOTICE, "- Restarting at BSN %d, "
271 "because all window is stalled.\n",
272 m_window.v_a());
273 bts->rlc_stalled();
274 } else {
275 /* No blocks are left */
276 return create_new_bsn(fn, ts);
Daniel Willmannca102af2014-08-08 12:14:12 +0200277 }
278
Jacob Erlbeck95340242015-03-19 13:22:07 +0100279 /* If V(S) == V(A) and finished state, we would have received
280 * acknowledgement of all transmitted block. In this case we
281 * would have transmitted the final block, and received ack
282 * from MS. But in this case we did not receive the final ack
283 * indication from MS. This should never happen if MS works
284 * correctly. */
285 if (m_window.window_empty()) {
286 LOGP(DRLCMACDL, LOGL_DEBUG, "- MS acked all blocks, "
287 "so we re-transmit final block!\n");
288 /* we just send final block again */
289 int16_t index = m_window.v_s_mod(-1);
290 bts->rlc_resent();
291 return create_dl_acked_block(fn, ts, index);
292 }
293
294 /* cycle through all unacked blocks */
295 int resend = m_window.mark_for_resend();
296
297 /* At this point there should be at least one unacked block
298 * to be resent. If not, this is an software error. */
299 if (resend == 0) {
300 LOGP(DRLCMACDL, LOGL_ERROR, "Software error: "
301 "There are no unacknowledged blocks, but V(A) "
302 " != V(S). PLEASE FIX!\n");
303 /* we just send final block again */
304 int16_t index = m_window.v_s_mod(-1);
305 return create_dl_acked_block(fn, ts, index);
306 }
307 goto do_resend;
Daniel Willmannca102af2014-08-08 12:14:12 +0200308}
309
310struct msgb *gprs_rlcmac_dl_tbf::create_new_bsn(const uint32_t fn, const uint8_t ts)
311{
312 struct rlc_dl_header *rh;
313 struct rlc_li_field *li;
314 struct msgb *msg;
315 uint8_t *delimiter, *data, *e_pointer;
316 uint16_t space, chunk;
317 gprs_rlc_data *rlc_data;
Daniel Willmannca102af2014-08-08 12:14:12 +0200318 const uint16_t bsn = m_window.v_s();
319
320 LOGP(DRLCMACDL, LOGL_DEBUG, "- Sending new block at BSN %d\n",
321 m_window.v_s());
322
323#warning "Selection of the CS doesn't belong here"
324 if (cs == 0) {
325 cs = bts_data()->initial_cs_dl;
326 if (cs < 1 || cs > 4)
327 cs = 1;
328 }
329 /* total length of block, including spare bits */
330 const uint8_t block_length = gprs_rlcmac_cs[cs].block_length;
331 /* length of usable data of block, w/o spare bits, inc. MAC */
332 const uint8_t block_data_len = gprs_rlcmac_cs[cs].block_data;
333
334 /* now we still have untransmitted LLC data, so we fill mac block */
335 rlc_data = m_rlc.block(bsn);
336 data = rlc_data->prepare(block_data_len);
337
338 rh = (struct rlc_dl_header *)data;
339 rh->pt = 0; /* Data Block */
340 rh->rrbp = rh->s_p = 0; /* Polling, set later, if required */
341 rh->usf = 7; /* will be set at scheduler */
342 rh->pr = 0; /* FIXME: power reduction */
343 rh->tfi = m_tfi; /* TFI */
344 rh->fbi = 0; /* Final Block Indicator, set late, if true */
345 rh->bsn = bsn; /* Block Sequence Number */
346 rh->e = 0; /* Extension bit, maybe set later */
347 e_pointer = data + 2; /* points to E of current chunk */
348 data += sizeof(*rh);
349 delimiter = data; /* where next length header would be stored */
350 space = block_data_len - sizeof(*rh);
351 while (1) {
Jacob Erlbeckcbb1e702015-03-25 12:21:55 +0100352 if (m_llc.frame_length() == 0) {
353 /* A header will need to by added, so we just need
354 * space-1 octets */
355 m_llc.put_dummy_frame(space - 1);
356
357 /* It is not clear, when the next real data will
358 * arrive, so request a DL ack/nack now */
359 request_dl_ack();
360
361 LOGP(DRLCMACDL, LOGL_DEBUG,
362 "-- Empty chunk, "
363 "added LLC dummy command of size %d\n",
364 m_llc.frame_length());
365 }
366
Daniel Willmannca102af2014-08-08 12:14:12 +0200367 chunk = m_llc.chunk_size();
Jacob Erlbeckcbb1e702015-03-25 12:21:55 +0100368
Daniel Willmannca102af2014-08-08 12:14:12 +0200369 /* if chunk will exceed block limit */
370 if (chunk > space) {
371 LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d "
372 "larger than space (%d) left in block: copy "
373 "only remaining space, and we are done\n",
374 chunk, space);
375 /* block is filled, so there is no extension */
376 *e_pointer |= 0x01;
377 /* fill only space */
378 m_llc.consume(data, space);
379 /* return data block as message */
380 break;
381 }
382 /* if FINAL chunk would fit precisely in space left */
383 if (chunk == space && llist_empty(&m_llc.queue)) {
384 LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d "
385 "would exactly fit into space (%d): because "
386 "this is a final block, we don't add length "
387 "header, and we are done\n", chunk, space);
388 LOGP(DRLCMACDL, LOGL_INFO, "Complete DL frame for "
389 "%s that fits precisely in last block: "
390 "len=%d\n", tbf_name(this), m_llc.frame_length());
391 gprs_rlcmac_dl_bw(this, m_llc.frame_length());
392 /* block is filled, so there is no extension */
393 *e_pointer |= 0x01;
394 /* fill space */
395 m_llc.consume(data, space);
396 m_llc.reset();
397 /* final block */
398 rh->fbi = 1; /* we indicate final block */
Jacob Erlbeck7c444152015-03-12 12:08:54 +0100399 request_dl_ack();
Daniel Willmannca102af2014-08-08 12:14:12 +0200400 set_state(GPRS_RLCMAC_FINISHED);
401 /* return data block as message */
402 break;
403 }
404 /* if chunk would fit exactly in space left */
405 if (chunk == space) {
406 LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d "
407 "would exactly fit into space (%d): add length "
408 "header with LI=0, to make frame extend to "
409 "next block, and we are done\n", chunk, space);
410 /* make space for delimiter */
411 if (delimiter != data)
412 memmove(delimiter + 1, delimiter,
413 data - delimiter);
414 data++;
415 space--;
416 /* add LI with 0 length */
417 li = (struct rlc_li_field *)delimiter;
418 li->e = 1; /* not more extension */
419 li->m = 0; /* shall be set to 0, in case of li = 0 */
420 li->li = 0; /* chunk fills the complete space */
421 // no need to set e_pointer nor increase delimiter
422 /* fill only space, which is 1 octet less than chunk */
423 m_llc.consume(data, space);
424 /* return data block as message */
425 break;
426 }
427 LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d is less "
428 "than remaining space (%d): add length header to "
429 "to delimit LLC frame\n", chunk, space);
430 /* the LLC frame chunk ends in this block */
431 /* make space for delimiter */
432 if (delimiter != data)
433 memmove(delimiter + 1, delimiter, data - delimiter);
434 data++;
435 space--;
436 /* add LI to delimit frame */
437 li = (struct rlc_li_field *)delimiter;
438 li->e = 0; /* Extension bit, maybe set later */
439 li->m = 0; /* will be set later, if there is more LLC data */
440 li->li = chunk; /* length of chunk */
441 e_pointer = delimiter; /* points to E of current delimiter */
442 delimiter++;
443 /* copy (rest of) LLC frame to space and reset later */
444 m_llc.consume(data, chunk);
445 data += chunk;
446 space -= chunk;
447 LOGP(DRLCMACDL, LOGL_INFO, "Complete DL frame for %s"
448 "len=%d\n", tbf_name(this), m_llc.frame_length());
449 gprs_rlcmac_dl_bw(this, m_llc.frame_length());
450 m_llc.reset();
451 /* dequeue next LLC frame, if any */
452 msg = llc_dequeue(gprs_bssgp_pcu_current_bctx());
453 if (msg) {
454 LOGP(DRLCMACDL, LOGL_INFO, "- Dequeue next LLC for "
455 "%s (len=%d)\n", tbf_name(this), msg->len);
456 m_llc.put_frame(msg->data, msg->len);
457 bts->llc_frame_sched();
458 msgb_free(msg);
459 }
460 /* if we have more data and we have space left */
461 if (space > 0 && m_llc.frame_length()) {
462 li->m = 1; /* we indicate more frames to follow */
463 continue;
464 }
465 /* if we don't have more LLC frames */
466 if (!m_llc.frame_length()) {
467 LOGP(DRLCMACDL, LOGL_DEBUG, "-- Final block, so we "
468 "done.\n");
469 li->e = 1; /* we cannot extend */
470 rh->fbi = 1; /* we indicate final block */
Jacob Erlbeck7c444152015-03-12 12:08:54 +0100471 request_dl_ack();
Daniel Willmannca102af2014-08-08 12:14:12 +0200472 set_state(GPRS_RLCMAC_FINISHED);
473 break;
474 }
475 /* we have no space left */
476 LOGP(DRLCMACDL, LOGL_DEBUG, "-- No space left, so we are "
477 "done.\n");
478 li->e = 1; /* we cannot extend */
479 break;
480 }
481 LOGP(DRLCMACDL, LOGL_DEBUG, "data block: %s\n",
482 osmo_hexdump(rlc_data->block, block_length));
483#warning "move this up?"
484 rlc_data->len = block_length;
485 /* raise send state and set ack state array */
486 m_window.m_v_b.mark_unacked(bsn);
487 m_window.increment_send();
488
Jacob Erlbeck7c444152015-03-12 12:08:54 +0100489 return create_dl_acked_block(fn, ts, bsn);
490}
491
Daniel Willmannca102af2014-08-08 12:14:12 +0200492struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(
493 const uint32_t fn, const uint8_t ts,
Jacob Erlbeck7c444152015-03-12 12:08:54 +0100494 const int index)
Daniel Willmannca102af2014-08-08 12:14:12 +0200495{
496 uint8_t *data;
497 struct rlc_dl_header *rh;
498 struct msgb *dl_msg;
499 uint8_t len;
Daniel Willmannefd5dbb2014-08-25 16:20:23 +0200500 bool need_poll;
Daniel Willmannca102af2014-08-08 12:14:12 +0200501
502 /* get data and header from current block */
503 data = m_rlc.block(index)->block;
504 len = m_rlc.block(index)->len;
505 rh = (struct rlc_dl_header *)data;
506
Jacob Erlbeck005ee7f2015-03-20 14:53:54 +0100507 /* If the TBF has just started, relate frames_since_last_poll to the
508 * current fn */
509 if (m_last_dl_poll_fn < 0)
510 m_last_dl_poll_fn = fn;
511
Daniel Willmannefd5dbb2014-08-25 16:20:23 +0200512 need_poll = state_flags & (1 << GPRS_RLCMAC_FLAG_TO_DL_ACK);
Daniel Willmannca102af2014-08-08 12:14:12 +0200513 /* Clear Polling, if still set in history buffer */
514 rh->s_p = 0;
515
516 /* poll after POLL_ACK_AFTER_FRAMES frames, or when final block is tx.
517 */
Jacob Erlbeck7c444152015-03-12 12:08:54 +0100518 if (m_tx_counter >= POLL_ACK_AFTER_FRAMES || m_dl_ack_requested ||
Daniel Willmannefd5dbb2014-08-25 16:20:23 +0200519 need_poll) {
Jacob Erlbeck7c444152015-03-12 12:08:54 +0100520 if (m_dl_ack_requested) {
Daniel Willmannca102af2014-08-08 12:14:12 +0200521 LOGP(DRLCMACDL, LOGL_DEBUG, "- Scheduling Ack/Nack "
Jacob Erlbeck7c444152015-03-12 12:08:54 +0100522 "polling, because is was requested explicitly "
523 "(e.g. first final block sent).\n");
Daniel Willmannefd5dbb2014-08-25 16:20:23 +0200524 } else if (need_poll) {
525 LOGP(DRLCMACDL, LOGL_DEBUG, "- Scheduling Ack/Nack "
Daniel Willmann635d47c2014-09-17 17:58:29 +0200526 "polling, because polling timed out.\n");
Daniel Willmannca102af2014-08-08 12:14:12 +0200527 } else {
528 LOGP(DRLCMACDL, LOGL_DEBUG, "- Scheduling Ack/Nack "
529 "polling, because %d blocks sent.\n",
530 POLL_ACK_AFTER_FRAMES);
531 }
532 /* scheduling not possible, because: */
533 if (poll_state != GPRS_RLCMAC_POLL_NONE)
534 LOGP(DRLCMACDL, LOGL_DEBUG, "Polling is already "
535 "sheduled for %s, so we must wait for "
536 "requesting downlink ack\n", tbf_name(this));
537 else if (control_ts != ts)
538 LOGP(DRLCMACDL, LOGL_DEBUG, "Polling cannot be "
539 "sheduled in this TS %d, waiting for "
540 "TS %d\n", ts, control_ts);
Daniel Willmannca102af2014-08-08 12:14:12 +0200541 else if (bts->sba()->find(trx->trx_no, ts, (fn + 13) % 2715648))
542 LOGP(DRLCMACDL, LOGL_DEBUG, "Polling cannot be "
543 "sheduled, because single block alllocation "
544 "already exists\n");
545 else {
546 LOGP(DRLCMACDL, LOGL_DEBUG, "Polling sheduled in this "
547 "TS %d\n", ts);
548 m_tx_counter = 0;
549 /* start timer whenever we send the final block */
550 if (rh->fbi == 1)
551 tbf_timer_start(this, 3191, bts_data()->t3191, 0);
552
553 /* schedule polling */
554 poll_state = GPRS_RLCMAC_POLL_SCHED;
555 poll_fn = (fn + 13) % 2715648;
556
Daniel Willmannefd5dbb2014-08-25 16:20:23 +0200557 /* Clear poll timeout flag */
558 state_flags &= ~(1 << GPRS_RLCMAC_FLAG_TO_DL_ACK);
559
Jacob Erlbeck7c444152015-03-12 12:08:54 +0100560 /* Clear request flag */
561 m_dl_ack_requested = false;
562
Daniel Willmannca102af2014-08-08 12:14:12 +0200563 /* set polling in header */
564 rh->rrbp = 0; /* N+13 */
565 rh->s_p = 1; /* Polling */
Jacob Erlbeck005ee7f2015-03-20 14:53:54 +0100566
567 m_last_dl_poll_fn = poll_fn;
Daniel Willmannca102af2014-08-08 12:14:12 +0200568 }
569 }
570
571 /* return data block as message */
572 dl_msg = msgb_alloc(len, "rlcmac_dl_data");
573 if (!dl_msg)
574 return NULL;
575
576 /* Increment TX-counter */
577 m_tx_counter++;
578
579 memcpy(msgb_put(dl_msg, len), data, len);
580 bts->rlc_sent();
581
582 return dl_msg;
583}
584
585int gprs_rlcmac_dl_tbf::update_window(const uint8_t ssn, const uint8_t *rbb)
586{
587 int16_t dist; /* must be signed */
588 uint16_t lost = 0, received = 0;
589 char show_rbb[65];
590 char show_v_b[RLC_MAX_SNS + 1];
591 const uint16_t mod_sns = m_window.mod_sns();
592
593 Decoding::extract_rbb(rbb, show_rbb);
594 /* show received array in debug (bit 64..1) */
595 LOGP(DRLCMACDL, LOGL_DEBUG, "- ack: (BSN=%d)\"%s\""
596 "(BSN=%d) R=ACK I=NACK\n", (ssn - 64) & mod_sns,
597 show_rbb, (ssn - 1) & mod_sns);
598
599 /* apply received array to receive state (SSN-64..SSN-1) */
600 /* calculate distance of ssn from V(S) */
601 dist = (m_window.v_s() - ssn) & mod_sns;
602 /* check if distance is less than distance V(A)..V(S) */
603 if (dist >= m_window.distance()) {
604 /* this might happpen, if the downlink assignment
605 * was not received by ms and the ack refers
606 * to previous TBF
607 * FIXME: we should implement polling for
608 * control ack!*/
609 LOGP(DRLCMACDL, LOGL_NOTICE, "- ack range is out of "
610 "V(A)..V(S) range %s Free TBF!\n", tbf_name(this));
611 return 1; /* indicate to free TBF */
612 }
613
614 m_window.update(bts, show_rbb, ssn,
615 &lost, &received);
616
617 /* report lost and received packets */
618 gprs_rlcmac_received_lost(this, received, lost);
619
620 /* raise V(A), if possible */
621 m_window.raise(m_window.move_window());
622
623 /* show receive state array in debug (V(A)..V(S)-1) */
624 m_window.show_state(show_v_b);
625 LOGP(DRLCMACDL, LOGL_DEBUG, "- V(B): (V(A)=%d)\"%s\""
626 "(V(S)-1=%d) A=Acked N=Nacked U=Unacked "
627 "X=Resend-Unacked I=Invalid\n",
628 m_window.v_a(), show_v_b,
629 m_window.v_s_mod(-1));
630
631 if (state_is(GPRS_RLCMAC_FINISHED) && m_window.window_empty()) {
632 LOGP(DRLCMACDL, LOGL_NOTICE, "Received acknowledge of "
633 "all blocks, but without final ack "
634 "inidcation (don't worry)\n");
635 }
636 return 0;
637}
638
639
640int gprs_rlcmac_dl_tbf::maybe_start_new_window()
641{
642 struct msgb *msg;
643 uint16_t received;
644
645 LOGP(DRLCMACDL, LOGL_DEBUG, "- Final ACK received.\n");
646 /* range V(A)..V(S)-1 */
647 received = m_window.count_unacked();
648
649 /* report all outstanding packets as received */
650 gprs_rlcmac_received_lost(this, received, 0);
651
652 set_state(GPRS_RLCMAC_WAIT_RELEASE);
653
654 /* check for LLC PDU in the LLC Queue */
655 msg = llc_dequeue(gprs_bssgp_pcu_current_bctx());
656 if (!msg) {
657 /* no message, start T3193, change state to RELEASE */
658 LOGP(DRLCMACDL, LOGL_DEBUG, "- No new message, so we release.\n");
659 /* start T3193 */
660 tbf_timer_start(this, 3193,
661 bts_data()->t3193_msec / 1000,
662 (bts_data()->t3193_msec % 1000) * 1000);
663
664 return 0;
665 }
666
667 /* we have more data so we will re-use this tbf */
668 reuse_tbf(msg->data, msg->len);
669 msgb_free(msg);
670 return 0;
671}
672
673int gprs_rlcmac_dl_tbf::rcvd_dl_ack(uint8_t final_ack, uint8_t ssn, uint8_t *rbb)
674{
675 LOGP(DRLCMACDL, LOGL_DEBUG, "%s downlink acknowledge\n", tbf_name(this));
676
677 if (!final_ack)
678 return update_window(ssn, rbb);
679 return maybe_start_new_window();
680}
681
682void gprs_rlcmac_dl_tbf::reuse_tbf(const uint8_t *data, const uint16_t len)
683{
Daniel Willmanne4818152014-08-15 16:52:09 +0200684 uint8_t trx;
685 struct gprs_rlcmac_dl_tbf *new_tbf;
686 int8_t tfi; /* must be signed */
Daniel Willmanne4818152014-08-15 16:52:09 +0200687 struct msgb *msg;
688
Daniel Willmannca102af2014-08-08 12:14:12 +0200689 bts->tbf_reused();
Daniel Willmanne4818152014-08-15 16:52:09 +0200690
691 tfi = bts->tfi_find_free(GPRS_RLCMAC_DL_TBF, &trx, this->trx->trx_no);
692 if (tfi < 0) {
693 LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH resource\n");
694 /* FIXME: send reject */
695 return;
696 }
697 new_tbf = tbf_alloc_dl_tbf(bts->bts_data(), NULL, tfi, trx, ms_class, 0);
698 if (!new_tbf) {
699 LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH resource\n");
700 /* FIXME: send reject */
701 return;
702 }
703
704 new_tbf->m_tlli = m_tlli;
705 new_tbf->m_tlli_valid = m_tlli_valid;
706 new_tbf->ta = ta;
707 new_tbf->assign_imsi(m_imsi);
708
709 /* Copy over all data to the new TBF */
710 new_tbf->m_llc.put_frame(data, len);
Daniel Willmannca102af2014-08-08 12:14:12 +0200711 bts->llc_frame_sched();
712
Daniel Willmanne4818152014-08-15 16:52:09 +0200713 while ((msg = m_llc.dequeue()))
714 new_tbf->m_llc.enqueue(msg);
715
Daniel Willmannca102af2014-08-08 12:14:12 +0200716 /* reset rlc states */
717 m_tx_counter = 0;
718 m_wait_confirm = 0;
719 m_window.reset();
720
Jacob Erlbeck297edf72015-02-26 14:59:52 +0100721 /* mark TLLI as invalid */
722 m_tlli_valid = 0;
723
Daniel Willmannca102af2014-08-08 12:14:12 +0200724 /* keep to flags */
725 state_flags &= GPRS_RLCMAC_FLAG_TO_MASK;
726 state_flags &= ~(1 << GPRS_RLCMAC_FLAG_CCCH);
727
728 update();
729
730 LOGP(DRLCMAC, LOGL_DEBUG, "%s Trigger dowlink assignment on PACCH, "
731 "because another LLC PDU has arrived in between\n",
732 tbf_name(this));
Daniel Willmanne4818152014-08-15 16:52:09 +0200733 bts->trigger_dl_ass(new_tbf, this, NULL);
Daniel Willmannca102af2014-08-08 12:14:12 +0200734}
735
736bool gprs_rlcmac_dl_tbf::dl_window_stalled() const
737{
738 return m_window.window_stalled();
739}
740
Jacob Erlbeckeceb9102015-03-20 14:41:50 +0100741void gprs_rlcmac_dl_tbf::request_dl_ack()
742{
743 m_dl_ack_requested = true;
744}
745
746bool gprs_rlcmac_dl_tbf::need_control_ts() const
747{
748 if (poll_state != GPRS_RLCMAC_POLL_NONE)
749 return false;
750
751 return state_flags & (1 << GPRS_RLCMAC_FLAG_TO_DL_ACK) ||
752 m_tx_counter >= POLL_ACK_AFTER_FRAMES ||
753 m_dl_ack_requested;
754}
755
756bool gprs_rlcmac_dl_tbf::have_data() const
757{
758 return m_llc.chunk_size() > 0 || !llist_empty(&m_llc.queue);
759}
Jacob Erlbeck005ee7f2015-03-20 14:53:54 +0100760
761int gprs_rlcmac_dl_tbf::frames_since_last_poll(unsigned fn) const
762{
763 unsigned wrapped;
764 if (m_last_dl_poll_fn < 0)
765 return -1;
766
767 wrapped = (fn + 2715648 - m_last_dl_poll_fn) % 2715648;
768 if (wrapped < 2715648/2)
769 return wrapped;
770 else
771 return wrapped - 2715648;
772}
773