aboutsummaryrefslogtreecommitdiffstats
path: root/src/encoding.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/encoding.cpp')
-rw-r--r--src/encoding.cpp131
1 files changed, 108 insertions, 23 deletions
diff --git a/src/encoding.cpp b/src/encoding.cpp
index 8fa4bf6..ea38b77 100644
--- a/src/encoding.cpp
+++ b/src/encoding.cpp
@@ -24,6 +24,7 @@
#include <bts.h>
#include <tbf.h>
#include <gprs_debug.h>
+#include <egprs_rlc_compression.h>
extern "C" {
#include <osmocom/gprs/protocol/gsm_04_60.h>
@@ -699,20 +700,44 @@ static void write_packet_uplink_ack_gprs(
static void write_packet_ack_nack_desc_egprs(
struct gprs_rlcmac_bts *bts, bitvec * dest, unsigned& wp,
- gprs_rlc_ul_window *window, bool is_final)
+ gprs_rlc_ul_window *window, bool is_final, unsigned& rest_bits)
{
- int urbb_len = 0;
- int len;
+ unsigned int urbb_len = 0;
+ uint8_t crbb_len = 0;
+ uint8_t len;
bool bow = true;
bool eow = true;
int ssn = window->mod_sns(window->v_q() + 1);
- int num_blocks = window->mod_sns(window->v_r() - window->v_q());
+ unsigned int num_blocks = window->mod_sns(window->v_r() - window->v_q());
int esn_crbb = window->mod_sns(ssn - 1);
- /* Bit 0 at the end is mandatory Table 11.2.28.1 in 44.060 */
- int rest_bits = dest->data_len * 8 - wp - 1;
+ static uint8_t rbb[RLC_EGPRS_MAX_WS] = {'\0'};
+ uint8_t iter = 0;
int is_compressed = 0;
+ bool try_compression = false;
+ uint8_t ucmp_bmplen;
+ uint8_t crbb_bitmap[23] = {'\0'};
+ bitvec ucmp_vec;
+ bitvec crbb_vec;
+ uint8_t uclen_crbb = 0;
bool len_coded = true;
+ uint8_t crbb_start_clr_code;
uint8_t i;
+#if 0
+ /* static size of 16 bits*/
+ ..0. .... = ACKNACK: (Union)
+ Desc
+
+ ...0 .... = FINAL_ACK_INDICATION: False
+
+ .... 1... = BEGINNING_OF_WINDOW: 1
+
+ .... .1.. = END_OF_WINDOW: 1
+
+ .... ..10 0101 0001 1... .... = STARTING_SEQUENCE_NUMBER: 1187
+
+ .0.. .... = CRBB Exist: 0
+#endif
+ rest_bits -= 16;
if (num_blocks > 0)
/* V(Q) is NACK and omitted -> SSN = V(Q) + 1 */
@@ -720,27 +745,67 @@ static void write_packet_ack_nack_desc_egprs(
if (num_blocks > window->ws())
num_blocks = window->ws();
- /* TODO Compression support */
- if (is_compressed == 0) {
- /* Union bit takes 1 bit */
- /* Other fields in descr for uncompresed bitmap takes 15 bits*/
+ /* Try Compression as number of blocks does not fit */
+ if (num_blocks > rest_bits) {
+ try_compression = true;
+ }
+ if (try_compression == true) {
+ ucmp_bmplen = window->update_egprs_rbb(rbb);
+ ucmp_vec.data = rbb;
+ ucmp_vec.cur_bit = ucmp_bmplen;
+ ucmp_vec.data_len = 127;
+ crbb_vec.data = crbb_bitmap;
+ crbb_vec.cur_bit = 0;
+ crbb_vec.data_len = 127;
+ LOGP(DRLCMACUL, LOGL_DEBUG,
+ "rest_bits=%d uncompressed len %d and uncompressed bitmap = %s\n",
+ rest_bits, ucmp_bmplen,
+ osmo_hexdump(ucmp_vec.data, (ucmp_bmplen+7)/8));
+
+ is_compressed = egprs_compress::compress_rbb(&ucmp_vec, /* Uncompressed bitmap*/
+ &crbb_vec, /*Compressed bitmap vector */
+ &uclen_crbb,
+ (rest_bits - 16));/* CRBBlength:7 colourcode:1 dissector length:8*/
+ LOGP(DRLCMACUL, LOGL_DEBUG,
+ "the ucmp len=%d uclen_crbb=%d num_blocks=%d crbb length %d, "
+ "and the CRBB bitmap = %s\n",
+ ucmp_bmplen, uclen_crbb, num_blocks, crbb_vec.cur_bit,
+ osmo_hexdump(crbb_bitmap, (crbb_vec.cur_bit+7)/8));
+ crbb_len = crbb_vec.cur_bit;
+ }
- if (num_blocks > rest_bits - 15 - 1) {
+ if (is_compressed == 0) {
+ /* length field takes 8 bits*/
+ if (num_blocks > rest_bits - 8) {
eow = false;
- urbb_len = rest_bits - 15 - 1;
+ urbb_len = rest_bits;
len_coded = false;
- } else if (num_blocks == rest_bits - 15 - 1) {
- urbb_len = rest_bits - 15 - 1;
+ } else if (num_blocks == rest_bits) {
+ urbb_len = rest_bits;
len_coded = false;
- /* Union bit takes 1 bit length field takes 8 bits*/
- } else if (num_blocks > rest_bits - 15 - 9) {
- eow = false;
- urbb_len = rest_bits - 15 - 9;
} else
urbb_len = num_blocks;
+
len = urbb_len + 15;
} else {
- /* TODO Compressed bitmap */
+ if (num_blocks > uclen_crbb) {
+ eow = false;
+ urbb_len = num_blocks - uclen_crbb;
+ }
+ /* Union bit takes 1 bit */
+ /* Other fields in descr of compresed bitmap takes 23 bits
+ * -8 = CRBB_STARTING_COLOR_CODE + CRBB_LENGTH */
+ if (urbb_len > (rest_bits - crbb_len - 8)) {
+ eow = false;
+ len_coded = false;
+ urbb_len = rest_bits - crbb_len - 8;
+ /* -16 = ACKNACK Dissector length + CRBB_STARTING_COLOR_CODE + CRBB_LENGTH */
+ } else if (urbb_len > (rest_bits - crbb_len - 16)) {
+ eow = false;
+ len_coded = false;
+ urbb_len = rest_bits - crbb_len - 16;
+ }
+ len = urbb_len + crbb_len + 23;
}
/* EGPRS Ack/Nack Description IE */
@@ -756,14 +821,32 @@ static void write_packet_ack_nack_desc_egprs(
bitvec_write_field(dest, wp, eow, 1); // END_OF_WINDOW
bitvec_write_field(dest, wp, ssn, 11); // STARTING_SEQUENCE_NUMBER
if (is_compressed) {
- /* TODO Add CRBB support */
- } else
+ bitvec_write_field(dest, wp, 1, 1); // CRBB_Exist
+ bitvec_write_field(dest, wp, crbb_len, 7); // CRBB_LENGTH
+ crbb_start_clr_code = (0x80 & ucmp_vec.data[0])>>7;
+ bitvec_write_field(dest, wp, crbb_start_clr_code, 1); // CRBB_clr_code
+ LOGP(DRLCMACUL, LOGL_DEBUG,
+ "EGPRS CRBB, crbb_len = %d, crbb_start_clr_code = %d\n",
+ crbb_len, crbb_start_clr_code);
+ while (crbb_len != 0) {
+ if (crbb_len > 8) {
+ bitvec_write_field(dest, wp, crbb_bitmap[iter], 8);
+ crbb_len = crbb_len - 8;
+ iter++;
+ } else {
+ bitvec_write_field(dest, wp, crbb_bitmap[iter], crbb_len);
+ crbb_len = 0;
+ }
+ }
+ esn_crbb = window->mod_sns(esn_crbb + uclen_crbb);
+ } else {
bitvec_write_field(dest, wp, 0, 1); // CRBB_Exist
+ }
LOGP(DRLCMACUL, LOGL_DEBUG,
"EGPRS URBB, urbb len = %d, SSN = %d, ESN_CRBB = %d, "
"len present = %s,desc len = %d, "
"SNS = %d, WS = %d, V(Q) = %d, V(R) = %d%s%s\n",
- urbb_len, ssn, esn_crbb, len_coded ? "yes" : "No", len,
+ urbb_len, ssn, esn_crbb, len_coded ? "yes" : "No" , len,
window->sns(), window->ws(), window->v_q(), window->v_r(),
bow ? ", BOW" : "", eow ? ", EOW" : "");
@@ -795,7 +878,9 @@ static void write_packet_uplink_ack_egprs(
bitvec_write_field(dest, wp, 0, 1); // 0: don't have Power Control Parameters
bitvec_write_field(dest, wp, 0, 1); // 0: don't have Extension Bits
- write_packet_ack_nack_desc_egprs(bts, dest, wp, &tbf->m_window, is_final);
+ /* -2 for last bit 0 mandatory and REL5 not supported */
+ unsigned bits_ack_nack = dest->data_len * 8 - wp - 2;
+ write_packet_ack_nack_desc_egprs(bts, dest, wp, &tbf->m_window, is_final, bits_ack_nack);
bitvec_write_field(dest, wp, 0, 1); // fixed 0
bitvec_write_field(dest, wp, 0, 1); // 0: don't have REL 5