diff options
-rw-r--r-- | src/tbf_dl.cpp | 131 | ||||
-rw-r--r-- | tests/tbf/TbfTest.err | 28 |
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). |