From 2585451408951696e94a53d62137b39db3926bb7 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 17 Jun 2019 01:50:33 +0200 Subject: tests: test encoding of egprs ul ack/nacks Test the encoding with uncompressed and compressed acknowledgements. Change-Id: I35d6b5e312faeb116ddda6b33c550840da1496fe --- tests/types/TypesTest.cpp | 294 ++++++++++++++++++++++++++++++++++++++++++++++ tests/types/TypesTest.err | 10 ++ 2 files changed, 304 insertions(+) (limited to 'tests') diff --git a/tests/types/TypesTest.cpp b/tests/types/TypesTest.cpp index 589f1562..b2ddc94f 100644 --- a/tests/types/TypesTest.cpp +++ b/tests/types/TypesTest.cpp @@ -2,6 +2,7 @@ * TypesTest.cpp Test the primitive data types * * Copyright (C) 2013 by Holger Hans Peter Freyther + * Copyright (C) 2019 by Sysmocom s.f.m.c. GmbH * * All Rights Reserved * @@ -26,6 +27,7 @@ #include "encoding.h" #include "decoding.h" #include "gprs_rlcmac.h" +#include "egprs_rlc_compression.h" extern "C" { #include @@ -431,6 +433,296 @@ static void test_rlc_dl_ul_basic() } } +struct crbb_test { + bool has_crbb; + bitvec *crbb; + uint8_t length; + bool color_code; +}; + +static void extract_egprs_ul_ack_nack( + struct gprs_rlcmac_ul_tbf *tbf, + struct bitvec *dest, + uint16_t *ssn, + struct crbb_test *crbb_test, + struct bitvec **urbb, + bool is_final) +{ + uint8_t bytelength; + + /* Start of Ack/Nack Description struct */ + uint8_t startbit_ack_nack = 0; + + bool has_length = false; + uint8_t length = 0; + + bool bow = false; + uint8_t urbb_length = 0; + dest->cur_bit = 0; + + /* ignore the first 8 bit */ + bitvec_get_uint(dest, 8); + + /* uplink ack/nack message content */ + OSMO_ASSERT(bitvec_get_uint(dest, 6) == 0b001001); + + /* ignore page mode*/ + bitvec_get_uint(dest, 2); + + /* fix 00 */ + OSMO_ASSERT(bitvec_get_uint(dest, 2) == 0); + + OSMO_ASSERT(bitvec_get_uint(dest, 5) == tbf->tfi()); + + /* egprs ack/nack */ + OSMO_ASSERT(bitvec_get_uint(dest, 1) == 1); + + /* fix 00 */ + OSMO_ASSERT(bitvec_get_uint(dest, 2) == 0); + + /* ignore Channel Coding Command */ + bitvec_get_uint(dest, 4); + + /* we always allow resegmentation */ + OSMO_ASSERT(bitvec_get_uint(dest, 1) == 1); + + /* ignore pre emptive transmission */ + bitvec_get_uint(dest, 1); + + /* ignore PRR retransmission request */ + bitvec_get_uint(dest, 1); + + /* ignore ARAC retransmission request */ + bitvec_get_uint(dest, 1); + + if (bitvec_get_uint(dest, 1)) { + OSMO_ASSERT((uint32_t) bitvec_get_uint(dest, 32) == tbf->tlli()); + } + + /* ignore TBF_EST */ + bitvec_get_uint(dest, 1); + + /* Timing Advance */ + if (bitvec_get_uint(dest, 1)) { + /* Timing Advance Value */ + if (bitvec_get_uint(dest, 1)) + bitvec_get_uint(dest, 6); + + /* Timing Advance Index*/ + if (bitvec_get_uint(dest, 1)) + bitvec_get_uint(dest, 6); + /* Timing Advance Timeslot Number */ + bitvec_get_uint(dest, 3); + } + + /* Packet Extended Timing Advance */ + if (bitvec_get_uint(dest, 1)) + bitvec_get_uint(dest, 2); + + /* Power Control Parameters */ + if (bitvec_get_uint(dest, 1)) { + /* Alpha */ + bitvec_get_uint(dest, 4); + for (int i=0; i<8 ; i++) { + /* Gamma */ + if (bitvec_get_uint(dest, 1)) + bitvec_get_uint(dest, 5); + } + } + + /* Extension Bits */ + if (bitvec_get_uint(dest, 1)) { + int length = bitvec_get_uint(dest, 6); + bitvec_get_uint(dest, length); + } + + /* Beging of the EGPRS Ack/Nack */ + has_length = bitvec_get_uint(dest, 1); + if (has_length) { + length = bitvec_get_uint(dest, 8); + } else { + /* remaining bits is the length */ + length = dest->data_len * 8 - dest->cur_bit; + } + startbit_ack_nack = dest->cur_bit; + + OSMO_ASSERT(bitvec_get_uint(dest, 1) == is_final); + + /* bow Begin Of Window */ + bow = bitvec_get_uint(dest, 1); + /* TODO: check if bow is always present in our implementation */ + + /* eow End Of Window */ + /* TODO: eow checking */ + bitvec_get_uint(dest, 1); + + *ssn = bitvec_get_uint(dest, 11); + if (bow) { + OSMO_ASSERT(*ssn == tbf->window()->v_q() + 1); + } + + crbb_test->has_crbb = bitvec_get_uint(dest, 1); + if (crbb_test->has_crbb) { + crbb_test->length = bitvec_get_uint(dest, 7); + crbb_test->color_code = bitvec_get_uint(dest, 1); + if (crbb_test->length % 8) + bytelength = crbb_test->length * 8 + 1; + else + bytelength = crbb_test->length * 8; + + crbb_test->crbb = bitvec_alloc(bytelength, tall_pcu_ctx); + for (int i=0; ilength; i++) + bitvec_set_bit(crbb_test->crbb, bitvec_get_bit_pos(dest, dest->cur_bit + i)); + + dest->cur_bit += crbb_test->length; + } + + OSMO_ASSERT(dest->cur_bit < dest->data_len * 8); + urbb_length = length - (dest->cur_bit - startbit_ack_nack); + + if (urbb_length > 0) { + if (urbb_length % 8) + bytelength = urbb_length / 8 + 1; + else + bytelength = urbb_length / 8; + + *urbb = bitvec_alloc(bytelength, tall_pcu_ctx); + for (int i=urbb_length; i>0; i--) { + bitvec_set_bit(*urbb, bitvec_get_bit_pos(dest, dest->cur_bit + i - 1)); + } + } +} + +static void check_egprs_bitmap(struct gprs_rlcmac_ul_tbf *tbf, uint16_t ssn, struct crbb_test *crbb_test, bitvec *urbb, unsigned int *rbb_size) +{ + gprs_rlc_ul_window *win = tbf->window(); + uint8_t rbb_should[RLC_EGPRS_MAX_WS] = {0}; + bitvec rbb_should_bv; + rbb_should_bv.data = rbb_should; + rbb_should_bv.data_len = RLC_EGPRS_MAX_WS; + rbb_should_bv.cur_bit = 0; + + /* rbb starting at ssn without mod */ + bitvec *rbb_ssn_bv = bitvec_alloc(RLC_EGPRS_MAX_WS, tall_pcu_ctx); + + /* even any ssn is allowed, pcu should only use v_q() at least for now */ + OSMO_ASSERT(ssn == (win->v_q() + 1)); + + if (crbb_test->has_crbb) { + OSMO_ASSERT(0 == egprs_compress::decompress_crbb( + crbb_test->length, + crbb_test->color_code, + crbb_test->crbb->data, + rbb_ssn_bv)); + } + + if (urbb && urbb->cur_bit > 0) { + for (unsigned int i=0; icur_bit; i++) { + bitvec_set_bit(rbb_ssn_bv, bitvec_get_bit_pos(urbb, i)); + } + } + + /* check our rbb is equal the decompressed */ + rbb_should_bv.cur_bit = win->update_egprs_rbb(rbb_should); + + bool failed = false; + for (unsigned int i=0; i < rbb_ssn_bv->cur_bit; i++) { + if (bitvec_get_bit_pos(&rbb_should_bv, i) != + bitvec_get_bit_pos(rbb_ssn_bv, i)) + failed = true; + } + if (failed) { + fprintf(stderr, "SSN %d\n", ssn); + for (int i=win->v_q(); iws(); i++) { + fprintf(stderr, "bsn %d is %s\n", i, win->is_received( i) ? "received" : "MISS"); + } + char to_dump[256] = { 0 }; + bitvec_to_string_r(&rbb_should_bv, to_dump); + fprintf(stderr, "should: %s\n", to_dump); + memset(to_dump, 0x0, 256); + bitvec_to_string_r(rbb_ssn_bv, to_dump); + fprintf(stderr, "is : %s\n", to_dump); + OSMO_ASSERT(false); + } + + if (rbb_size) + *rbb_size = rbb_ssn_bv->cur_bit; +} + +static void free_egprs_ul_ack_nack(bitvec **rbb, struct crbb_test *crbb_test) +{ + if (*rbb) { + bitvec_free(*rbb); + *rbb = NULL; + } + + if (crbb_test->crbb) { + bitvec_free(crbb_test->crbb); + crbb_test->crbb = NULL; + } +} + +static void test_egprs_ul_ack_nack() +{ + bitvec *dest = bitvec_alloc(23, tall_pcu_ctx); + + fprintf(stderr, "############## test_egprs_ul_ack_nack\n"); + + BTS the_bts; + the_bts.bts_data()->egprs_enabled = true; + the_bts.bts_data()->alloc_algorithm = alloc_algorithm_a; + the_bts.bts_data()->trx[0].pdch[4].enable(); + + struct gprs_rlcmac_ul_tbf *tbf = tbf_alloc_ul_tbf(the_bts.bts_data(), NULL, 0, 1, 1, true); + struct crbb_test crbb_test = {0}; + bitvec *rbb = NULL; + unsigned int rbb_size; + uint16_t ssn = 0; + gprs_rlc_ul_window *win = tbf->window(); + + fprintf(stderr, "************** Test with empty window\n"); + win->reset_state(); + win->set_ws(256); + + Encoding::write_packet_uplink_ack(dest, tbf, false, 0); + extract_egprs_ul_ack_nack(tbf, dest, &ssn, &crbb_test, &rbb, false); + check_egprs_bitmap(tbf, ssn, &crbb_test, rbb, &rbb_size); + free_egprs_ul_ack_nack(&rbb, &crbb_test); + OSMO_ASSERT(rbb_size == 0); + + fprintf(stderr, "************** Test with 1 lost packet\n"); + win->reset_state(); + win->set_ws(256); + win->receive_bsn(1); + + Encoding::write_packet_uplink_ack(dest, tbf, false, 0); + extract_egprs_ul_ack_nack(tbf, dest, &ssn, &crbb_test, &rbb, false); + check_egprs_bitmap(tbf, ssn, &crbb_test, rbb, &rbb_size); + free_egprs_ul_ack_nack(&rbb, &crbb_test); + OSMO_ASSERT(rbb_size == 1); + + fprintf(stderr, "************** Test with compressed window\n"); + win->reset_state(); + win->set_ws(128); + win->receive_bsn(127); + + Encoding::write_packet_uplink_ack(dest, tbf, false, 0); + extract_egprs_ul_ack_nack(tbf, dest, &ssn, &crbb_test, &rbb, false); + check_egprs_bitmap(tbf, ssn, &crbb_test, rbb, &rbb_size); + free_egprs_ul_ack_nack(&rbb, &crbb_test); + + fprintf(stderr, "************** Provoke an uncompressed ACK without EOW\n"); + win->reset_state(); + win->set_ws(384); + for (uint16_t i=1; i<384/2; i++) + win->receive_bsn(i*2); + + Encoding::write_packet_uplink_ack(dest, tbf, false, 0); + extract_egprs_ul_ack_nack(tbf, dest, &ssn, &crbb_test, &rbb, false); + check_egprs_bitmap(tbf, ssn, &crbb_test, rbb, &rbb_size); + free_egprs_ul_ack_nack(&rbb, &crbb_test); +} + static void check_imm_ass(struct gprs_rlcmac_tbf *tbf, bool dl, enum ph_burst_type bt, const uint8_t *exp, uint8_t len, const char *kind) { @@ -619,6 +911,7 @@ int main(int argc, char **argv) log_set_print_filename(osmo_stderr_target, 0); printf("Making some basic type testing.\n"); + test_llc(); test_rlc(); test_rlc_v_b(); @@ -631,6 +924,7 @@ int main(int argc, char **argv) test_immediate_assign_ul1s(); test_immediate_assign_rej(); test_lsb(); + test_egprs_ul_ack_nack(); return EXIT_SUCCESS; } diff --git a/tests/types/TypesTest.err b/tests/types/TypesTest.err index 3abc61c0..92dbe061 100644 --- a/tests/types/TypesTest.err +++ b/tests/types/TypesTest.err @@ -7,3 +7,13 @@ TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=NULL) Allocated: trx = 0, ul_slots = 10, Allocating UL TBF: MS_CLASS=1/1 TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=NULL) Setting Control TS 1 TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=NULL) Allocated: trx = 0, ul_slots = 02, dl_slots = 00 +############## test_egprs_ul_ack_nack +Allocating UL TBF: MS_CLASS=1/1 +TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=NULL EGPRS) Enabled EGPRS, mode EGPRS +TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=NULL EGPRS) Setting Control TS 4 +TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=NULL EGPRS) Allocated: trx = 0, ul_slots = 10, dl_slots = 00 +TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=NULL EGPRS) setting EGPRS UL window size to 64, base(0) slots(1) ws_pdch(0) +************** Test with empty window +************** Test with 1 lost packet +************** Test with compressed window +************** Provoke an uncompressed ACK without EOW -- cgit v1.2.3