aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/tbf_dl.cpp131
-rw-r--r--tests/tbf/TbfTest.err28
2 files changed, 34 insertions, 125 deletions
diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp
index a1f8b60a..35c3ccb6 100644
--- a/src/tbf_dl.cpp
+++ b/src/tbf_dl.cpp
@@ -424,13 +424,14 @@ void gprs_rlcmac_dl_tbf::schedule_next_frame()
struct msgb *gprs_rlcmac_dl_tbf::create_new_bsn(const uint32_t fn, const uint8_t ts)
{
- struct rlc_li_field *li;
- uint8_t *delimiter, *data, *e_pointer;
- uint16_t space, chunk;
+ uint8_t *data;
gprs_rlc_data *rlc_data;
const uint16_t bsn = m_window.v_s();
GprsCodingScheme cs = current_cs();
gprs_rlc_data_block_info *rdbi;
+ int num_chunks = 0;
+ int write_offset = 0;
+ Encoding::AppendResult ar;
if (m_llc.frame_length() == 0)
schedule_next_frame();
@@ -457,12 +458,11 @@ struct msgb *gprs_rlcmac_dl_tbf::create_new_bsn(const uint32_t fn, const uint8_t
rdbi->bsn = bsn; /* Block Sequence Number */
rdbi->e = 1; /* Extension bit, maybe set later (1: no extension) */
- e_pointer = NULL; /* points to E of current chunk if it is stored in an
- extension byte */
- delimiter = data; /* where next length header would be stored */
- space = block_data_len;
- while (1) {
+ do {
+ bool is_final;
+
if (m_llc.frame_length() == 0) {
+ int space = block_data_len - write_offset;
/* A header will need to by added, so we just need
* space-1 octets */
m_llc.put_dummy_frame(space - 1);
@@ -482,119 +482,28 @@ struct msgb *gprs_rlcmac_dl_tbf::create_new_bsn(const uint32_t fn, const uint8_t
m_llc.frame_length(), frames_since_last_drain(fn));
}
- chunk = m_llc.chunk_size();
-
- /* if chunk will exceed block limit */
- if (chunk > space) {
- LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d "
- "larger than space (%d) left in block: copy "
- "only remaining space, and we are done\n",
- chunk, space);
- /* block is filled, so there is no extension */
- if (e_pointer)
- *e_pointer |= 0x01;
- /* fill only space */
- m_llc.consume(data, space);
- /* return data block as message */
- break;
- }
- /* if FINAL chunk would fit precisely in space left */
- if (chunk == space && llc_queue()->size() == 0 && !keep_open(fn))
- {
- LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d "
- "would exactly fit into space (%d): because "
- "this is a final block, we don't add length "
- "header, and we are done\n", chunk, space);
- LOGP(DRLCMACDL, LOGL_INFO, "Complete DL frame for "
- "%s that fits precisely in last block: "
- "len=%d\n", tbf_name(this), m_llc.frame_length());
- gprs_rlcmac_dl_bw(this, m_llc.frame_length());
- /* block is filled, so there is no extension */
- if (e_pointer)
- *e_pointer |= 0x01;
- /* fill space */
- m_llc.consume(data, space);
- m_llc.reset();
- /* final block */
- rdbi->cv = 0; /* we indicate final block */
- request_dl_ack();
- set_state(GPRS_RLCMAC_FINISHED);
- /* return data block as message */
- break;
- }
- /* if chunk would fit exactly in space left */
- if (chunk == space) {
- LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d "
- "would exactly fit into space (%d): add length "
- "header with LI=0, to make frame extend to "
- "next block, and we are done\n", chunk, space);
- /* make space for delimiter */
- if (delimiter != data)
- memmove(delimiter + 1, delimiter,
- data - delimiter);
- data++;
- space--;
- /* add LI with 0 length */
- li = (struct rlc_li_field *)delimiter;
- li->e = 1; /* not more extension */
- li->m = 0; /* shall be set to 0, in case of li = 0 */
- li->li = 0; /* chunk fills the complete space */
- // no need to set e_pointer nor increase delimiter
- /* fill only space, which is 1 octet less than chunk */
- m_llc.consume(data, space);
- /* return data block as message */
+ is_final = llc_queue()->size() == 0 && !keep_open(fn);
+
+ ar = Encoding::rlc_data_to_dl_append(rdbi,
+ &m_llc, &write_offset, &num_chunks, data, is_final);
+
+ if (ar == Encoding::AR_NEED_MORE_BLOCKS)
break;
- }
- LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d is less "
- "than remaining space (%d): add length header to "
- "to delimit LLC frame\n", chunk, space);
- /* the LLC frame chunk ends in this block */
- /* make space for delimiter */
- if (delimiter != data)
- memmove(delimiter + 1, delimiter, data - delimiter);
- data++;
- space--;
- /* add LI to delimit frame */
- li = (struct rlc_li_field *)delimiter;
- li->e = 0; /* Extension bit, maybe set later */
- li->m = 0; /* will be set later, if there is more LLC data */
- li->li = chunk; /* length of chunk */
- rdbi->e = 0; /* 0: extensions present */
- e_pointer = delimiter; /* points to E of current delimiter */
- delimiter++;
- /* copy (rest of) LLC frame to space and reset later */
- m_llc.consume(data, chunk);
- data += chunk;
- space -= chunk;
LOGP(DRLCMACDL, LOGL_INFO, "Complete DL frame for %s"
"len=%d\n", tbf_name(this), m_llc.frame_length());
gprs_rlcmac_dl_bw(this, m_llc.frame_length());
m_llc.reset();
- /* dequeue next LLC frame, if any */
- schedule_next_frame();
- /* if we have more data and we have space left */
- if (space > 0 && (m_llc.frame_length() || keep_open(fn))) {
- li->m = 1; /* we indicate more frames to follow */
- continue;
- }
- /* if we don't have more LLC frames */
- if (!m_llc.frame_length() && !keep_open(fn)) {
- LOGP(DRLCMACDL, LOGL_DEBUG, "-- Final block, so we "
- "done.\n");
- li->e = 1; /* we cannot extend */
- rdbi->cv = 0; /* we indicate final block */
+ if (is_final) {
request_dl_ack();
set_state(GPRS_RLCMAC_FINISHED);
- break;
}
- /* we have no space left */
- LOGP(DRLCMACDL, LOGL_DEBUG, "-- No space left, so we are "
- "done.\n");
- li->e = 1; /* we cannot extend */
- break;
- }
+
+ /* dequeue next LLC frame, if any */
+ schedule_next_frame();
+ } while (ar == Encoding::AR_COMPLETED_SPACE_LEFT);
+
LOGP(DRLCMACDL, LOGL_DEBUG, "data block (BSN %d, %s): %s\n",
bsn, rlc_data->cs.name(),
osmo_hexdump(rlc_data->block, block_data_len));
diff --git a/tests/tbf/TbfTest.err b/tests/tbf/TbfTest.err
index 80aee605..ad0b69bb 100644
--- a/tests/tbf/TbfTest.err
+++ b/tests/tbf/TbfTest.err
@@ -294,8 +294,8 @@ TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==9)
- Sending new block at BSN 9, CS=CS-1
-- Chunk with length 20 would exactly fit into space (20): add length header with LI=0, to make frame extend to next block, and we are done
data block (BSN 9, CS-1): 01 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5 c6
-msg block (BSN 9, CS-1): 07 00 13 01 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5 c6
-Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=43 block=10 data=07 00 13 01 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5 c6
+msg block (BSN 9, CS-1): 07 00 12 01 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5 c6
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=43 block=10 data=07 00 12 01 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5 c6
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==10)
- Sending new block at BSN 10, CS=CS-1
@@ -376,8 +376,8 @@ TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==20)
Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW)len=200
-- Empty chunk, added LLC dummy command of size 16, drained_since=0
-- Chunk with length 16 is less than remaining space (17): add length header to to delimit LLC frame
-Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW)len=16
-- No space left, so we are done.
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW)len=16
data block (BSN 20, CS-1): 0a 41 c6 c7 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
Polling is already sheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW), so we must wait for requesting downlink ack
@@ -413,8 +413,8 @@ TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink (V(A)==21 .. V(S)==21)
- Sending new block at BSN 21, CS=CS-1
-- Empty chunk, added LLC dummy command of size 19, drained_since=4
-- Chunk with length 19 is less than remaining space (20): add length header to to delimit LLC frame
-Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW)len=19
-- No space left, so we are done.
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW)len=19
data block (BSN 21, CS-1): 4d 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
Polling is already sheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW), so we must wait for requesting downlink ack
@@ -430,8 +430,8 @@ TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink (V(A)==22 .. V(S)==22)
- Sending new block at BSN 22, CS=CS-1
-- Empty chunk, added LLC dummy command of size 19, drained_since=112
-- Chunk with length 19 is less than remaining space (20): add length header to to delimit LLC frame
-Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW)len=19
-- Final block, so we done.
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW)len=19
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) changes state from FLOW to FINISHED
data block (BSN 22, CS-1): 4d 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
@@ -1371,26 +1371,26 @@ TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=ASSIGN) downlink (V(A)==0 .. V(S)==0)
- Dequeue next LLC for TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=ASSIGN) (len=19)
- Sending new block at BSN 0, CS=CS-1
-- Chunk with length 19 is less than remaining space (20): add length header to to delimit LLC frame
+-- No space left, so we are done.
Complete DL frame for TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=ASSIGN)len=19
- Dequeue next LLC for TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=ASSIGN) (len=19)
--- No space left, so we are done.
data block (BSN 0, CS-1): 4d 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
msg block (BSN 0, CS-1): 07 00 00 4d 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
MSG = 07 00 00 4d 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=ASSIGN) downlink (V(A)==0 .. V(S)==1)
- Sending new block at BSN 1, CS=CS-1
-- Chunk with length 19 is less than remaining space (20): add length header to to delimit LLC frame
+-- No space left, so we are done.
Complete DL frame for TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=ASSIGN)len=19
- Dequeue next LLC for TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=ASSIGN) (len=19)
--- No space left, so we are done.
data block (BSN 1, CS-1): 4d 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
msg block (BSN 1, CS-1): 07 00 02 4d 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
MSG = 07 00 02 4d 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=ASSIGN) downlink (V(A)==0 .. V(S)==2)
- Sending new block at BSN 2, CS=CS-1
-- Chunk with length 19 is less than remaining space (20): add length header to to delimit LLC frame
-Complete DL frame for TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=ASSIGN)len=19
-- Final block, so we done.
+Complete DL frame for TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=ASSIGN)len=19
TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=ASSIGN) changes state from ASSIGN to FINISHED
data block (BSN 2, CS-1): 4d 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03
- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
@@ -1663,8 +1663,8 @@ TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==0)
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=10)
- Sending new block at BSN 0, CS=CS-4
-- Chunk with length 10 is less than remaining space (50): add length header to to delimit LLC frame
-Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=10
-- Final block, so we done.
+Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=10
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) changes state from FLOW to FINISHED
data block (BSN 0, CS-4): 29 52 41 55 5f 41 43 43 45 50 54 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
@@ -2334,9 +2334,9 @@ TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==6)
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Chunk with length 13 is less than remaining space (14): add length header to to delimit LLC frame
+-- No space left, so we are done.
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
--- No space left, so we are done.
data block (BSN 6, CS-1): 16 35 45 54 20 30 38 4c 4c 43 20 50 41 43 4b 45 54 20 30 39
msg block (BSN 6, CS-1): 07 00 0c 16 35 45 54 20 30 38 4c 4c 43 20 50 41 43 4b 45 54 20 30 39
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654305 block=4 data=00 00 0c 16 35 45 54 20 30 38 4c 4c 43 20 50 41 43 4b 45 54 20 30 39
@@ -2469,9 +2469,9 @@ TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==13)
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Chunk with length 13 is less than remaining space (14): add length header to to delimit LLC frame
+-- No space left, so we are done.
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
--- No space left, so we are done.
data block (BSN 13, CS-1): 16 35 45 54 20 31 38 4c 4c 43 20 50 41 43 4b 45 54 20 31 39
msg block (BSN 13, CS-1): 07 00 1a 16 35 45 54 20 31 38 4c 4c 43 20 50 41 43 4b 45 54 20 31 39
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654335 block=11 data=00 00 1a 16 35 45 54 20 31 38 4c 4c 43 20 50 41 43 4b 45 54 20 31 39
@@ -2604,9 +2604,9 @@ TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==20)
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Chunk with length 13 is less than remaining space (14): add length header to to delimit LLC frame
+-- No space left, so we are done.
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
--- No space left, so we are done.
data block (BSN 20, CS-1): 16 35 45 54 20 32 38 4c 4c 43 20 50 41 43 4b 45 54 20 32 39
- Scheduling Ack/Nack polling, because 20 blocks sent.
Polling sheduled in this TS 7
@@ -2742,8 +2742,8 @@ TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==27)
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Chunk with length 13 is less than remaining space (14): add length header to to delimit LLC frame
-Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
-- Final block, so we done.
+Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) changes state from FLOW to FINISHED
data block (BSN 27, CS-1): 16 35 45 54 20 33 38 4c 4c 43 20 50 41 43 4b 45 54 20 33 39
- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
@@ -2997,8 +2997,8 @@ Scheduling data message at RTS for DL TFI=1 (TRX=0, TS=7) prio=3
TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==10)
- Sending new block at BSN 10, CS=CS-1
-- Chunk with length 19 is less than remaining space (20): add length header to to delimit LLC frame
-Complete DL frame for TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=21
-- Final block, so we done.
+Complete DL frame for TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=21
TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW) changes state from FLOW to FINISHED
data block (BSN 10, CS-1): 4d 43 20 50 41 43 4b 45 54 20 30 39 20 28 54 42 46 20 32 29
- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).