diff options
Diffstat (limited to 'tests/edge/EdgeTest.cpp')
-rw-r--r-- | tests/edge/EdgeTest.cpp | 2523 |
1 files changed, 1992 insertions, 531 deletions
diff --git a/tests/edge/EdgeTest.cpp b/tests/edge/EdgeTest.cpp index 96ea0c1..2abcd8f 100644 --- a/tests/edge/EdgeTest.cpp +++ b/tests/edge/EdgeTest.cpp @@ -23,12 +23,12 @@ #include "gprs_debug.h" #include "gprs_coding_scheme.h" #include "decoding.h" -#include "encoding.h" #include "rlc.h" -#include "llc.h" +#include "bts.h" extern "C" { #include "pcu_vty.h" +#include "pcuif_proto.h" #include <osmocom/core/application.h> #include <osmocom/core/msgb.h> @@ -38,7 +38,83 @@ extern "C" { } #include <errno.h> -#include <string.h> + +enum test_tbf_final_ack_mode { + TEST_MODE_STANDARD, + TEST_MODE_REVERSE_FREE +}; + + +/*structure to fill uplink data for mcs 8*/ +struct gprs_rlc_ul_header_egprs_1_test { + uint8_t r:1, + si:1, + cv:4, + tfi_a:2; + uint8_t tfi_b:3, + bsn1_a:5; + uint8_t bsn1_b:6, + bsn2_a:2; + uint8_t bsn2_b; + uint8_t cps:5, + rsb:1, + pi:1, + spare:1; + uint8_t spare2:6, + dummy:2; + uint8_t e1 :1, + ti1 : 1, + dummy1:6; + uint8_t e2 :1, + length1 : 7; + uint8_t data1[67]; + uint8_t e3: 1, + ti2:1, + dummy2:6; + uint8_t e4:1, + length2:7; + uint8_t data2[67]; +} __attribute__ ((packed)); + + +/*structure to fill uplink data for mcs9*/ + +struct gprs_rlc_ul_header_egprs_2_test { + uint8_t r:1, + si:1, + cv:4, + tfi_a:2; + uint8_t tfi_b:3, + bsn1_a:5; + uint8_t bsn1_b:6, + bsn2_a:2; + uint8_t bsn2_b; + uint8_t cps:5, + rsb:1, + pi:1, + spare:1; + uint8_t spare2:6, + dummy:2; + uint8_t e1 :1, + ti1 : 1, + dummy1:6; + uint8_t e2 :1, + length1 : 7; + uint8_t data1[73]; + uint8_t e3: 1, + ti2:1, + dummy2:6; + uint8_t e4:1, + length2:7; + uint8_t data2[73]; + +} __attribute__ ((packed)); + + + + + +static uint8_t llc_data[256]; void *tall_pcu_ctx; int16_t spoof_mnc = 0, spoof_mcc = 0; @@ -46,22 +122,21 @@ int16_t spoof_mnc = 0, spoof_mcc = 0; static void check_coding_scheme(GprsCodingScheme& cs, GprsCodingScheme::Mode mode) { volatile unsigned expected_size; - bool need_padding; GprsCodingScheme new_cs; OSMO_ASSERT(cs.isValid()); OSMO_ASSERT(cs.isCompatible(mode)); /* Check static getBySizeUL() */ - expected_size = cs.usedSizeUL(); - if (cs.spareBitsUL() > 0 && cs.isGprs()) - expected_size += 1; + expected_size = cs.maxBytesUL(); + OSMO_ASSERT(expected_size == cs.sizeUL()); + OSMO_ASSERT(cs == GprsCodingScheme::getBySizeUL(expected_size)); /* Check static sizeUL() */ - expected_size = cs.usedSizeDL(); - if (cs.spareBitsDL() > 0 && cs.isGprs()) + expected_size = cs.maxBytesDL(); + if (cs.spareBitsDL() > 0) expected_size += 1; OSMO_ASSERT(expected_size == cs.sizeDL()); @@ -69,35 +144,6 @@ static void check_coding_scheme(GprsCodingScheme& cs, GprsCodingScheme::Mode mod OSMO_ASSERT(cs.maxDataBlockBytes() * cs.numDataBlocks() < cs.maxBytesDL()); OSMO_ASSERT(cs.maxDataBlockBytes() * cs.numDataBlocks() < cs.maxBytesUL()); - /* Check inc/dec */ - new_cs = cs; - new_cs.inc(mode); - OSMO_ASSERT(new_cs.isCompatible(mode)); - if (new_cs != cs) { - new_cs.dec(mode); - OSMO_ASSERT(new_cs.isCompatible(mode)); - OSMO_ASSERT(new_cs == cs); - } - new_cs.dec(mode); - OSMO_ASSERT(new_cs.isCompatible(mode)); - if (new_cs != cs) { - new_cs.inc(mode); - OSMO_ASSERT(new_cs.isCompatible(mode)); - OSMO_ASSERT(new_cs == cs); - } - - new_cs = cs; - new_cs.decToSingleBlock(&need_padding); - OSMO_ASSERT(new_cs.isFamilyCompatible(cs)); - OSMO_ASSERT(cs.isFamilyCompatible(new_cs)); - OSMO_ASSERT(cs.isCompatible(new_cs)); - if (need_padding) { - OSMO_ASSERT(new_cs.maxDataBlockBytes() == - new_cs.optionalPaddingBits()/8 + cs.maxDataBlockBytes()); - } else { - OSMO_ASSERT(new_cs.maxDataBlockBytes() == cs.maxDataBlockBytes()); - } - } static void test_coding_scheme() @@ -130,10 +176,8 @@ static void test_coding_scheme() GprsCodingScheme cs; OSMO_ASSERT(!cs); - OSMO_ASSERT(GprsCodingScheme::Scheme(cs) == GprsCodingScheme::UNKNOWN); - OSMO_ASSERT(cs == GprsCodingScheme(GprsCodingScheme::UNKNOWN)); + OSMO_ASSERT(cs == GprsCodingScheme::UNKNOWN); OSMO_ASSERT(!cs.isCompatible(GprsCodingScheme::GPRS)); - OSMO_ASSERT(!cs.isCompatible(GprsCodingScheme::EGPRS_GMSK)); OSMO_ASSERT(!cs.isCompatible(GprsCodingScheme::EGPRS)); last_size_UL = 0; @@ -143,8 +187,7 @@ static void test_coding_scheme() GprsCodingScheme current_cs(gprs_schemes[i]); OSMO_ASSERT(current_cs.isGprs()); OSMO_ASSERT(!current_cs.isEgprs()); - OSMO_ASSERT(!current_cs.isEgprsGmsk()); - OSMO_ASSERT(GprsCodingScheme::Scheme(current_cs) == gprs_schemes[i]); + OSMO_ASSERT(current_cs == gprs_schemes[i]); OSMO_ASSERT(current_cs == GprsCodingScheme(gprs_schemes[i])); /* Check strong monotonicity */ @@ -158,8 +201,9 @@ static void test_coding_scheme() GprsCodingScheme::HEADER_GPRS_DATA); OSMO_ASSERT(current_cs.headerTypeControl() == GprsCodingScheme::HEADER_GPRS_CONTROL); - +#if 0 check_coding_scheme(current_cs, GprsCodingScheme::GPRS); +#endif } OSMO_ASSERT(i == 4); @@ -170,8 +214,7 @@ static void test_coding_scheme() GprsCodingScheme current_cs(egprs_schemes[i].s); OSMO_ASSERT(!current_cs.isGprs()); OSMO_ASSERT(current_cs.isEgprs()); - OSMO_ASSERT(!!current_cs.isEgprsGmsk() == !!egprs_schemes[i].is_gmsk); - OSMO_ASSERT(GprsCodingScheme::Scheme(current_cs) == egprs_schemes[i].s); + OSMO_ASSERT(current_cs == egprs_schemes[i].s); OSMO_ASSERT(current_cs == GprsCodingScheme(egprs_schemes[i].s)); /* Check strong monotonicity */ @@ -179,19 +222,61 @@ static void test_coding_scheme() OSMO_ASSERT(current_cs.maxBytesDL() > last_size_DL); last_size_UL = current_cs.maxBytesUL(); last_size_DL = current_cs.maxBytesDL(); - - if (egprs_schemes[i].is_gmsk) - check_coding_scheme(current_cs, GprsCodingScheme::EGPRS_GMSK); +#if 0 check_coding_scheme(current_cs, GprsCodingScheme::EGPRS); +#endif } OSMO_ASSERT(i == 9); printf("=== end %s ===\n", __func__); } + + +static void test_rlc_decoder() +{ + struct gprs_rlc_ul_data_block_info rdbi = {0}; + GprsCodingScheme cs; + uint8_t data[74]; + Decoding::RlcData chunks[16]; + volatile int num_chunks = 0; + uint32_t tlli, tlli2; + unsigned int offs; + BTS the_bts; + the_bts.bts_data()->egprs_enabled = true; + the_bts.bts_data()->alloc_algorithm = alloc_algorithm_b; + the_bts.bts_data()->trx[0].pdch[2].enable(); + the_bts.bts_data()->trx[0].pdch[3].enable();/* + * Make a uplink and downlink allocation + */ + gprs_rlcmac_tbf *dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(), + NULL, + 0, 0, 4, 0); + OSMO_ASSERT(dl_tbf != NULL); + + gprs_rlcmac_tbf *ul_tbf = tbf_alloc_ul_tbf(the_bts.bts_data(), + dl_tbf->ms(), + 0, 0, 4, 0); + /* + bts.cpp:1156 Got RLC block, coding scheme: CS-4, length : 54 (53)) +bts.cpp:1200 UL data: 3c 02 02 33 0a ed 5d fe d8 00 8f 18 33 2c 16 45 03 c0 68 75 00 00 16 45 00 03 c5 62 29 40 00 45 06 4e b6 c0 a8 00 02 c0 a8 00 01 86 74 1f 91 17 ac 35 ee 33 5e +bts.cpp:1217 Got CS-4 RLC block: R=0, SI=0, TFI=1, CPS=0, RSB=0, rc=424 +tbf_ul.cpp:323 UL DATA TFI=1 received (V(Q)=1 .. V(R)=1) +tbf.cpp:406 TBF(TFI=1 TLLI=0xdf1781e3 DIR=UL STATE=FLOW) restarting timer 3169 while old timer 3169 pending +tbf_ul.cpp:357 TBF(TFI=1 TLLI=0xdf1781e3 DIR=UL STATE=FLOW): Got CS-4 RLC data block: CV=15, BSN=1, SPB=0, PI=0, E=0, TI=0, bitoffs=24 +tbf_ul.cpp:390 - BSN 1 storing in window (1..64) +tbf_ul.cpp:415 TBF(TFI=1 TLLI=0xdf1781e3 DIR=UL STATE=FLOW): data_length=50, data=33 0a ed 5d fe d8 00 8f 18 33 2c 16 45 03 c0 68 75 00 00 16 45 00 03 c5 62 29 40 00 45 06 4e b6 c0 a8 00 02 c0 a8 00 01 86 74 1f 91 17 ac 35 ee 33 5e + */ + + + printf("=== start %s ===\n", __func__); + + printf("=== end %s ===\n", __func__); +} + static void test_rlc_unit_decoder() { - struct gprs_rlc_data_block_info rdbi = {0}; + struct gprs_rlc_ul_data_block_info rdbi = {0}; GprsCodingScheme cs; uint8_t data[74]; Decoding::RlcData chunks[16]; @@ -321,21 +406,23 @@ static void test_rlc_unit_decoder() rdbi.cv = 15; tlli = 0; offs = 0; - data[offs++] = (11 << 1) | (0 << 0); - data[offs++] = (26 << 1) | (1 << 0); + data[offs++] = 6; + data[offs++] = 10; + data[offs++] = 16; + data[offs++] = 255; num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data, chunks, ARRAY_SIZE(chunks), &tlli); OSMO_ASSERT(num_chunks == 3); OSMO_ASSERT(tlli == 0); - OSMO_ASSERT(chunks[0].offset == 2); - OSMO_ASSERT(chunks[0].length == 11); + OSMO_ASSERT(chunks[0].offset == 4); + OSMO_ASSERT(chunks[0].length == 3); OSMO_ASSERT(chunks[0].is_complete); - OSMO_ASSERT(chunks[1].offset == 13); - OSMO_ASSERT(chunks[1].length == 26); + OSMO_ASSERT(chunks[1].offset == 7); + OSMO_ASSERT(chunks[1].length == 5); OSMO_ASSERT(chunks[1].is_complete); - OSMO_ASSERT(chunks[2].offset == 39); - OSMO_ASSERT(chunks[2].length == 5); - OSMO_ASSERT(!chunks[2].is_complete); + OSMO_ASSERT(chunks[2].offset == 12); + OSMO_ASSERT(chunks[2].length == 8); + OSMO_ASSERT(chunks[2].is_complete); /* TS 44.060, B.8.2 */ @@ -495,614 +582,1966 @@ static void test_rlc_unit_decoder() OSMO_ASSERT(chunks[2].length == 1); OSMO_ASSERT(!chunks[2].is_complete); - printf("=== end %s ===\n", __func__); -} -static void test_rlc_unit_encoder() -{ - struct gprs_rlc_data_block_info rdbi = {0}; - GprsCodingScheme cs; - uint8_t data[74]; - uint8_t llc_data[1500] = {0,}; - int num_chunks = 0; - int write_offset; - struct gprs_llc llc; - Encoding::AppendResult ar; - - printf("=== start %s ===\n", __func__); - - llc.init(); + cs = GprsCodingScheme::MCS5; + rdbi.data_len = cs.maxDataBlockBytes(); + rdbi.e = 0; + rdbi.ti = 0; + rdbi.cv = 15; + tlli = 0; + offs = 0; + data[offs++] = (15 << 1) | (1 << 0); + num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data, + chunks, ARRAY_SIZE(chunks), &tlli); + OSMO_ASSERT(num_chunks == 2); + OSMO_ASSERT(tlli == 0); + OSMO_ASSERT(chunks[0].offset == 1); + OSMO_ASSERT(chunks[0].length == 15); + OSMO_ASSERT(chunks[0].is_complete); + OSMO_ASSERT(chunks[1].offset == 16); + OSMO_ASSERT(chunks[1].length == 40); + OSMO_ASSERT(!chunks[1].is_complete); + + rdbi.e = 0; + rdbi.ti = 0; + rdbi.cv = 15; + tlli = 1; + offs = 0; + data[offs++] = ( 0 << 1) | (0 << 0); + data[offs++] = ( 7 << 1) | (0 << 0); + data[offs++] = (18 << 1) | (1 << 0); /* Differs from spec's N2-11 = 17 */ + num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data, + chunks, ARRAY_SIZE(chunks), &tlli); + + OSMO_ASSERT(num_chunks == 4); + OSMO_ASSERT(tlli == 0); + OSMO_ASSERT(chunks[0].length == 0); + OSMO_ASSERT(chunks[0].is_complete); + OSMO_ASSERT(chunks[1].offset == 3); + OSMO_ASSERT(chunks[1].length == 7); + OSMO_ASSERT(chunks[1].is_complete); + OSMO_ASSERT(chunks[2].offset == 10); + OSMO_ASSERT(chunks[2].length == 18); + OSMO_ASSERT(chunks[2].is_complete); +//#endif + + rdbi.e = 0; + rdbi.ti = 0; + rdbi.cv = 0; + tlli = 0; + offs = 0; + data[offs++] = ( 6 << 1) | (0 << 0); + data[offs++] = (12 << 1) | (0 << 0); + data[offs++] = (127 << 1) | (1 << 0); + num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data, + chunks, ARRAY_SIZE(chunks), &tlli); + OSMO_ASSERT(num_chunks == 2); + OSMO_ASSERT(tlli == 0); + OSMO_ASSERT(chunks[0].offset == 3); + OSMO_ASSERT(chunks[0].length == 6); + OSMO_ASSERT(chunks[0].is_complete); + OSMO_ASSERT(chunks[1].offset == 9); + OSMO_ASSERT(chunks[1].length == 12); + OSMO_ASSERT(chunks[1].is_complete); + + cs = GprsCodingScheme::MCS5; + rdbi.data_len = cs.maxDataBlockBytes(); + rdbi.e = 1; + rdbi.ti = 0; + rdbi.cv = 0; + tlli = 0; + offs = 0; + num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data, + chunks, ARRAY_SIZE(chunks), &tlli); + OSMO_ASSERT(num_chunks == 1); + OSMO_ASSERT(tlli == 0); + OSMO_ASSERT(chunks[0].offset == 0); + OSMO_ASSERT(chunks[0].length == 56); + + OSMO_ASSERT(chunks[0].is_complete); + + cs = GprsCodingScheme::MCS6; + rdbi.data_len = cs.maxDataBlockBytes(); + rdbi.e = 0; + rdbi.ti = 0; + rdbi.cv = 15; + tlli = 0; + offs = 0; + data[offs++] = (15 << 1) | (1 << 0); + num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data, + chunks, ARRAY_SIZE(chunks), &tlli); + OSMO_ASSERT(num_chunks == 2); + OSMO_ASSERT(tlli == 0); + OSMO_ASSERT(chunks[0].offset == 1); + OSMO_ASSERT(chunks[0].length == 15); + OSMO_ASSERT(chunks[0].is_complete); + OSMO_ASSERT(chunks[1].offset == 16); + OSMO_ASSERT(chunks[1].length == 58); + OSMO_ASSERT(!chunks[1].is_complete); + + rdbi.e = 0; + rdbi.ti = 0; + rdbi.cv = 15; + tlli = 1; + offs = 0; + data[offs++] = ( 0 << 1) | (0 << 0); + data[offs++] = ( 7 << 1) | (0 << 0); + data[offs++] = (18 << 1) | (1 << 0); /* Differs from spec's N2-11 = 17 */ + num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data, + chunks, ARRAY_SIZE(chunks), &tlli); + + OSMO_ASSERT(num_chunks == 4); + OSMO_ASSERT(tlli == 0); + OSMO_ASSERT(chunks[0].length == 0); + OSMO_ASSERT(chunks[0].is_complete); + OSMO_ASSERT(chunks[1].offset == 3); + OSMO_ASSERT(chunks[1].length == 7); + OSMO_ASSERT(chunks[1].is_complete); + OSMO_ASSERT(chunks[2].offset == 10); + OSMO_ASSERT(chunks[2].length == 18); + OSMO_ASSERT(chunks[2].is_complete); + + + rdbi.e = 0; + rdbi.ti = 0; + rdbi.cv = 0; + tlli = 0; + offs = 0; + data[offs++] = ( 6 << 1) | (0 << 0); + data[offs++] = (12 << 1) | (0 << 0); + data[offs++] = (127 << 1) | (1 << 0); + num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data, + chunks, ARRAY_SIZE(chunks), &tlli); + OSMO_ASSERT(num_chunks == 2); + OSMO_ASSERT(tlli == 0); + OSMO_ASSERT(chunks[0].offset == 3); + OSMO_ASSERT(chunks[0].length == 6); + OSMO_ASSERT(chunks[0].is_complete); + OSMO_ASSERT(chunks[1].offset == 9); + OSMO_ASSERT(chunks[1].length == 12); + OSMO_ASSERT(chunks[1].is_complete); + + + cs = GprsCodingScheme::MCS6; + rdbi.data_len = cs.maxDataBlockBytes(); + rdbi.e = 1; + rdbi.ti = 0; + rdbi.cv = 0; + tlli = 0; + offs = 0; + num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data, + chunks, ARRAY_SIZE(chunks), &tlli); + OSMO_ASSERT(num_chunks == 1); + OSMO_ASSERT(tlli == 0); + OSMO_ASSERT(chunks[0].offset == 0); + OSMO_ASSERT(chunks[0].length == 74); + OSMO_ASSERT(chunks[0].is_complete); - /* TS 44.060, B.1 */ - cs = GprsCodingScheme::CS4; - gprs_rlc_data_block_info_init(&rdbi, cs, false); - num_chunks = 0; - write_offset = 0; - memset(data, 0, sizeof(data)); - llc.reset(); - llc.put_frame(llc_data, 11); - ar = Encoding::rlc_data_to_dl_append(&rdbi, cs, - &llc, &write_offset, &num_chunks, data, false); - OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT); - OSMO_ASSERT(rdbi.e == 0); - OSMO_ASSERT(write_offset == 1 + 11); - OSMO_ASSERT(num_chunks == 1); - llc.reset(); - llc.put_frame(llc_data, 26); + printf("=== end %s ===\n", __func__); +} - ar = Encoding::rlc_data_to_dl_append(&rdbi, cs, - &llc, &write_offset, &num_chunks, data, false); - OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT); - OSMO_ASSERT(rdbi.e == 0); - OSMO_ASSERT(write_offset == 2 + 11 + 26); - OSMO_ASSERT(num_chunks == 2); +static const struct log_info_cat default_categories[] = { + {"DCSN1", "\033[1;31m", "Concrete Syntax Notation One (CSN1)", LOGL_INFO, 0}, + {"DL1IF", "\033[1;32m", "GPRS PCU L1 interface (L1IF)", LOGL_DEBUG, 1}, + {"DRLCMAC", "\033[0;33m", "GPRS RLC/MAC layer (RLCMAC)", LOGL_DEBUG, 1}, + {"DRLCMACDATA", "\033[0;33m", "GPRS RLC/MAC layer Data (RLCMAC)", LOGL_DEBUG, 1}, + {"DRLCMACDL", "\033[1;33m", "GPRS RLC/MAC layer Downlink (RLCMAC)", LOGL_DEBUG, 1}, + {"DRLCMACUL", "\033[1;36m", "GPRS RLC/MAC layer Uplink (RLCMAC)", LOGL_DEBUG, 1}, + {"DRLCMACSCHED", "\033[0;36m", "GPRS RLC/MAC layer Scheduling (RLCMAC)", LOGL_DEBUG, 1}, + {"DRLCMACMEAS", "\033[1;31m", "GPRS RLC/MAC layer Measurements (RLCMAC)", LOGL_INFO, 1}, + {"DNS","\033[1;34m", "GPRS Network Service Protocol (NS)", LOGL_INFO , 1}, + {"DBSSGP","\033[1;34m", "GPRS BSS Gateway Protocol (BSSGP)", LOGL_INFO , 1}, + {"DPCU", "\033[1;35m", "GPRS Packet Control Unit (PCU)", LOGL_NOTICE, 1}, +}; - llc.reset(); - llc.put_frame(llc_data, 99); +static int filter_fn(const struct log_context *ctx, + struct log_target *tar) +{ + return 1; +} - ar = Encoding::rlc_data_to_dl_append(&rdbi, cs, - &llc, &write_offset, &num_chunks, data, false); +const struct log_info debug_log_info = { + filter_fn, + (struct log_info_cat*)default_categories, + ARRAY_SIZE(default_categories), +}; - OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS); - OSMO_ASSERT(rdbi.e == 0); - OSMO_ASSERT(rdbi.cv != 0); - OSMO_ASSERT(write_offset == (int)rdbi.data_len); - OSMO_ASSERT(num_chunks == 3); +static unsigned fn2bn(unsigned fn) +{ + return (fn % 52) / 4; +} - OSMO_ASSERT(data[0] == ((11 << 2) | (1 << 1) | (0 << 0))); - OSMO_ASSERT(data[1] == ((26 << 2) | (1 << 1) | (1 << 0))); - OSMO_ASSERT(data[2] == 0); +static unsigned fn_add_blocks(unsigned fn, unsigned blocks) +{ + unsigned bn = fn2bn(fn) + blocks; + fn = fn - (fn % 52); + fn += bn * 4 + bn / 3; + return fn % 2715648; +} +static void request_dl_rlc_block(struct gprs_rlcmac_bts *bts, + uint8_t trx_no, uint8_t ts_no, uint16_t arfcn, + uint32_t *fn, uint8_t *block_nr = NULL) +{ + uint8_t bn = fn2bn(*fn); + gprs_rlcmac_rcv_rts_block(bts, trx_no, ts_no, arfcn, *fn, bn); + *fn = fn_add_blocks(*fn, 1); + bn += 1; + if (block_nr) + *block_nr = bn; +} +static void send_ul_mac_block_PDAN(BTS *the_bts, unsigned trx_no, unsigned ts_no, + RlcMacUplink_t *ulreq, unsigned fn) +{ + bitvec *rlc_block; + uint8_t buf[64]; + int num_bytes; + struct gprs_rlcmac_pdch *pdch; + struct pcu_l1_meas meas; + + bitvec *dest; + + meas.set_rssi(31); + + dest = bitvec_alloc(23); + unsigned wp =0; + + bitvec_write_field(dest, wp, 0x1, 2); // Payload Type + bitvec_write_field(dest, wp, 0x0, 2); // Uplink block with TDMA framenumber (N+13) + bitvec_write_field(dest, wp, 0x0, 1); // Suppl/Polling Bit + bitvec_write_field(dest, wp, 0x0, 3); // Uplink state flag + bitvec_write_field(dest, wp, 0x8, 6); // MESSAGE TYPE Uplink Ack/Nack + bitvec_write_field(dest, wp, 0x0, 5); // Downlink TFI + + bitvec_write_field(dest, wp, 0, 1); //MS_OUT_OF_MEMORY + bitvec_write_field(dest, wp, 0, 1); //Exist_EGPRS_ChannelQualityReport + bitvec_write_field(dest, wp, 0, 1); //Exist_ChannelRequestDescription + bitvec_write_field(dest, wp, 0, 1); //Exist_PFI + bitvec_write_field(dest, wp, 0, 1); // Exist_ExtensionBits + bitvec_write_field(dest, wp, 1, 1); // 1: have length + bitvec_write_field(dest, wp, 39, 8); // length + bitvec_write_field(dest, wp, 0, 1); // FINAL_ACK_INDICATION + bitvec_write_field(dest, wp, 1, 1); // BEGINNING_OF_WINDOW + bitvec_write_field(dest, wp, 1, 1); // END_OF_WINDOW + bitvec_write_field(dest, wp, 0x1, 11); // STARTING_SEQUENCE_NUMBER + bitvec_write_field(dest, wp, 1, 1); // CRBB_Exist + bitvec_write_field(dest, wp, 10, 7); // CRBB_LENGTH + bitvec_write_field(dest, wp, 1, 1); + bitvec_write_field(dest, wp, 0x73, 8); + bitvec_write_field(dest, wp, 0x35, 8); + bitvec_write_field(dest, wp, 0, 8);//URBB_LENGTH + + num_bytes = bitvec_pack(dest, &buf[0]); + OSMO_ASSERT(size_t(num_bytes) < sizeof(buf)); + bitvec_free(dest); + the_bts->set_current_block_frame_number(fn, 0); + + pdch = &the_bts->bts_data()->trx[trx_no].pdch[ts_no]; + pdch->rcv_block(&buf[0], num_bytes, fn, &meas); +} +static void send_ul_mac_block(BTS *the_bts, unsigned trx_no, unsigned ts_no, + RlcMacUplink_t *ulreq, unsigned fn) +{ + bitvec *rlc_block; +// uint8_t rlc_block[128]; + uint8_t buf[64]; + int num_bytes; + struct gprs_rlcmac_pdch *pdch; + struct pcu_l1_meas meas; + + meas.set_rssi(31); + + rlc_block = bitvec_alloc(23); + encode_gsm_rlcmac_uplink(rlc_block, ulreq); + + num_bytes = bitvec_pack(rlc_block, &buf[0]); + OSMO_ASSERT(size_t(num_bytes) < sizeof(buf)); + bitvec_free(rlc_block); + + the_bts->set_current_block_frame_number(fn, 0); + + pdch = &the_bts->bts_data()->trx[trx_no].pdch[ts_no]; + pdch->rcv_block(&buf[0], num_bytes, fn, &meas); +} +static void send_egprs_control_ack(gprs_rlcmac_tbf *tbf) +{ + RlcMacUplink_t ulreq = {0}; + + OSMO_ASSERT(tbf->poll_fn != 0); + + ulreq.u.MESSAGE_TYPE = MT_EGPRS_PACKET_DOWNLINK_ACK_NACK ; + EGPRS_PD_AckNack_t *Egprs_ackNack = + &ulreq.u.Egprs_Packet_Downlink_Ack_Nack; + + Egprs_ackNack->PayloadType = GPRS_RLCMAC_CONTROL_BLOCK; + Egprs_ackNack->DOWNLINK_TFI = tbf->tfi(); + Egprs_ackNack->Exist_EGPRS_ChannelQualityReport = 0; + Egprs_ackNack->Exist_ChannelRequestDescription = 0; + Egprs_ackNack->Exist_PFI = 0; + Egprs_ackNack->Exist_ExtensionBits = 0; + //Egprs_ackNack->u.EGPRS_AckNack.UnionType = 0; + Egprs_ackNack->u.EGPRS_AckNack.Desc.FINAL_ACK_INDICATION = 0; + Egprs_ackNack->u.EGPRS_AckNack.Desc.STARTING_SEQUENCE_NUMBER = 10; + Egprs_ackNack->u.EGPRS_AckNack.Desc.BEGINNING_OF_WINDOW = 1 ; + Egprs_ackNack->u.EGPRS_AckNack.Desc.END_OF_WINDOW = 1 ; + Egprs_ackNack->u.EGPRS_AckNack.Desc.Exist_CRBB = 0 ; + Egprs_ackNack->u.EGPRS_AckNack.Desc.URBB_LENGTH = 0x1 ; + + send_ul_mac_block(tbf->bts, tbf->trx->trx_no, tbf->control_ts, + &ulreq, tbf->poll_fn); +} - /* TS 44.060, B.2 */ - cs = GprsCodingScheme::CS1; +static void send_egprs_pack_dl_acknack1(gprs_rlcmac_tbf *tbf) +{ + RlcMacUplink_t ulreq = {0}; - /* Block 1 */ - gprs_rlc_data_block_info_init(&rdbi, cs, false); - num_chunks = 0; - write_offset = 0; - memset(data, 0, sizeof(data)); + OSMO_ASSERT(tbf->poll_fn != 0); - llc.reset(); - llc.put_frame(llc_data, 20); + ulreq.u.MESSAGE_TYPE = MT_EGPRS_PACKET_DOWNLINK_ACK_NACK ; + EGPRS_PD_AckNack_t *Egprs_ackNack = + &ulreq.u.Egprs_Packet_Downlink_Ack_Nack; - ar = Encoding::rlc_data_to_dl_append(&rdbi, cs, - &llc, &write_offset, &num_chunks, data, false); + send_ul_mac_block_PDAN(tbf->bts, tbf->trx->trx_no, tbf->control_ts, + &ulreq, tbf->poll_fn); +} - OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS); - OSMO_ASSERT(rdbi.e == 0); - OSMO_ASSERT(write_offset == 1 + 19); - OSMO_ASSERT(num_chunks == 1); +static void send_egprs_pack_dl_acknack2(gprs_rlcmac_tbf *tbf) +{ + RlcMacUplink_t ulreq = {0}; + + OSMO_ASSERT(tbf->poll_fn != 0); + + ulreq.u.MESSAGE_TYPE = MT_EGPRS_PACKET_DOWNLINK_ACK_NACK ; + EGPRS_PD_AckNack_t *Egprs_ackNack = + &ulreq.u.Egprs_Packet_Downlink_Ack_Nack; + + Egprs_ackNack->PayloadType = GPRS_RLCMAC_CONTROL_BLOCK; + Egprs_ackNack->DOWNLINK_TFI = tbf->tfi(); + Egprs_ackNack->Exist_EGPRS_ChannelQualityReport = 1; + Egprs_ackNack->EGPRS_ChannelQualityReport.EGPRS_BEP_LinkQualityMeasurements.Exist_MEAN_CV_BEP_GMSK = 1; + Egprs_ackNack->EGPRS_ChannelQualityReport.EGPRS_BEP_LinkQualityMeasurements.MEAN_BEP_GMSK = 10; + Egprs_ackNack->EGPRS_ChannelQualityReport.EGPRS_BEP_LinkQualityMeasurements.CV_BEP_GMSK = 5; + Egprs_ackNack->EGPRS_ChannelQualityReport.EGPRS_BEP_LinkQualityMeasurements.Exist_MEAN_CV_BEP_8PSK = 0; + Egprs_ackNack->EGPRS_ChannelQualityReport.C_VALUE = 10; + Egprs_ackNack->EGPRS_ChannelQualityReport.EGPRS_TimeslotLinkQualityMeasurements.Exist_BEP_MEASUREMENTS = 0; + Egprs_ackNack->EGPRS_ChannelQualityReport.EGPRS_TimeslotLinkQualityMeasurements.Exist_INTERFERENCE_MEASUREMENTS = 0; + Egprs_ackNack->Exist_ChannelRequestDescription = 0; + Egprs_ackNack->Exist_PFI = 0; + Egprs_ackNack->Exist_ExtensionBits = 0; + Egprs_ackNack->UnionType = 0; + Egprs_ackNack->u.EGPRS_AckNack.Desc.FINAL_ACK_INDICATION = 0; + Egprs_ackNack->u.EGPRS_AckNack.Desc.STARTING_SEQUENCE_NUMBER = 1; + Egprs_ackNack->u.EGPRS_AckNack.Desc.BEGINNING_OF_WINDOW = 1 ; + Egprs_ackNack->u.EGPRS_AckNack.Desc.END_OF_WINDOW = 1 ; + Egprs_ackNack->u.EGPRS_AckNack.Desc.Exist_CRBB = 1 ; + Egprs_ackNack->u.EGPRS_AckNack.Desc.CRBB_LENGTH = 8; + Egprs_ackNack->u.EGPRS_AckNack.Desc.CRBB_STARTING_COLOR_CODE = 0; + Egprs_ackNack->u.EGPRS_AckNack.Desc.CRBB[0] = 0x2E; + Egprs_ackNack->u.EGPRS_AckNack.Desc.URBB_LENGTH = 10; + memset(Egprs_ackNack->u.EGPRS_AckNack.Desc.URBB,0,42); + + send_ul_mac_block(tbf->bts, tbf->trx->trx_no, tbf->control_ts, + &ulreq, tbf->poll_fn); +} - OSMO_ASSERT(data[0] == ((0 << 2) | (0 << 1) | (1 << 0))); - OSMO_ASSERT(data[1] == 0); +static void send_egprs_pack_dl_acknack3(gprs_rlcmac_tbf *tbf) +{ + RlcMacUplink_t ulreq = {0}; + + OSMO_ASSERT(tbf->poll_fn != 0); + + ulreq.u.MESSAGE_TYPE = MT_EGPRS_PACKET_DOWNLINK_ACK_NACK ; + EGPRS_PD_AckNack_t *Egprs_ackNack = + &ulreq.u.Egprs_Packet_Downlink_Ack_Nack; + + Egprs_ackNack->PayloadType = GPRS_RLCMAC_CONTROL_BLOCK; + Egprs_ackNack->DOWNLINK_TFI = tbf->tfi(); + Egprs_ackNack->Exist_EGPRS_ChannelQualityReport = 0; + Egprs_ackNack->Exist_ChannelRequestDescription = 0; + Egprs_ackNack->Exist_PFI = 0; + Egprs_ackNack->Exist_ExtensionBits = 0; + Egprs_ackNack->UnionType = 0; + Egprs_ackNack->u.EGPRS_AckNack.Desc.FINAL_ACK_INDICATION = 0; + Egprs_ackNack->u.EGPRS_AckNack.Desc.STARTING_SEQUENCE_NUMBER = 10; + Egprs_ackNack->u.EGPRS_AckNack.Desc.BEGINNING_OF_WINDOW = 1 ; + Egprs_ackNack->u.EGPRS_AckNack.Desc.END_OF_WINDOW = 1 ; + Egprs_ackNack->u.EGPRS_AckNack.Desc.Exist_CRBB = 1 ; + Egprs_ackNack->u.EGPRS_AckNack.Desc.CRBB_LENGTH = 10; + Egprs_ackNack->u.EGPRS_AckNack.Desc.CRBB_STARTING_COLOR_CODE = 1; + Egprs_ackNack->u.EGPRS_AckNack.Desc.CRBB[0] = 0xD9; + Egprs_ackNack->u.EGPRS_AckNack.Desc.CRBB[1] = 0xC0; + Egprs_ackNack->u.EGPRS_AckNack.Desc.URBB_LENGTH = 40; + memset(Egprs_ackNack->u.EGPRS_AckNack.Desc.URBB,0,42); + + send_ul_mac_block(tbf->bts, tbf->trx->trx_no, tbf->control_ts, + &ulreq, tbf->poll_fn); +} - /* Block 2 */ - gprs_rlc_data_block_info_init(&rdbi, cs, false); - num_chunks = 0; - write_offset = 0; - memset(data, 0, sizeof(data)); +static void send_egprs_pack_dl_acknack4(gprs_rlcmac_tbf *tbf) +{ + RlcMacUplink_t ulreq = {0}; + + OSMO_ASSERT(tbf->poll_fn != 0); + + ulreq.u.MESSAGE_TYPE = MT_EGPRS_PACKET_DOWNLINK_ACK_NACK ; + EGPRS_PD_AckNack_t *Egprs_ackNack = + &ulreq.u.Egprs_Packet_Downlink_Ack_Nack; + + Egprs_ackNack->PayloadType = GPRS_RLCMAC_CONTROL_BLOCK; + Egprs_ackNack->DOWNLINK_TFI = tbf->tfi(); + Egprs_ackNack->Exist_EGPRS_ChannelQualityReport = 0; + Egprs_ackNack->Exist_ChannelRequestDescription = 0; + Egprs_ackNack->Exist_PFI = 0; + Egprs_ackNack->Exist_ExtensionBits = 0; + Egprs_ackNack->UnionType = 0; + Egprs_ackNack->u.EGPRS_AckNack.Desc.FINAL_ACK_INDICATION = 0; + Egprs_ackNack->u.EGPRS_AckNack.Desc.STARTING_SEQUENCE_NUMBER = 20; + Egprs_ackNack->u.EGPRS_AckNack.Desc.BEGINNING_OF_WINDOW = 1 ; + Egprs_ackNack->u.EGPRS_AckNack.Desc.END_OF_WINDOW = 1 ; + Egprs_ackNack->u.EGPRS_AckNack.Desc.Exist_CRBB = 1 ; + Egprs_ackNack->u.EGPRS_AckNack.Desc.CRBB_LENGTH = 16; + Egprs_ackNack->u.EGPRS_AckNack.Desc.CRBB_STARTING_COLOR_CODE = 0; + Egprs_ackNack->u.EGPRS_AckNack.Desc.CRBB[0] = 0x03; + Egprs_ackNack->u.EGPRS_AckNack.Desc.CRBB[1] = 0xC4; + Egprs_ackNack->u.EGPRS_AckNack.Desc.URBB_LENGTH = 40; + memset(Egprs_ackNack->u.EGPRS_AckNack.Desc.URBB,0,42); + + send_ul_mac_block(tbf->bts, tbf->trx->trx_no, tbf->control_ts, + &ulreq, tbf->poll_fn); +} - OSMO_ASSERT(llc.chunk_size() == 1); - ar = Encoding::rlc_data_to_dl_append(&rdbi, cs, - &llc, &write_offset, &num_chunks, data, false); - OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT); - OSMO_ASSERT(rdbi.e == 0); - OSMO_ASSERT(write_offset == 1 + 1); - OSMO_ASSERT(num_chunks == 1); +static void send_control_ack(gprs_rlcmac_tbf *tbf) +{ + RlcMacUplink_t ulreq = {0}; - llc.reset(); - llc.put_frame(llc_data, 99); + OSMO_ASSERT(tbf->poll_fn != 0); - ar = Encoding::rlc_data_to_dl_append(&rdbi, cs, - &llc, &write_offset, &num_chunks, data, false); + ulreq.u.MESSAGE_TYPE = MT_PACKET_CONTROL_ACK; + Packet_Control_Acknowledgement_t *ctrl_ack = + &ulreq.u.Packet_Control_Acknowledgement; - OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS); - OSMO_ASSERT(rdbi.e == 0); - OSMO_ASSERT(write_offset == 1 + 1 + 18); - OSMO_ASSERT(num_chunks == 2); + ctrl_ack->PayloadType = GPRS_RLCMAC_CONTROL_BLOCK; + ctrl_ack->TLLI = tbf->tlli(); + send_ul_mac_block(tbf->bts, tbf->trx->trx_no, tbf->control_ts, + &ulreq, tbf->poll_fn); +} +static void check_tbf(gprs_rlcmac_tbf *tbf) +{ + OSMO_ASSERT(tbf); + if (tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE)) + OSMO_ASSERT(tbf->T == 3191 || tbf->T == 3193); + if (tbf->state_is(GPRS_RLCMAC_RELEASING)) + OSMO_ASSERT(tbf->T != 0); +} - OSMO_ASSERT(data[0] == ((1 << 2) | (1 << 1) | (1 << 0))); - OSMO_ASSERT(data[1] == 0); +static void request_dl_rlc_block(struct gprs_rlcmac_tbf *tbf, + uint32_t *fn, uint8_t *block_nr = NULL) +{ + request_dl_rlc_block(tbf->bts->bts_data(), tbf->trx->trx_no, + tbf->control_ts, tbf->trx->arfcn, fn, block_nr); +} - /* TS 44.060, B.3 */ - cs = GprsCodingScheme::CS1; +void send_dl_data(BTS *the_bts, uint32_t tlli, const char *imsi, + const uint8_t *data, unsigned data_size) +{ + GprsMs *ms, *ms2; - /* Block 1 */ - gprs_rlc_data_block_info_init(&rdbi, cs, false); - num_chunks = 0; - write_offset = 0; - memset(data, 0, sizeof(data)); + ms = the_bts->ms_store().get_ms(tlli, 0, imsi); - llc.reset(); - llc.put_frame(llc_data, 7); + gprs_rlcmac_dl_tbf::handle(the_bts->bts_data(), tlli, 0, imsi, 0, 0, + 1000, data, data_size); - ar = Encoding::rlc_data_to_dl_append(&rdbi, cs, - &llc, &write_offset, &num_chunks, data, false); + ms = the_bts->ms_by_imsi(imsi); + OSMO_ASSERT(ms != NULL); + OSMO_ASSERT(ms->dl_tbf() != NULL); - OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT); - OSMO_ASSERT(rdbi.e == 0); - OSMO_ASSERT(write_offset == 1 + 7); - OSMO_ASSERT(num_chunks == 1); + if (imsi[0] && strcmp(imsi, "000") != 0) { + ms2 = the_bts->ms_by_tlli(tlli); + OSMO_ASSERT(ms == ms2); + } +} +static gprs_rlcmac_dl_tbf *create_dl_tbf(BTS *the_bts, uint8_t ms_class, + uint8_t *trx_no_) +{ + gprs_rlcmac_bts *bts; + int tfi; + uint8_t trx_no; - llc.reset(); - llc.put_frame(llc_data, 11); + gprs_rlcmac_dl_tbf *dl_tbf; - ar = Encoding::rlc_data_to_dl_append(&rdbi, cs, - &llc, &write_offset, &num_chunks, data, false); + bts = the_bts->bts_data(); - OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED); - OSMO_ASSERT(rdbi.e == 0); - OSMO_ASSERT(write_offset == 2 + 7 + 11); - OSMO_ASSERT(num_chunks == 2); + tfi = the_bts->tfi_find_free(GPRS_RLCMAC_DL_TBF, &trx_no, -1); + OSMO_ASSERT(tfi >= 0); + dl_tbf = tbf_alloc_dl_tbf(bts, NULL, trx_no, ms_class, ms_class, 1); + check_tbf(dl_tbf); - OSMO_ASSERT(data[0] == ((7 << 2) | (1 << 1) | (0 << 0))); - OSMO_ASSERT(data[1] == ((11 << 2) | (0 << 1) | (1 << 0))); - OSMO_ASSERT(data[2] == 0); + /* "Establish" the DL TBF */ + dl_tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_SEND_ASS; + dl_tbf->set_state(GPRS_RLCMAC_FLOW); + dl_tbf->m_wait_confirm = 0; + check_tbf(dl_tbf); - /* TS 44.060, B.4 */ - cs = GprsCodingScheme::CS1; + *trx_no_ = trx_no; - /* Block 1 */ - gprs_rlc_data_block_info_init(&rdbi, cs, false); - num_chunks = 0; - write_offset = 0; - memset(data, 0, sizeof(data)); + return dl_tbf; +} - llc.reset(); - llc.put_frame(llc_data, 99); +static void setup_bts(BTS *the_bts, uint8_t ts_no, uint8_t cs = 1) +{ + gprs_rlcmac_bts *bts; + gprs_rlcmac_trx *trx; - ar = Encoding::rlc_data_to_dl_append(&rdbi, cs, - &llc, &write_offset, &num_chunks, data, false); + bts = the_bts->bts_data(); + bts->egprs_enabled = true; + bts->alloc_algorithm = alloc_algorithm_a; + bts->initial_cs_dl = cs; + bts->initial_cs_ul = cs; + trx = &bts->trx[0]; - OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS); - OSMO_ASSERT(rdbi.e == 1); - OSMO_ASSERT(write_offset == 20); - OSMO_ASSERT(num_chunks == 1); - OSMO_ASSERT(rdbi.cv != 0); + trx->pdch[ts_no].enable(); +} +static void test_tbf_final_ack(enum test_tbf_final_ack_mode test_mode) +{ + BTS the_bts; + uint8_t ts_no = 4; + unsigned i; + uint8_t ms_class = 4; + uint32_t fn; + uint8_t block_nr; + uint8_t trx_no; + GprsMs *ms; + uint32_t tlli = 0xffeeddcc; + + uint8_t rbb[64/8]; + + gprs_rlcmac_dl_tbf *dl_tbf; + gprs_rlcmac_tbf *new_tbf; + + setup_bts(&the_bts, ts_no , 12); + dl_tbf = create_dl_tbf(&the_bts, ms_class, &trx_no); + dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF); + ms = dl_tbf->ms(); + + for (i = 0; i < sizeof(llc_data); i++) + llc_data[i] = i%256; + + /* Schedule two LLC frames */ + dl_tbf->append_data(ms_class, 2000, llc_data, 25); + dl_tbf->append_data(ms_class, 2000, llc_data, 200); + + /* Send only a few RLC/MAC blocks */ + fn = 0; + int index = 0; + do { + static int xxx = 0; + /* Request to send one block */ + request_dl_rlc_block(dl_tbf, &fn, &block_nr); + index ++; + } while (index < 25); + + //send_egprs_control_ack(dl_tbf); +} +static void test_tbf_final_ack_EPDAN(enum test_tbf_final_ack_mode test_mode) +{ + BTS the_bts; + uint8_t ts_no = 4; + unsigned i; + uint8_t ms_class = 4; + uint32_t fn; + uint8_t block_nr; + uint8_t trx_no; + GprsMs *ms; + uint32_t tlli = 0xffeeddcc; + + // uint8_t rbb[64/8]; - OSMO_ASSERT(data[0] == 0); + printf("=== start %s ===\n", __func__); + gprs_rlcmac_dl_tbf *dl_tbf; + gprs_rlcmac_tbf *new_tbf; + + setup_bts(&the_bts, ts_no , 12); + dl_tbf = create_dl_tbf(&the_bts, ms_class, &trx_no); + dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF); + ms = dl_tbf->ms(); + + for (i = 0; i < sizeof(llc_data); i++) + llc_data[i] = i%256; + + /* Schedule two LLC frames */ + dl_tbf->append_data(ms_class, 2000, llc_data, 150); + dl_tbf->append_data(ms_class, 2000, llc_data, 100); + dl_tbf->append_data(ms_class, 2000, llc_data, 100); + dl_tbf->append_data(ms_class, 2000, llc_data, 100); + dl_tbf->append_data(ms_class, 2000, llc_data, 100); + dl_tbf->append_data(ms_class, 2000, llc_data, 100); + /* Send only a few RLC/MAC blocks */ + fn = 0; + int index = 0; + do { + /* Request to send one block */ + request_dl_rlc_block(dl_tbf, &fn, &block_nr); + index ++; + } while (index < 50); + + send_egprs_pack_dl_acknack1(dl_tbf); + + index = 0; + do { + /* Request to send one block */ + request_dl_rlc_block(dl_tbf, &fn, &block_nr); + index ++; + } while (index < 25); + send_egprs_pack_dl_acknack2(dl_tbf); + index = 0; + do { + /* Request to send one block */ + request_dl_rlc_block(dl_tbf, &fn, &block_nr); + index ++; + } while (index < 25); + send_egprs_pack_dl_acknack3(dl_tbf); + + index = 0; + do { + /* Request to send one block */ + request_dl_rlc_block(dl_tbf, &fn, &block_nr); + index ++; + } while (index < 25); + send_egprs_pack_dl_acknack4(dl_tbf); + printf("=== end %s ===\n", __func__); +} - /* TS 44.060, B.5 */ - cs = GprsCodingScheme::CS1; +static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase(BTS *the_bts, + uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta, + uint8_t ms_class) +{ + GprsMs *ms; + uint32_t rach_fn = *fn - 51; + uint32_t sba_fn = *fn + 52; + uint8_t trx_no = 0; + int tfi = 0; + gprs_rlcmac_ul_tbf *ul_tbf; + struct gprs_rlcmac_pdch *pdch; + gprs_rlcmac_bts *bts; + RlcMacUplink_t ulreq = {0}; + struct pcu_l1_meas meas; + meas.set_rssi(31); + + bts = the_bts->bts_data(); + + /* needed to set last_rts_fn in the PDCH object */ + request_dl_rlc_block(bts, trx_no, ts_no, 0, fn); + + /* simulate RACH, this sends an Immediate Assignment Uplink on the AGCH */ + the_bts->rcv_rach(0x73, rach_fn, qta); + + /* get next free TFI */ + tfi = the_bts->tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1); + + /* fake a resource request */ + ulreq.u.MESSAGE_TYPE = MT_PACKET_RESOURCE_REQUEST; + ulreq.u.Packet_Resource_Request.PayloadType = GPRS_RLCMAC_CONTROL_BLOCK; + ulreq.u.Packet_Resource_Request.ID.UnionType = 1; /* != 0 */ + ulreq.u.Packet_Resource_Request.ID.u.TLLI = tlli; + ulreq.u.Packet_Resource_Request.Exist_MS_Radio_Access_capability = 1; + ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability. + Count_MS_RA_capability_value = 1; + ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability. + MS_RA_capability_value[0].u.Content.Exist_Multislot_capability = 1; + ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability. + MS_RA_capability_value[0].u.Content.Multislot_capability. + Exist_GPRS_multislot_class = 1; + ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability. + MS_RA_capability_value[0].u.Content.Multislot_capability. + GPRS_multislot_class = ms_class; + + ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability. + MS_RA_capability_value[0].u.Content.Multislot_capability. + Exist_EGPRS_multislot_class = 1; + + ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability. + MS_RA_capability_value[0].u.Content.Multislot_capability. + EGPRS_multislot_class = ms_class; + + send_ul_mac_block(the_bts, trx_no, ts_no, &ulreq, sba_fn); + + /* check the TBF */ + ul_tbf = the_bts->ul_tbf_by_tfi(tfi, trx_no, ts_no); + OSMO_ASSERT(ul_tbf != NULL); + OSMO_ASSERT(ul_tbf->ta() == qta / 4); + + /* send packet uplink assignment */ + *fn = sba_fn; + request_dl_rlc_block(ul_tbf, fn); + + /* send real acknowledgement */ + send_control_ack(ul_tbf); + + check_tbf(ul_tbf); + + uint8_t data_msg[27] = {0}; + /* send fake data */ + data_msg[0] = 0x00 | 0xf << 2; + data_msg[1] = uint8_t(0 | (tfi << 1)); + data_msg[2] = uint8_t(0);/* BSN:7, E:1 */ + data_msg[3] =uint8_t(0); /* BSN:7, E:1 */ + data_msg[4] = uint8_t(1); /* E: 1 */ + + pdch = &the_bts->bts_data()->trx[trx_no].pdch[ts_no]; + pdch->rcv_block(&data_msg[0], sizeof(data_msg), *fn, &meas); + + ms = the_bts->ms_by_tlli(tlli); + OSMO_ASSERT(ms != NULL); + OSMO_ASSERT(ms->ta() == qta/4); + OSMO_ASSERT(ms->ul_tbf() == ul_tbf); + + return ul_tbf; +} - /* Block 1 */ - gprs_rlc_data_block_info_init(&rdbi, cs, false); - num_chunks = 0; - write_offset = 0; - memset(data, 0, sizeof(data)); +static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase_cv0(BTS *the_bts, + uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta, + uint8_t ms_class) +{ + GprsMs *ms; + uint32_t rach_fn = *fn - 51; + uint32_t sba_fn = *fn + 52; + uint8_t trx_no = 0; + int tfi = 0; + gprs_rlcmac_ul_tbf *ul_tbf; + struct gprs_rlcmac_pdch *pdch; + gprs_rlcmac_bts *bts; + RlcMacUplink_t ulreq = {0}; + struct pcu_l1_meas meas; + meas.set_rssi(31); + + bts = the_bts->bts_data(); + + /* needed to set last_rts_fn in the PDCH object */ + request_dl_rlc_block(bts, trx_no, ts_no, 0, fn); + + /* simulate RACH, this sends an Immediate Assignment Uplink on the AGCH */ + the_bts->rcv_rach(0x73, rach_fn, qta); + + /* get next free TFI */ + tfi = the_bts->tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1); + + /* fake a resource request */ + ulreq.u.MESSAGE_TYPE = MT_PACKET_RESOURCE_REQUEST; + ulreq.u.Packet_Resource_Request.PayloadType = GPRS_RLCMAC_CONTROL_BLOCK; + ulreq.u.Packet_Resource_Request.ID.UnionType = 1; /* != 0 */ + ulreq.u.Packet_Resource_Request.ID.u.TLLI = tlli; + ulreq.u.Packet_Resource_Request.Exist_MS_Radio_Access_capability = 1; + ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability. + Count_MS_RA_capability_value = 1; + ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability. + MS_RA_capability_value[0].u.Content.Exist_Multislot_capability = 1; + ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability. + MS_RA_capability_value[0].u.Content.Multislot_capability. + Exist_GPRS_multislot_class = 1; + ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability. + MS_RA_capability_value[0].u.Content.Multislot_capability. + GPRS_multislot_class = ms_class; + + ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability. + MS_RA_capability_value[0].u.Content.Multislot_capability. + Exist_EGPRS_multislot_class = 1; + + ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability. + MS_RA_capability_value[0].u.Content.Multislot_capability. + EGPRS_multislot_class = ms_class; + + send_ul_mac_block(the_bts, trx_no, ts_no, &ulreq, sba_fn); + + /* check the TBF */ + ul_tbf = the_bts->ul_tbf_by_tfi(tfi, trx_no, ts_no); + OSMO_ASSERT(ul_tbf != NULL); + OSMO_ASSERT(ul_tbf->ta() == qta / 4); + + /* send packet uplink assignment */ + *fn = sba_fn; + request_dl_rlc_block(ul_tbf, fn); + + /* send real acknowledgement */ + send_control_ack(ul_tbf); + + check_tbf(ul_tbf); + + /* send fake data with cv=0*/ + + struct gprs_rlc_ul_header_egprs_1 *hdr1 = NULL; + uint8_t data[42] = {0}; + + hdr1 = (struct gprs_rlc_ul_header_egprs_1 *)data; + + /*header_construction */ + memset(data, 0x2b, sizeof(data)); + + for (int i =0 ; i< 100; i++) { + hdr1 -> r = 0; + hdr1 -> si = 0; + hdr1 -> cv = 10; + hdr1 -> tfi_a = (tfi >> 3) & 0x3; + hdr1 -> tfi_b = tfi & 0x7; + hdr1 -> bsn1_a = ((i+1)&0x1f)*2; + hdr1 -> bsn1_b = (i+1)/32; + hdr1 -> rsb = 0; + hdr1 -> pi = 0; + hdr1 -> spare = 1; + hdr1 -> dummy = 1; + data[4] = 0x0; + data[5] = 0x2b; + data[6] = 0x2b; + data[7] = 0x2b; + + pdch = &the_bts->bts_data()->trx[trx_no].pdch[ts_no]; + pdch->rcv_block(&data[0], sizeof(data), *fn, &meas); + //request_dl_rlc_block(ul_tbf, fn); + } + memset(data, 0x2b, sizeof(data)); + hdr1 = (struct gprs_rlc_ul_header_egprs_1 *)data; + hdr1 -> r = 0; + hdr1 -> si = 0; + hdr1 -> cv = 15; + hdr1 -> tfi_a = (tfi >> 3) & 0x3; + hdr1 -> tfi_b = tfi & 0x7; + hdr1 -> bsn1_a = 0; + hdr1 -> bsn1_b = 2; + hdr1 -> rsb = 0; + hdr1 -> pi = 0; + hdr1 -> spare = 1; + hdr1 -> dummy = 1; + data[4] = 0x0; + data[5] = 0x2b; + data[6] = 0x2b; + data[7] = 0x2b; + + pdch = &the_bts->bts_data()->trx[trx_no].pdch[ts_no]; + pdch->rcv_block(&data[0], sizeof(data), *fn, &meas); + + request_dl_rlc_block(ul_tbf, fn); + + ms = the_bts->ms_by_tlli(tlli); + OSMO_ASSERT(ms != NULL); + OSMO_ASSERT(ms->ta() == qta/4); + OSMO_ASSERT(ms->ul_tbf() == ul_tbf); + + return ul_tbf; +} - llc.reset(); - llc.put_frame(llc_data, 20); - ar = Encoding::rlc_data_to_dl_append(&rdbi, cs, - &llc, &write_offset, &num_chunks, data, true); +void test_tbf_two_phase() +{ + BTS the_bts; + int ts_no = 7; + uint32_t fn = 2654218; + uint16_t qta = 31; + uint32_t tlli = 0xf1223344; + const char *imsi = "0011223344"; + uint8_t ms_class = 1; + gprs_rlcmac_ul_tbf *ul_tbf; + GprsMs *ms; - OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED); - OSMO_ASSERT(rdbi.e == 1); - OSMO_ASSERT(write_offset == 20); - OSMO_ASSERT(num_chunks == 1); - OSMO_ASSERT(rdbi.cv == 0); + printf("=== start %s ===\n", __func__); - OSMO_ASSERT(data[0] == 0); + setup_bts(&the_bts, ts_no, 9); - /* TS 44.060, B.7 */ - cs = GprsCodingScheme::CS1; + ul_tbf = establish_ul_tbf_two_phase(&the_bts, ts_no, tlli, &fn, qta, ms_class); - /* Block 1 */ - gprs_rlc_data_block_info_init(&rdbi, cs, false); - num_chunks = 0; - write_offset = 0; - memset(data, 0, sizeof(data)); + ms = ul_tbf->ms(); + fprintf(stderr, "Got '%s', TA=%d\n", ul_tbf->name(), ul_tbf->ta()); + fprintf(stderr, "Got MS: TLLI = 0x%08x, TA = %d\n", ms->tlli(), ms->ta()); - llc.reset(); - llc.put_frame(llc_data, 30); + send_dl_data(&the_bts, tlli, imsi, (const uint8_t *)"TEST", 4); + send_dl_data(&the_bts, tlli, imsi, (const uint8_t *)"TEST", 4); - ar = Encoding::rlc_data_to_dl_append(&rdbi, cs, - &llc, &write_offset, &num_chunks, data, false); + /* Send Packet Downlink Assignment to MS */ + request_dl_rlc_block(ul_tbf, &fn); + printf("=== end %s ===\n", __func__); +} - OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS); - OSMO_ASSERT(rdbi.e == 1); - OSMO_ASSERT(write_offset == 20); - OSMO_ASSERT(num_chunks == 1); +void test_tbf_two_phase_PUAN() +{ + BTS the_bts; + int ts_no = 7; + uint32_t fn = 2654218; + uint16_t qta = 31; + uint32_t tlli = 0xf1223344; + const char *imsi = "0011223344"; + uint8_t ms_class = 1; + gprs_rlcmac_ul_tbf *ul_tbf; + GprsMs *ms; - OSMO_ASSERT(data[0] == 0); + printf("=== start %s ===\n", __func__); - /* Block 2 */ - gprs_rlc_data_block_info_init(&rdbi, cs, false); - num_chunks = 0; - write_offset = 0; - memset(data, 0, sizeof(data)); + setup_bts(&the_bts, ts_no, 7); - OSMO_ASSERT(llc.chunk_size() == 10); + ul_tbf = establish_ul_tbf_two_phase_cv0(&the_bts, ts_no, tlli, &fn, qta, ms_class); - ar = Encoding::rlc_data_to_dl_append(&rdbi, cs, - &llc, &write_offset, &num_chunks, data, false); + ms = ul_tbf->ms(); + fprintf(stderr, "Got '%s', TA=%d\n", ul_tbf->name(), ul_tbf->ta()); + fprintf(stderr, "Got MS: TLLI = 0x%08x, TA = %d\n", ms->tlli(), ms->ta()); - OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT); - OSMO_ASSERT(rdbi.e == 0); - OSMO_ASSERT(write_offset == 1 + 10); - OSMO_ASSERT(num_chunks == 1); + send_dl_data(&the_bts, tlli, imsi, (const uint8_t *)"TEST", 4); + send_dl_data(&the_bts, tlli, imsi, (const uint8_t *)"TEST", 4); - llc.reset(); - llc.put_frame(llc_data, 99); + /* Send Packet Downlink Assignment to MS */ +// request_dl_rlc_block(ul_tbf, &fn); + printf("=== end %s ===\n", __func__); +} - ar = Encoding::rlc_data_to_dl_append(&rdbi, cs, - &llc, &write_offset, &num_chunks, data, false); +int pcu_sock_send(struct msgb *msg) +{ + struct gsm_pcu_if *pcu_prim; + struct gsm_pcu_if_data *data_req; + + + pcu_prim = (struct gsm_pcu_if *) msg->data; + data_req = &pcu_prim->u.data_req; + + uint32_t bsn_val = 0, bsn_val1 = 0; + struct gprs_rlc_dl_header_egprs_3 *header3 = NULL; + struct gprs_rlc_dl_header_egprs_2 *header2 = NULL; + struct gprs_rlc_dl_header_egprs_1 *header1 = NULL; + + if( data_req->len != 23 ) { + + if(data_req -> len == 61 || data_req -> len == 79 ) { + + header2 = (struct gprs_rlc_dl_header_egprs_2 *) data_req ->data ; + bsn_val = ((header2 ->bsn_a)); + bsn_val = (bsn_val | ((header2 -> bsn_b) << 2)); + bsn_val = (bsn_val | ((header2-> bsn_c ) << 10)); + + LOGP(DRLCMACDL, LOGL_DEBUG,"------------------header type 2 decode-------------- \n"); + LOGP(DRLCMACDL, LOGL_DEBUG, "length %d \n ",data_req -> len ); + LOGP(DRLCMACDL, LOGL_DEBUG, "usf :%d \n es :%d\n rrbp: %d \n tfi1:%d\n tfi2:%d\n bsn1:%d \n bsn2:%d \n bsn3:%d\n", + header2 ->usf, header2 -> es_p, header2 -> rrbp, header2 -> tfi_a, header2 ->tfi_b, header2->bsn_a, + header2->bsn_b, header2->bsn_c); + LOGP(DRLCMACDL, LOGL_DEBUG," pr: %d cps:%d ", header2 -> pr, header2 ->cps); + LOGP(DRLCMACDL, LOGL_DEBUG,"bsn_val: %d \n", bsn_val); + + } else if (data_req -> len == 119 || data_req -> len == 143 || data_req -> len == 155 ) { + + header1 = (struct gprs_rlc_dl_header_egprs_1 *) data_req -> data ; + bsn_val = (header1 -> bsn1_a); + bsn_val = (bsn_val | ((header1 -> bsn1_b)<< 2)); + bsn_val = (bsn_val | ((header1 -> bsn1_c) << 10)); + bsn_val1 = (bsn_val1 | (header1 -> bsn2_a)); + bsn_val1 = (bsn_val1 | ((header1 -> bsn2_b) << 7)); + + LOGP(DRLCMACDL, LOGL_DEBUG,"------------------header type 1 decode-------------- \n"); + LOGP(DRLCMACDL, LOGL_DEBUG,"length %d \n ",data_req -> len ); + LOGP(DRLCMACDL, LOGL_DEBUG,"usf :%d \n es :%d\n rrbp: %d \n tfi1:%d\n tfi2:%d\n bsn1a:%d \n bsn1b:%d \n bsn1c:%d\n" + "bsn2a:%d\n bsn2b:%d\n ", + header1 ->usf, header1 -> es_p, header1 -> rrbp, header1 -> tfi_a, header1 ->tfi_b, header1->bsn1_a, + header1->bsn1_b, header1->bsn1_c, header1->bsn2_a, header1->bsn2_b); + LOGP(DRLCMACDL, LOGL_DEBUG," pr: %d cps:%d ", header1 -> pr, header1 ->cps); + LOGP(DRLCMACDL, LOGL_DEBUG,"bsn_1: %d \n bsn_2:%d \n", bsn_val, bsn_val1); + + + } else if(data_req -> len == 27 || data_req -> len == 33 || data_req -> len == 42 || data_req ->len == 49 ) { + + header3 = (struct gprs_rlc_dl_header_egprs_3 *) data_req -> data; + bsn_val = ((header3 ->bsn_a)); + bsn_val = (bsn_val | ((header3 -> bsn_b) << 2)); + bsn_val = (bsn_val | ((header3->bsn_c ) << 10)); + + + LOGP(DRLCMACDL, LOGL_DEBUG,"------------------header type 3 decode-------------- \n"); + LOGP(DRLCMACDL, LOGL_DEBUG,"length %d \n ",data_req -> len ); + LOGP(DRLCMACDL, LOGL_DEBUG,"usf :%d \n es :%d\n rrbp: %d \n tfi1:%d\n tfi2:%d\n bsn1:%d \n bsn2:%d \n" + "bsn3:%d\n spb:%d \n",header3 ->usf, header3 -> es_p, header3 -> rrbp, header3 -> tfi_a, header3 ->tfi_b, + header3->bsn_a,header3->bsn_b, header3->bsn_c, header3 ->spb); + LOGP(DRLCMACDL, LOGL_DEBUG," pr: %d cps:%d ", header3 -> pr, header3 ->cps); + LOGP(DRLCMACDL, LOGL_DEBUG,"bsn_val: %d \n", bsn_val); + } else { + + LOGP(DRLCMACDL, LOGL_DEBUG,"block with size received %d \n ", data_req -> len); + + } - OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS); - OSMO_ASSERT(rdbi.e == 0); - OSMO_ASSERT(write_offset == 1 + 10 + 9); - OSMO_ASSERT(num_chunks == 2); + } - OSMO_ASSERT(data[0] == ((10 << 2) | (1 << 1) | (1 << 0))); - OSMO_ASSERT(data[1] == 0); + return 0; +} - /* TS 44.060, B.8.1 */ - cs = GprsCodingScheme::MCS4; +static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase_header(BTS *the_bts, + uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta, + uint8_t ms_class) +{ + GprsMs *ms; + uint32_t rach_fn = *fn - 51; + uint32_t sba_fn = *fn + 52; + uint8_t trx_no = 0; + int tfi = 0; + gprs_rlcmac_ul_tbf *ul_tbf; + struct gprs_rlcmac_pdch *pdch; + gprs_rlcmac_bts *bts; + RlcMacUplink_t ulreq = {0}; + struct pcu_l1_meas meas; + meas.set_rssi(31); + uint8_t data_buf[156] = {0}; + + uint8_t data[144] = {0}; + struct gprs_rlc_ul_header_egprs_1_test *egprs1 = NULL; + egprs1 = (struct gprs_rlc_ul_header_egprs_1_test *) data; + + + struct gprs_rlc_ul_header_egprs_2_test *egprs2 = NULL; + + bts = the_bts->bts_data(); + + /* needed to set last_rts_fn in the PDCH object */ + request_dl_rlc_block(bts, trx_no, ts_no, 0, fn); + + /* simulate RACH, this sends an Immediate Assignment Uplink on the AGCH */ + the_bts->rcv_rach(0x73, rach_fn, qta); + + /* get next free TFI */ + tfi = the_bts->tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1); + + /* fake a resource request */ + ulreq.u.MESSAGE_TYPE = MT_PACKET_RESOURCE_REQUEST; + ulreq.u.Packet_Resource_Request.PayloadType = GPRS_RLCMAC_CONTROL_BLOCK; + ulreq.u.Packet_Resource_Request.ID.UnionType = 1; /* != 0 */ + ulreq.u.Packet_Resource_Request.ID.u.TLLI = tlli; + ulreq.u.Packet_Resource_Request.Exist_MS_Radio_Access_capability = 1; + ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability. + Count_MS_RA_capability_value = 1; + ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability. + MS_RA_capability_value[0].u.Content.Exist_Multislot_capability = 1; + ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability. + MS_RA_capability_value[0].u.Content.Multislot_capability. + Exist_GPRS_multislot_class = 1; + ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability. + MS_RA_capability_value[0].u.Content.Multislot_capability. + GPRS_multislot_class = ms_class; + + send_ul_mac_block(the_bts, trx_no, ts_no, &ulreq, sba_fn); + + /* check the TBF */ + ul_tbf = the_bts->ul_tbf_by_tfi(tfi, trx_no, ts_no); + OSMO_ASSERT(ul_tbf != NULL); + OSMO_ASSERT(ul_tbf->ta() == qta / 4); + + egprs1 -> si = 1; + egprs1 -> r = 1; + egprs1 -> cv = 7; + egprs1 -> tfi_a = tfi & (~((~0) << 2 )); + + egprs1 -> tfi_b = tfi & (~((~0) << 3 )) << 2; ; + egprs1 -> bsn1_a = 10; + egprs1 -> bsn1_b = 17; + egprs1 -> bsn2_a = 0; + egprs1 -> bsn2_b = 25; + egprs1 -> cps = 15; + egprs1 -> rsb = 1; + egprs1 -> pi = 0; + egprs1 -> spare = 1; + egprs1 -> spare2 = 10; + egprs1 -> dummy = 2; + egprs1 -> e1 = 0; + egprs1 -> ti1 = 1; + egprs1 -> dummy1 = 2; + egprs1 -> e2 = 1; + egprs1 -> length1 = 40; + + egprs1 -> e3 = 0; + egprs1 -> ti2 = 1; + egprs1 -> dummy2 = 2; + egprs1 -> e4 = 1; + egprs1 -> length2 = 33; + + pdch = &the_bts->bts_data()->trx[trx_no].pdch[ts_no]; + pdch->rcv_block(&data[0], 144, *fn, &meas); + + + egprs2 = (struct gprs_rlc_ul_header_egprs_2_test *) data_buf; + egprs2 -> si = 1; + egprs2 -> r = 1; + egprs2 -> cv = 7; + egprs2 -> tfi_a = tfi >> 3; + egprs2 -> tfi_b = (tfi & 0x7); + egprs2 -> bsn1_a = 14; + egprs2 -> bsn1_b = 21; + egprs2 -> bsn2_a = 3; + egprs2 -> bsn2_b = 29; + egprs2 -> cps = 8; + egprs2 -> rsb = 1; + egprs2 -> pi = 0; + egprs2 -> spare = 1; + egprs2 -> spare2 = 10; + egprs2 -> dummy = 2; + egprs2 -> e1 = 0; + egprs2 -> ti1 = 0; + egprs2 -> dummy1 = 2; + egprs2 -> e2 = 1; + egprs2 -> length1 = 40; + egprs2 -> e3 = 0; + egprs2 -> ti2 = 1; + egprs2 -> dummy2 = 2; + egprs2 -> e4 = 1; + egprs2 -> length2 = 33; + pdch->rcv_block(&data_buf[0], 156, *fn, &meas); - /* Block 1 */ - gprs_rlc_data_block_info_init(&rdbi, cs, false); - num_chunks = 0; - write_offset = 0; - memset(data, 0, sizeof(data)); - llc.reset(); - llc.put_frame(llc_data, 11); +} - ar = Encoding::rlc_data_to_dl_append(&rdbi, cs, - &llc, &write_offset, &num_chunks, data, false); +void uplink_header_type1_test() +{ + BTS the_bts; + int ts_no = 7; + uint32_t fn = 2654218; + uint16_t qta = 31; + uint32_t tlli = 0xf1223344; + const char *imsi = "0011223344"; + uint8_t ms_class = 1; + gprs_rlcmac_ul_tbf *ul_tbf; + GprsMs *ms; - OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT); - OSMO_ASSERT(rdbi.e == 0); - OSMO_ASSERT(write_offset == 1 + 11); - OSMO_ASSERT(num_chunks == 1); + printf("=== start %s ===\n", __func__); - llc.reset(); - llc.put_frame(llc_data, 26); + setup_bts(&the_bts, ts_no, 9); - ar = Encoding::rlc_data_to_dl_append(&rdbi, cs, - &llc, &write_offset, &num_chunks, data, false); + ul_tbf = establish_ul_tbf_two_phase_header(&the_bts, ts_no, tlli, &fn, qta, ms_class); - OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT); - OSMO_ASSERT(rdbi.e == 0); - OSMO_ASSERT(write_offset == 2 + 11 + 26); - OSMO_ASSERT(num_chunks == 2); - llc.reset(); - llc.put_frame(llc_data, 99); +} - ar = Encoding::rlc_data_to_dl_append(&rdbi, cs, - &llc, &write_offset, &num_chunks, data, false); - OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS); - OSMO_ASSERT(rdbi.e == 0); - OSMO_ASSERT(rdbi.cv != 0); - OSMO_ASSERT(write_offset == (int)rdbi.data_len); - OSMO_ASSERT(num_chunks == 3); +void test_downlink_for_all_mcs(enum test_tbf_final_ack_mode test_mode, uint8_t mcs) +{ + BTS the_bts; + uint8_t ts_no = 4; + unsigned i; + uint8_t ms_class = 4; + uint32_t fn; + uint8_t block_nr; + uint8_t trx_no; + GprsMs *ms; + uint32_t tlli = 0xffeeddcc; - OSMO_ASSERT(data[0] == ((11 << 1) | (0 << 0))); - OSMO_ASSERT(data[1] == ((26 << 1) | (1 << 0))); - OSMO_ASSERT(data[2] == 0); + uint8_t rbb[64/8]; - /* TS 44.060, B.8.2 */ + gprs_rlcmac_dl_tbf *dl_tbf; + gprs_rlcmac_tbf *new_tbf; - /* Note that the spec confuses the byte numbering here, since it - * includes the FBI/E header bits into the N2 octet count which - * is not consistent with Section 10.3a.1 & 10.3a.2. */ + printf("=== start %s ===\n", __func__); + setup_bts(&the_bts, ts_no , (mcs + 5)); + dl_tbf = create_dl_tbf(&the_bts, ms_class, &trx_no); + dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF); + ms = dl_tbf->ms(); + + for (i = 0; i < sizeof(llc_data); i++) + llc_data[i] = i%256; + + /* Schedule two LLC frames */ + dl_tbf->append_data(ms_class, 4000, llc_data, 200); + + /* Send only a few RLC/MAC blocks */ + fn = 0; + int index = 0; + do { + /* Request to send one block */ + request_dl_rlc_block(dl_tbf, &fn, &block_nr); + index ++; + } while (index < 25); + + printf("=== end %s ===\n", __func__); - cs = GprsCodingScheme::MCS2; +} - /* Block 1 */ - gprs_rlc_data_block_info_init(&rdbi, cs, false); - num_chunks = 0; - write_offset = 0; - memset(data, 0, sizeof(data)); - llc.reset(); - llc.put_frame(llc_data, 15); +static void send_egprs_control_nack_all(gprs_rlcmac_tbf *tbf) +{ + RlcMacUplink_t ulreq = {0}; + + OSMO_ASSERT(tbf->poll_fn != 0); + + ulreq.u.MESSAGE_TYPE = MT_EGPRS_PACKET_DOWNLINK_ACK_NACK ; + EGPRS_PD_AckNack_t *Egprs_ackNack = + &ulreq.u.Egprs_Packet_Downlink_Ack_Nack; + + Egprs_ackNack->PayloadType = GPRS_RLCMAC_CONTROL_BLOCK; + Egprs_ackNack->DOWNLINK_TFI = tbf->tfi(); + Egprs_ackNack->Exist_EGPRS_ChannelQualityReport = 0; + Egprs_ackNack->Exist_ChannelRequestDescription = 0; + Egprs_ackNack->Exist_PFI = 0; + Egprs_ackNack->Exist_ExtensionBits = 0; + Egprs_ackNack->UnionType = 0; + Egprs_ackNack->u.EGPRS_AckNack.Desc.FINAL_ACK_INDICATION = 0; + Egprs_ackNack->u.EGPRS_AckNack.Desc.STARTING_SEQUENCE_NUMBER = 2; + Egprs_ackNack->u.EGPRS_AckNack.Desc.BEGINNING_OF_WINDOW = 1 ; + Egprs_ackNack->u.EGPRS_AckNack.Desc.END_OF_WINDOW = 1 ; + Egprs_ackNack->u.EGPRS_AckNack.Desc.Exist_CRBB = 0 ; + + Egprs_ackNack->u.EGPRS_AckNack.Desc.URBB_LENGTH = 10 ; /*Nack case*/ + Egprs_ackNack->u.EGPRS_AckNack.Desc.URBB[0] = 0; + Egprs_ackNack->u.EGPRS_AckNack.Desc.URBB[1] = 0; + send_ul_mac_block(tbf->bts, tbf->trx->trx_no, tbf->control_ts, + &ulreq, tbf->poll_fn); +} - ar = Encoding::rlc_data_to_dl_append(&rdbi, cs, - &llc, &write_offset, &num_chunks, data, false); +static void send_egprs_control_nack_and_ack(gprs_rlcmac_tbf *tbf) +{ + RlcMacUplink_t ulreq = {0}; + + OSMO_ASSERT(tbf->poll_fn != 0); + + ulreq.u.MESSAGE_TYPE = MT_EGPRS_PACKET_DOWNLINK_ACK_NACK ; + EGPRS_PD_AckNack_t *Egprs_ackNack = + &ulreq.u.Egprs_Packet_Downlink_Ack_Nack; + + Egprs_ackNack->PayloadType = GPRS_RLCMAC_CONTROL_BLOCK; + Egprs_ackNack->DOWNLINK_TFI = tbf->tfi(); + Egprs_ackNack->Exist_EGPRS_ChannelQualityReport = 0; + Egprs_ackNack->Exist_ChannelRequestDescription = 0; + Egprs_ackNack->Exist_PFI = 0; + Egprs_ackNack->Exist_ExtensionBits = 0; + Egprs_ackNack->UnionType = 0; + Egprs_ackNack->u.EGPRS_AckNack.Desc.FINAL_ACK_INDICATION = 0; + Egprs_ackNack->u.EGPRS_AckNack.Desc.STARTING_SEQUENCE_NUMBER = 2; + Egprs_ackNack->u.EGPRS_AckNack.Desc.BEGINNING_OF_WINDOW = 1 ; + Egprs_ackNack->u.EGPRS_AckNack.Desc.END_OF_WINDOW = 1 ; + Egprs_ackNack->u.EGPRS_AckNack.Desc.Exist_CRBB = 0 ; + + Egprs_ackNack->u.EGPRS_AckNack.Desc.URBB_LENGTH = 16 ; /*Nack case*/ + Egprs_ackNack->u.EGPRS_AckNack.Desc.URBB[0] = 0; + Egprs_ackNack->u.EGPRS_AckNack.Desc.URBB[2] = 0; + send_ul_mac_block(tbf->bts, tbf->trx->trx_no, tbf->control_ts, + &ulreq, tbf->poll_fn); +} - OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT); - OSMO_ASSERT(rdbi.e == 0); - OSMO_ASSERT(write_offset == 1 + 15); - OSMO_ASSERT(num_chunks == 1); +void test_downlink_retransmission_mcs5_mcs2() +{ - llc.reset(); - llc.put_frame(llc_data, 12); + BTS the_bts; + uint8_t ts_no = 4; + unsigned i; + uint8_t ms_class = 4; + uint32_t fn; + uint8_t block_nr; + uint8_t trx_no; + GprsMs *ms; + uint32_t tlli = 0xffeeddcc; - ar = Encoding::rlc_data_to_dl_append(&rdbi, cs, - &llc, &write_offset, &num_chunks, data, false); + uint8_t rbb[64/8]; - OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS); - OSMO_ASSERT(rdbi.e == 0); - OSMO_ASSERT(rdbi.cv != 0); - OSMO_ASSERT(write_offset == (int)rdbi.data_len); - OSMO_ASSERT(num_chunks == 2); + printf("=== start %s ===\n", __func__); + gprs_rlcmac_dl_tbf *dl_tbf; + gprs_rlcmac_tbf *new_tbf; + + setup_bts(&the_bts, ts_no , 9); + dl_tbf = create_dl_tbf(&the_bts, ms_class, &trx_no); + dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF); + ms = dl_tbf->ms(); + + for (i = 0; i < sizeof(llc_data); i++) + llc_data[i] = i%256; + + /* Schedule two LLC frames */ + dl_tbf->append_data(ms_class, 1000, llc_data, 25); + + /* Send only a few RLC/MAC blocks */ + fn = 0; + int index1 = 0; + while(index1 < 4){ + /* Request to send one block */ + request_dl_rlc_block(dl_tbf, &fn, &block_nr); + index1 ++; + if(dl_tbf->m_window.m_v_b.is_unacked(0)) + { + dl_tbf->m_window.m_v_b.mark_nacked(0); + ms->set_current_cs_dl(6); + } - OSMO_ASSERT(data[0] == ((15 << 1) | (1 << 0))); - OSMO_ASSERT(data[1] == 0); + } + printf("=== end %s ===\n", __func__); + +} - /* Block 2 */ - gprs_rlc_data_block_info_init(&rdbi, cs, false); - num_chunks = 0; - write_offset = 0; - memset(data, 0, sizeof(data)); +void test_downlink_retransmission_mcs7_mcs5() +{ - OSMO_ASSERT(llc.chunk_size() == 0); + BTS the_bts; + uint8_t ts_no = 4; + unsigned i; + uint8_t ms_class = 4; + uint32_t fn; + uint8_t block_nr; + uint8_t trx_no; + GprsMs *ms; + uint32_t tlli = 0xffeeddcc; + + uint8_t rbb[64/8]; +printf("=== start %s ===\n", __func__); + + gprs_rlcmac_dl_tbf *dl_tbf; + gprs_rlcmac_tbf *new_tbf; + + setup_bts(&the_bts, ts_no , 11); + dl_tbf = create_dl_tbf(&the_bts, ms_class, &trx_no); + dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF); + ms = dl_tbf->ms(); + + for (i = 0; i < sizeof(llc_data); i++) + llc_data[i] = i%256; + + /* Schedule two LLC frames */ + dl_tbf->append_data(ms_class, 1000, llc_data, 100); + + /* Send only a few RLC/MAC blocks */ + fn = 0; + int index1 = 0; + while(index1 < 4){ + /* Request to send one block */ + request_dl_rlc_block(dl_tbf, &fn, &block_nr); + index1 ++; + if(dl_tbf->m_window.m_v_b.is_unacked(0)) + { + dl_tbf->m_window.m_v_b.mark_nacked(0); + ms->set_current_cs_dl(9); + } - ar = Encoding::rlc_data_to_dl_append(&rdbi, cs, - &llc, &write_offset, &num_chunks, data, false); + } + + printf("=== end %s ===\n", __func__); +} +void test_downlink_retransmission_mcs8_mcs6_mcs3() +{ - OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT); - OSMO_ASSERT(rdbi.e == 0); - OSMO_ASSERT(write_offset == 1 + 0); - OSMO_ASSERT(num_chunks == 1); + BTS the_bts; + uint8_t ts_no = 4; + unsigned i; + uint8_t ms_class = 4; + uint32_t fn; + uint8_t block_nr; + uint8_t trx_no; + GprsMs *ms; + uint32_t tlli = 0xffeeddcc; - llc.reset(); - llc.put_frame(llc_data, 7); + printf("=== start %s ===\n", __func__); + uint8_t rbb[64/8]; + + gprs_rlcmac_dl_tbf *dl_tbf; + gprs_rlcmac_tbf *new_tbf; + + setup_bts(&the_bts, ts_no , 12); + dl_tbf = create_dl_tbf(&the_bts, ms_class, &trx_no); + dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF); + ms = dl_tbf->ms(); + + for (i = 0; i < sizeof(llc_data); i++) + llc_data[i] = i%256; + + /* Schedule two LLC frames */ + dl_tbf->append_data(ms_class, 1000, llc_data, 100); + + /* Send only a few RLC/MAC blocks */ + fn = 0; + int index1 = 0; + bool hit_already = false; + while(index1 < 10){ + /* Request to send one block */ + request_dl_rlc_block(dl_tbf, &fn, &block_nr); + index1 ++; + if(dl_tbf->m_window.m_v_b.is_unacked(0) && (hit_already == false)) + { + hit_already = true; + dl_tbf->m_window.m_v_b.mark_nacked(0); + ms->set_current_cs_dl(10); + }else if( hit_already == true){ + ms->set_current_cs_dl(7); + } + } + printf("=== end %s ===\n", __func__); + +} - ar = Encoding::rlc_data_to_dl_append(&rdbi, cs, - &llc, &write_offset, &num_chunks, data, false); +void test_downlink_retransmission_mcs8_mcs6() +{ - OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT); - OSMO_ASSERT(rdbi.e == 0); - OSMO_ASSERT(rdbi.cv != 0); - OSMO_ASSERT(write_offset == 2 + 0 + 7); - OSMO_ASSERT(num_chunks == 2); + BTS the_bts; + uint8_t ts_no = 4; + unsigned i; + uint8_t ms_class = 4; + uint32_t fn; + uint8_t block_nr; + uint8_t trx_no; + GprsMs *ms; + uint32_t tlli = 0xffeeddcc; - llc.reset(); - llc.put_frame(llc_data, 18); + uint8_t rbb[64/8]; - ar = Encoding::rlc_data_to_dl_append(&rdbi, cs, - &llc, &write_offset, &num_chunks, data, false); + printf("=== start %s ===\n", __func__); + gprs_rlcmac_dl_tbf *dl_tbf; + gprs_rlcmac_tbf *new_tbf; + + setup_bts(&the_bts, ts_no , 12); + dl_tbf = create_dl_tbf(&the_bts, ms_class, &trx_no); + dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF); + ms = dl_tbf->ms(); + + for (i = 0; i < sizeof(llc_data); i++) + llc_data[i] = i%256; + + /* Schedule two LLC frames */ + dl_tbf->append_data(ms_class, 1000, llc_data, 100); + + /* Send only a few RLC/MAC blocks */ + fn = 0; + int index1 = 0; + while(index1 < 4){ + /* Request to send one block */ + request_dl_rlc_block(dl_tbf, &fn, &block_nr); + index1 ++; + if(dl_tbf->m_window.m_v_b.is_unacked(0)) + { + dl_tbf->m_window.m_v_b.mark_nacked(0); + ms->set_current_cs_dl(10); + } - OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED); - OSMO_ASSERT(rdbi.e == 0); - OSMO_ASSERT(rdbi.cv != 0); - OSMO_ASSERT(write_offset == (int)rdbi.data_len); - OSMO_ASSERT(num_chunks == 3); + } + printf("=== end %s ===\n", __func__); + +} +void test_downlink_retransmission_mcs9_mcs6() +{ - OSMO_ASSERT(data[0] == ((0 << 1) | (0 << 0))); - OSMO_ASSERT(data[1] == ((7 << 1) | (0 << 0))); - OSMO_ASSERT(data[2] == ((18 << 1) | (1 << 0))); - OSMO_ASSERT(data[3] == 0); + BTS the_bts; + uint8_t ts_no = 4; + unsigned i; + uint8_t ms_class = 4; + uint32_t fn; + uint8_t block_nr; + uint8_t trx_no; + GprsMs *ms; + uint32_t tlli = 0xffeeddcc; - /* Block 3 */ - gprs_rlc_data_block_info_init(&rdbi, cs, false); - num_chunks = 0; - write_offset = 0; - memset(data, 0, sizeof(data)); + printf("=== start %s ===\n", __func__); + uint8_t rbb[64/8]; + + gprs_rlcmac_dl_tbf *dl_tbf; + gprs_rlcmac_tbf *new_tbf; + + setup_bts(&the_bts, ts_no , 13); + dl_tbf = create_dl_tbf(&the_bts, ms_class, &trx_no); + dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF); + ms = dl_tbf->ms(); + + for (i = 0; i < sizeof(llc_data); i++) + llc_data[i] = i%256; + + /* Schedule two LLC frames */ + dl_tbf->append_data(ms_class, 1000, llc_data, 100); + + /* Send only a few RLC/MAC blocks */ + fn = 0; + int index1 = 0; + while(index1 < 4){ + /* Request to send one block */ + request_dl_rlc_block(dl_tbf, &fn, &block_nr); + index1 ++; + if(dl_tbf->m_window.m_v_b.is_unacked(0)) + { + dl_tbf->m_window.m_v_b.mark_nacked(0); + ms->set_current_cs_dl(10); + } - llc.reset(); - llc.put_frame(llc_data, 6); + } + printf("=== end %s ===\n", __func__); + +} - ar = Encoding::rlc_data_to_dl_append(&rdbi, cs, - &llc, &write_offset, &num_chunks, data, false); - OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT); - OSMO_ASSERT(rdbi.e == 0); - OSMO_ASSERT(write_offset == 1 + 6); - OSMO_ASSERT(num_chunks == 1); +void test_downlink_retransmission_mcs4_mcs1() +{ - llc.reset(); - llc.put_frame(llc_data, 12); + BTS the_bts; + uint8_t ts_no = 4; + unsigned i; + uint8_t ms_class = 4; + uint32_t fn; + uint8_t block_nr; + uint8_t trx_no; + GprsMs *ms; + uint32_t tlli = 0xffeeddcc; + + printf("=== start %s ===\n", __func__); + uint8_t rbb[64/8]; + + gprs_rlcmac_dl_tbf *dl_tbf; + gprs_rlcmac_tbf *new_tbf; + + setup_bts(&the_bts, ts_no , 8); + dl_tbf = create_dl_tbf(&the_bts, ms_class, &trx_no); + dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF); + ms = dl_tbf->ms(); + + for (i = 0; i < sizeof(llc_data); i++) + llc_data[i] = i%256; + + /* Schedule two LLC frames */ + dl_tbf->append_data(ms_class, 1000, llc_data, 25); + + /* Send only a few RLC/MAC blocks */ + fn = 0; + int index1 = 0; + while(index1 < 4){ + /* Request to send one block */ + request_dl_rlc_block(dl_tbf, &fn, &block_nr); + index1 ++; + if(dl_tbf->m_window.m_v_b.is_unacked(0)) + { + dl_tbf->m_window.m_v_b.mark_nacked(0); + ms->set_current_cs_dl(5); + } + + } + + printf("=== end %s ===\n", __func__); +} - ar = Encoding::rlc_data_to_dl_append(&rdbi, cs, - &llc, &write_offset, &num_chunks, data, true); +void test_downlink_retransmission_mcs6_mcs3() +{ - OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED); - OSMO_ASSERT(rdbi.e == 0); - OSMO_ASSERT(rdbi.cv == 0); - OSMO_ASSERT(write_offset == (int)rdbi.data_len); - OSMO_ASSERT(num_chunks == 3); + BTS the_bts; + uint8_t ts_no = 4; + unsigned i; + uint8_t ms_class = 4; + uint32_t fn; + uint8_t block_nr; + uint8_t trx_no; + GprsMs *ms; + uint32_t tlli = 0xffeeddcc; - OSMO_ASSERT(data[0] == ((6 << 1) | (0 << 0))); - OSMO_ASSERT(data[1] == ((12 << 1) | (0 << 0))); - OSMO_ASSERT(data[2] == ((127 << 1) | (1 << 0))); - OSMO_ASSERT(data[3] == 0); + uint8_t rbb[64/8]; - /* TS 44.060, B.8.3 */ + printf("=== start %s ===\n", __func__); + gprs_rlcmac_dl_tbf *dl_tbf; + gprs_rlcmac_tbf *new_tbf; + + setup_bts(&the_bts, ts_no , 10); + dl_tbf = create_dl_tbf(&the_bts, ms_class, &trx_no); + dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF); + ms = dl_tbf->ms(); + + for (i = 0; i < sizeof(llc_data); i++) + llc_data[i] = i%256; + + /* Schedule two LLC frames */ + dl_tbf->append_data(ms_class, 1000, llc_data, 25); + + /* Send only a few RLC/MAC blocks */ + fn = 0; + int index1 = 0; + while(index1 < 4){ + /* Request to send one block */ + request_dl_rlc_block(dl_tbf, &fn, &block_nr); + index1 ++; + if(dl_tbf->m_window.m_v_b.is_unacked(0)) + { + dl_tbf->m_window.m_v_b.mark_nacked(0); + ms->set_current_cs_dl(7); + } - /* Note that the spec confuses the byte numbering here, too (see above) */ + } + printf("=== end %s ===\n", __func__); + +} - cs = GprsCodingScheme::MCS2; +void test_downlink_retransmission_mcs9_mcs3() +{ - /* Block 1 */ - gprs_rlc_data_block_info_init(&rdbi, cs, false); - num_chunks = 0; - write_offset = 0; - memset(data, 0, sizeof(data)); + BTS the_bts; + uint8_t ts_no = 4; + unsigned i; + uint8_t ms_class = 4; + uint32_t fn; + uint8_t block_nr; + uint8_t trx_no; + GprsMs *ms; + uint32_t tlli = 0xffeeddcc; - llc.reset(); - llc.put_frame(llc_data, rdbi.data_len); + uint8_t rbb[64/8]; - ar = Encoding::rlc_data_to_dl_append(&rdbi, cs, - &llc, &write_offset, &num_chunks, data, true); + printf("=== start %s ===\n", __func__); + gprs_rlcmac_dl_tbf *dl_tbf; + gprs_rlcmac_tbf *new_tbf; + + setup_bts(&the_bts, ts_no , 13); + dl_tbf = create_dl_tbf(&the_bts, ms_class, &trx_no); + dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF); + ms = dl_tbf->ms(); + + for (i = 0; i < sizeof(llc_data); i++) + llc_data[i] = i%256; + + /* Schedule two LLC frames */ + dl_tbf->append_data(ms_class, 1000, llc_data, 100); + + /* Send only a few RLC/MAC blocks */ + fn = 0; + int index1 = 0; + while(index1 < 4){ + /* Request to send one block */ + request_dl_rlc_block(dl_tbf, &fn, &block_nr); + index1 ++; + if(dl_tbf->m_window.m_v_b.is_unacked(0)) + { + dl_tbf->m_window.m_v_b.mark_nacked(0); + ms->set_current_cs_dl(7); + } - OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED); - OSMO_ASSERT(rdbi.e == 1); - OSMO_ASSERT(rdbi.cv == 0); - OSMO_ASSERT(write_offset == (int)rdbi.data_len); - OSMO_ASSERT(num_chunks == 1); + } + printf("=== end %s ===\n", __func__); + +} +void test_downlink_retransmission_mcs8_mcs3() +{ - OSMO_ASSERT(data[0] == 0); + BTS the_bts; + uint8_t ts_no = 4; + unsigned i; + uint8_t ms_class = 4; + uint32_t fn; + uint8_t block_nr; + uint8_t trx_no; + GprsMs *ms; + uint32_t tlli = 0xffeeddcc; - /* Final block with an LLC of size data_len-1 */ + printf("=== start %s ===\n", __func__); + uint8_t rbb[64/8]; + + gprs_rlcmac_dl_tbf *dl_tbf; + gprs_rlcmac_tbf *new_tbf; + + setup_bts(&the_bts, ts_no , 12); + dl_tbf = create_dl_tbf(&the_bts, ms_class, &trx_no); + dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF); + ms = dl_tbf->ms(); + + for (i = 0; i < sizeof(llc_data); i++) + llc_data[i] = i%256; + + /* Schedule two LLC frames */ + dl_tbf->append_data(ms_class, 1000, llc_data, 100); + + /* Send only a few RLC/MAC blocks */ + fn = 0; + int index1 = 0; + while(index1 < 4){ + /* Request to send one block */ + request_dl_rlc_block(dl_tbf, &fn, &block_nr); + index1 ++; + if(dl_tbf->m_window.m_v_b.is_unacked(0)) + { + dl_tbf->m_window.m_v_b.mark_nacked(0); + ms->set_current_cs_dl(7); + } - cs = GprsCodingScheme::MCS2; + } + printf("=== end %s ===\n", __func__); + +} +void test_downlink_retransmission_mcs7_mcs2() +{ - /* Block 1 */ - gprs_rlc_data_block_info_init(&rdbi, cs, false); - num_chunks = 0; - write_offset = 0; - memset(data, 0, sizeof(data)); + BTS the_bts; + uint8_t ts_no = 4; + unsigned i; + uint8_t ms_class = 4; + uint32_t fn; + uint8_t block_nr; + uint8_t trx_no; + GprsMs *ms; + uint32_t tlli = 0xffeeddcc; + + uint8_t rbb[64/8]; + printf("=== start %s ===\n", __func__); - llc.reset(); - llc.put_frame(llc_data, rdbi.data_len - 1); + gprs_rlcmac_dl_tbf *dl_tbf; + gprs_rlcmac_tbf *new_tbf; + + setup_bts(&the_bts, ts_no , 11); + dl_tbf = create_dl_tbf(&the_bts, ms_class, &trx_no); + dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF); + ms = dl_tbf->ms(); + + for (i = 0; i < sizeof(llc_data); i++) + llc_data[i] = i%256; + + /* Schedule two LLC frames */ + dl_tbf->append_data(ms_class, 1000, llc_data, 100); + + /* Send only a few RLC/MAC blocks */ + fn = 0; + int index1 = 0; + while(index1 < 4){ + /* Request to send one block */ + request_dl_rlc_block(dl_tbf, &fn, &block_nr); + index1 ++; + if(dl_tbf->m_window.m_v_b.is_unacked(0)) + { + dl_tbf->m_window.m_v_b.mark_nacked(0); + ms->set_current_cs_dl(6); + } - ar = Encoding::rlc_data_to_dl_append(&rdbi, cs, - &llc, &write_offset, &num_chunks, data, true); + } + printf("=== end %s ===\n", __func__); + +} +static gprs_rlcmac_ul_tbf *mcs8_mcs6_retx(BTS *the_bts, + uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta, + uint8_t ms_class) +{ - OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED); - OSMO_ASSERT(rdbi.e == 0); - OSMO_ASSERT(rdbi.cv == 0); - OSMO_ASSERT(write_offset == (int)rdbi.data_len); - OSMO_ASSERT(num_chunks == 1); + GprsMs *ms; + uint32_t rach_fn = *fn - 51; + uint32_t sba_fn = *fn + 52; + uint8_t trx_no = 0; + int tfi = 0; + gprs_rlcmac_ul_tbf *ul_tbf; + struct gprs_rlcmac_pdch *pdch; + gprs_rlcmac_bts *bts; + RlcMacUplink_t ulreq = {0}; + struct pcu_l1_meas meas; + meas.set_rssi(31); + uint8_t data[80] = {0} ; + bts = the_bts->bts_data(); + + /* needed to set last_rts_fn in the PDCH object */ + request_dl_rlc_block(bts, trx_no, ts_no, 0, fn); + + /* simulate RACH, this sends an Immediate Assignment Uplink on the AGCH */ + the_bts->rcv_rach(0x73, rach_fn, qta); + + /* get next free TFI */ + tfi = the_bts->tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1); + + /* fake a resource request */ + ulreq.u.MESSAGE_TYPE = MT_PACKET_RESOURCE_REQUEST; + ulreq.u.Packet_Resource_Request.PayloadType = GPRS_RLCMAC_CONTROL_BLOCK; + ulreq.u.Packet_Resource_Request.ID.UnionType = 1; /* != 0 */ + ulreq.u.Packet_Resource_Request.ID.u.TLLI = tlli; + ulreq.u.Packet_Resource_Request.Exist_MS_Radio_Access_capability = 1; + ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability. + Count_MS_RA_capability_value = 1; + ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability. + MS_RA_capability_value[0].u.Content.Exist_Multislot_capability = 1; + ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability. + MS_RA_capability_value[0].u.Content.Multislot_capability. + Exist_GPRS_multislot_class = 1; + ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability. + MS_RA_capability_value[0].u.Content.Multislot_capability. + GPRS_multislot_class = ms_class; + + send_ul_mac_block(the_bts, trx_no, ts_no, &ulreq, sba_fn); + + /* check the TBF */ + ul_tbf = the_bts->ul_tbf_by_tfi(tfi, trx_no, ts_no); + OSMO_ASSERT(ul_tbf != NULL); + OSMO_ASSERT(ul_tbf->ta() == qta / 4); + + + + struct gprs_rlc_ul_header_egprs_2 *hdr2 = NULL; + + hdr2 = (struct gprs_rlc_ul_header_egprs_2 *)data; + + + /*header_construction */ + + hdr2 -> r = 1; + hdr2 -> si = 1; + hdr2 -> cv = 8; + hdr2 -> tfi_a = (tfi >> 3) & 0x3; + hdr2 -> tfi_b = tfi & 0x7; + hdr2 -> bsn1_a = 0; + hdr2 -> bsn1_b = 0; + hdr2 -> cps_a = 2; + hdr2 -> cps_b = 0; + hdr2 -> rsb = 1; + hdr2 -> pi = 0; + data[4] = 0x2b; + data[5] = 0x2b; + data[6] = 0x2b; + data[7] = 0x2b; + data[8] = 0x2b; + data[9] = 0x2b; + data[10] = 1; + data[11] = 81; /*the li =40 and e = 1*/ + + pdch = &the_bts->bts_data()->trx[trx_no].pdch[ts_no]; + + pdch->rcv_block(&data[0], 80, *fn, &meas); - OSMO_ASSERT(data[0] == (((rdbi.data_len-1) << 1) | (1 << 0))); - OSMO_ASSERT(data[1] == 0); +} - /* Final block with an LLC of size data_len-2 */ +static gprs_rlcmac_ul_tbf *spb_handler(BTS *the_bts, + uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta, + uint8_t ms_class) +{ - cs = GprsCodingScheme::MCS2; + GprsMs *ms; + uint32_t rach_fn = *fn - 51; + uint32_t sba_fn = *fn + 52; + uint8_t trx_no = 0; + int tfi = 0; + gprs_rlcmac_ul_tbf *ul_tbf; + struct gprs_rlcmac_pdch *pdch; + gprs_rlcmac_bts *bts; + RlcMacUplink_t ulreq = {0}; + struct pcu_l1_meas meas; + meas.set_rssi(31); + + bts = the_bts->bts_data(); + + /* needed to set last_rts_fn in the PDCH object */ + request_dl_rlc_block(bts, trx_no, ts_no, 0, fn); + + /* simulate RACH, this sends an Immediate Assignment Uplink on the AGCH */ + the_bts->rcv_rach(0x73, rach_fn, qta); + + /* get next free TFI */ + tfi = the_bts->tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1); + + /* fake a resource request */ + ulreq.u.MESSAGE_TYPE = MT_PACKET_RESOURCE_REQUEST; + ulreq.u.Packet_Resource_Request.PayloadType = GPRS_RLCMAC_CONTROL_BLOCK; + ulreq.u.Packet_Resource_Request.ID.UnionType = 1; /* != 0 */ + ulreq.u.Packet_Resource_Request.ID.u.TLLI = tlli; + ulreq.u.Packet_Resource_Request.Exist_MS_Radio_Access_capability = 1; + ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability. + Count_MS_RA_capability_value = 1; + ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability. + MS_RA_capability_value[0].u.Content.Exist_Multislot_capability = 1; + ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability. + MS_RA_capability_value[0].u.Content.Multislot_capability. + Exist_GPRS_multislot_class = 1; + ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability. + MS_RA_capability_value[0].u.Content.Multislot_capability. + GPRS_multislot_class = ms_class; + + send_ul_mac_block(the_bts, trx_no, ts_no, &ulreq, sba_fn); + + /* check the TBF */ + ul_tbf = the_bts->ul_tbf_by_tfi(tfi, trx_no, ts_no); + OSMO_ASSERT(ul_tbf != NULL); + OSMO_ASSERT(ul_tbf->ta() == qta / 4); + + + + struct gprs_rlc_ul_header_egprs_3 *hdr3 = NULL; + uint8_t data[42] = {0}; + + hdr3 = (struct gprs_rlc_ul_header_egprs_3 *)data; + + + /*header_construction */ + + hdr3 -> r = 1; + hdr3 -> si = 1; + hdr3 -> cv = 8; + hdr3 -> tfi_a = (tfi >> 3) & 0x3; + hdr3 -> tfi_b = tfi & 0x7; + hdr3 -> bsn1_a = 0; + hdr3 -> bsn1_b = 0; + hdr3 -> cps_a = 2; + hdr3 -> cps_b = 1; + hdr3 -> spb = 2 ; + hdr3 -> rsb = 1; + hdr3 -> pi = 0; + hdr3 -> spare = 1; + hdr3 -> dummy = 1; + data[4] = 0x2b; + data[5] = 0x2b; + data[6] = 0x2b; + data[7] = 0x2b; + data[8] = 0x2b; + data[9] = 0x2b; + data[10] = 1; + data[11] = 81; /*the li =40 and e = 1*/ + + pdch = &the_bts->bts_data()->trx[trx_no].pdch[ts_no]; + + pdch->rcv_block(&data[0], 42, *fn, &meas); + + memset(data, 0x2b , sizeof(data)); + + hdr3 = (struct gprs_rlc_ul_header_egprs_3 * )data; + + hdr3 -> r = 1; + hdr3 -> si = 1; + hdr3 -> cv = 8; + hdr3 -> tfi_a = (tfi >> 3) & 0x3; + hdr3 -> tfi_b = tfi & 0x7; + hdr3 -> bsn1_a = 0; + hdr3 -> bsn1_b = 0; + hdr3 -> cps_a = 3; + hdr3 -> cps_b = 0; + hdr3 -> spb =3; + hdr3 -> rsb = 1; + hdr3 -> pi = 0; + hdr3 -> spare = 1; + hdr3 -> dummy = 1; + data[4] = 1; + pdch = &the_bts->bts_data()->trx[trx_no].pdch[ts_no]; + pdch->rcv_block(&data[0], 42, *fn, &meas); - /* Block 1 */ - gprs_rlc_data_block_info_init(&rdbi, cs, false); - num_chunks = 0; - write_offset = 0; - memset(data, 0, sizeof(data)); +} - llc.reset(); - llc.put_frame(llc_data, rdbi.data_len - 2); - ar = Encoding::rlc_data_to_dl_append(&rdbi, cs, - &llc, &write_offset, &num_chunks, data, true); +void test_spb_handling() +{ + BTS the_bts; + int ts_no = 7; + uint32_t fn = 2654218; + uint16_t qta = 31; + uint32_t tlli = 0xf1223344; + const char *imsi = "0011223344"; + uint8_t ms_class = 1; + gprs_rlcmac_ul_tbf *ul_tbf; + GprsMs *ms; - OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED); - OSMO_ASSERT(rdbi.e == 0); - OSMO_ASSERT(rdbi.cv == 0); - OSMO_ASSERT(write_offset == (int)rdbi.data_len); - OSMO_ASSERT(num_chunks == 2); + printf("=== start %s ===\n", __func__); - OSMO_ASSERT(data[0] == (((rdbi.data_len-2) << 1) | (0 << 0))); - OSMO_ASSERT(data[1] == ((127 << 1) | (1 << 0))); - OSMO_ASSERT(data[2] == 0); + setup_bts(&the_bts, ts_no, 7); - printf("=== end %s ===\n", __func__); -} + ul_tbf = spb_handler(&the_bts, ts_no, tlli, &fn, qta, ms_class); -static void test_rlc_unaligned_copy() -{ - uint8_t bits[256]; - uint8_t saved_block[256]; - uint8_t test_block[256]; - uint8_t out_block[256]; - GprsCodingScheme::Scheme scheme; - int pattern; - volatile unsigned int block_idx, i; - - for (scheme = GprsCodingScheme::CS1; - scheme < GprsCodingScheme::NUM_SCHEMES; - scheme = GprsCodingScheme::Scheme(scheme + 1)) - { - GprsCodingScheme cs(scheme); - - for (pattern = 0; pattern <= 0xff; pattern += 0xff) { - /* prepare test block */ - test_block[0] = pattern ^ 0xff; - for (i = 1; i + 1 < cs.maxDataBlockBytes(); i++) - test_block[i] = i; - test_block[cs.maxDataBlockBytes()-1] = pattern ^ 0xff; - - for (block_idx = 0; - block_idx < cs.numDataBlocks(); - block_idx++) - { - struct gprs_rlc_data_info rlc; - gprs_rlc_data_info_init_dl(&rlc, cs, false); - - memset(bits, pattern, sizeof(bits)); - Decoding::rlc_copy_to_aligned_buffer( - &rlc, block_idx, bits, saved_block); - - fprintf(stderr, - "Test data block: %s\n", - osmo_hexdump(test_block, cs.maxDataBlockBytes())); - - Encoding::rlc_copy_from_aligned_buffer( - &rlc, block_idx, bits, test_block); - - fprintf(stderr, - "Encoded message block, %s, idx %d, " - "pattern %02x: %s\n", - rlc.cs.name(), block_idx, pattern, - osmo_hexdump(bits, cs.sizeDL())); - - Decoding::rlc_copy_to_aligned_buffer( - &rlc, block_idx, bits, out_block); - - fprintf(stderr, - "Out data block: %s\n", - osmo_hexdump(out_block, cs.maxDataBlockBytes())); - /* restore original bits */ - Encoding::rlc_copy_from_aligned_buffer( - &rlc, block_idx, bits, saved_block); - - OSMO_ASSERT(memcmp(test_block, out_block, - rlc.cs.maxDataBlockBytes()) == 0); - - for (i = 0; i < sizeof(bits); i++) - OSMO_ASSERT(bits[i] == pattern); - } - } - } } -static void test_rlc_info_init() +void test__mcs8_retx_mcs6() { - struct gprs_rlc_data_info rlc; + BTS the_bts; + int ts_no = 7; + uint32_t fn = 2654218; + uint16_t qta = 31; + uint32_t tlli = 0xf1223344; + const char *imsi = "0011223344"; + uint8_t ms_class = 1; + gprs_rlcmac_ul_tbf *ul_tbf; + GprsMs *ms; - printf("=== start %s ===\n", __func__); - gprs_rlc_data_info_init_dl(&rlc, GprsCodingScheme(GprsCodingScheme::CS1), false); - OSMO_ASSERT(rlc.num_data_blocks == 1); - OSMO_ASSERT(rlc.data_offs_bits[0] == 24); - OSMO_ASSERT(rlc.block_info[0].data_len == 20); + printf("=== start %s ===\n", __func__); - gprs_rlc_data_info_init_dl(&rlc, GprsCodingScheme(GprsCodingScheme::MCS1), false); - OSMO_ASSERT(rlc.num_data_blocks == 1); - OSMO_ASSERT(rlc.data_offs_bits[0] == 33); - OSMO_ASSERT(rlc.block_info[0].data_len == 22); + setup_bts(&the_bts, ts_no, 10); - printf("=== end %s ===\n", __func__); + ul_tbf = mcs8_mcs6_retx(&the_bts, ts_no, tlli, &fn, qta, ms_class); } -static const struct log_info_cat default_categories[] = { - {"DCSN1", "\033[1;31m", "Concrete Syntax Notation One (CSN1)", LOGL_INFO, 0}, - {"DL1IF", "\033[1;32m", "GPRS PCU L1 interface (L1IF)", LOGL_DEBUG, 1}, - {"DRLCMAC", "\033[0;33m", "GPRS RLC/MAC layer (RLCMAC)", LOGL_DEBUG, 1}, - {"DRLCMACDATA", "\033[0;33m", "GPRS RLC/MAC layer Data (RLCMAC)", LOGL_DEBUG, 1}, - {"DRLCMACDL", "\033[1;33m", "GPRS RLC/MAC layer Downlink (RLCMAC)", LOGL_DEBUG, 1}, - {"DRLCMACUL", "\033[1;36m", "GPRS RLC/MAC layer Uplink (RLCMAC)", LOGL_DEBUG, 1}, - {"DRLCMACSCHED", "\033[0;36m", "GPRS RLC/MAC layer Scheduling (RLCMAC)", LOGL_DEBUG, 1}, - {"DRLCMACMEAS", "\033[1;31m", "GPRS RLC/MAC layer Measurements (RLCMAC)", LOGL_INFO, 1}, - {"DNS","\033[1;34m", "GPRS Network Service Protocol (NS)", LOGL_INFO , 1}, - {"DBSSGP","\033[1;34m", "GPRS BSS Gateway Protocol (BSSGP)", LOGL_INFO , 1}, - {"DPCU", "\033[1;35m", "GPRS Packet Control Unit (PCU)", LOGL_NOTICE, 1}, -}; - -static int filter_fn(const struct log_context *ctx, - struct log_target *tar) -{ - return 1; -} -const struct log_info debug_log_info = { - filter_fn, - (struct log_info_cat*)default_categories, - ARRAY_SIZE(default_categories), -}; int main(int argc, char **argv) { + uint8_t i = 0, data_len = 0; struct vty_app_info pcu_vty_info = {0}; tall_pcu_ctx = talloc_named_const(NULL, 1, "EdgeTest context"); @@ -1118,11 +2557,33 @@ int main(int argc, char **argv) pcu_vty_init(&debug_log_info); test_coding_scheme(); - test_rlc_info_init(); + test_rlc_decoder(); + test_spb_handling(); + test__mcs8_retx_mcs6(); + uplink_header_type1_test(); test_rlc_unit_decoder(); - test_rlc_unaligned_copy(); - test_rlc_unit_encoder(); + test_tbf_two_phase(); + + test_tbf_two_phase_PUAN(); + + for(i = 0; i < 9; i++) { + + test_downlink_for_all_mcs(TEST_MODE_STANDARD, i); + + } + test_downlink_retransmission_mcs6_mcs3(); + test_downlink_retransmission_mcs5_mcs2(); + test_downlink_retransmission_mcs4_mcs1(); + test_downlink_retransmission_mcs7_mcs5(); + test_downlink_retransmission_mcs8_mcs6(); + test_downlink_retransmission_mcs9_mcs6(); + + test_downlink_retransmission_mcs9_mcs3(); + test_downlink_retransmission_mcs8_mcs3(); + test_downlink_retransmission_mcs7_mcs2(); + test_downlink_retransmission_mcs8_mcs6_mcs3(); + test_tbf_final_ack_EPDAN(TEST_MODE_STANDARD); if (getenv("TALLOC_REPORT_FULL")) talloc_report_full(tall_pcu_ctx, stderr); return EXIT_SUCCESS; |