This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/osmocom-net-gprs@lists.osmocom.org/.
Bhargava Abhyankar Bhargava.Abhyankar at radisys.comFunction is added to parse the EGPRS header type 1 in uplink tbf path. This is added to further support mcs 5 to mcs 9 in uplink. --- src/bts.cpp | 9 --- src/decoding.cpp | 56 +++++++++++++++++ src/decoding.h | 4 ++ tests/edge/EdgeTest.cpp | 164 +++++++++++++++++++++++++++++++++++++++++++++++- tests/edge/EdgeTest.ok | 2 + 5 files changed, 225 insertions(+), 10 deletions(-) diff --git a/src/bts.cpp b/src/bts.cpp index 715fb51..f818ee2 100644 --- a/src/bts.cpp +++ b/src/bts.cpp @@ -1333,15 +1333,6 @@ int gprs_rlcmac_pdch::rcv_data_block(uint8_t *data, uint32_t fn, cs.name()); return -EINVAL; } - - if (!cs.isEgprsGmsk()) { - LOGP(DRLCMACUL, LOGL_ERROR, - "Got %s RLC block but EGPRS is not implemented " - "for 8PSK yet\n", - cs.name()); - bts()->decode_error(); - return -EINVAL; - } } LOGP(DRLCMACUL, LOGL_DEBUG, " UL data: %s\n", osmo_hexdump(data, len)); diff --git a/src/decoding.cpp b/src/decoding.cpp index ad5b05f..f3d5515 100644 --- a/src/decoding.cpp +++ b/src/decoding.cpp @@ -416,6 +416,8 @@ int Decoding::rlc_parse_ul_data_header(struct gprs_rlc_data_info *rlc, data, cs); break; case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1 : + cur_bit = rlc_parse_ul_data_header_egprs_type_1(rlc, data, cs); + break; default: LOGP(DRLCMACDL, LOGL_ERROR, "Decoding of uplink %s data blocks not yet supported.\n", @@ -470,6 +472,60 @@ int Decoding::rlc_parse_ul_data_header_egprs_type_2( return cur_bit; } +int Decoding::rlc_parse_ul_data_header_egprs_type_1( + struct gprs_rlc_data_info *rlc, + const uint8_t *data, GprsCodingScheme cs) +{ + struct gprs_rlc_ul_header_egprs_1 *egprs1; + unsigned int e_ti_header, cur_bit = 0, offs; + int punct, punct2, with_padding; + + egprs1 = static_cast < struct gprs_rlc_ul_header_egprs_1 * > + ((void *)data); + gprs_rlc_mcs_cps_decode(egprs1->cps, cs, &punct, &punct2, + &with_padding); + gprs_rlc_data_info_init_ul(rlc, cs, with_padding); + + rlc->r = egprs1->r; + rlc->si = egprs1->si; + rlc->tfi = (egprs1->tfi_a << 0) | (egprs1->tfi_b << 2); + rlc->cps = egprs1->cps; + rlc->rsb = egprs1->rsb; + rlc->num_data_blocks = 2; + rlc->block_info[0].cv = egprs1->cv; + rlc->block_info[0].pi = egprs1->pi; + rlc->block_info[0].bsn = + (egprs1->bsn1_a << 0) | (egprs1->bsn1_b << 5); + + cur_bit += rlc->data_offs_bits[0] - 2; + offs = rlc->data_offs_bits[0] / 8; + OSMO_ASSERT(rlc->data_offs_bits[0] % 8 == 0); + + e_ti_header = (data[offs-1] + (data[offs] << 8)) >> 7; + rlc->block_info[0].e = !!(e_ti_header & 0x01); + rlc->block_info[0].ti = !!(e_ti_header & 0x02); + cur_bit += 2; + + rlc->block_info[1].cv = egprs1->cv; + rlc->block_info[1].pi = egprs1->pi; + rlc->block_info[1].bsn = rlc->block_info[0].bsn + + ((egprs1->bsn2_a << 0) | (egprs1->bsn2_b << 2)); + rlc->block_info[1].bsn = rlc->block_info[1].bsn & (RLC_EGPRS_SNS - 1); + + cur_bit += rlc->data_offs_bits[1] - 2; + + offs = rlc->data_offs_bits[1] / 8; + OSMO_ASSERT(rlc->data_offs_bits[1] % 8 == 2); + + e_ti_header = (data[offs-1] + (data[offs] << 8)) >> 7; + rlc->block_info[1].e = !!(e_ti_header & 0x01); + rlc->block_info[1].ti = !!(e_ti_header & 0x02); + cur_bit += 2; + /* skip data area */ + cur_bit += cs.maxDataBlockBytes() * 8; + + return cur_bit; +} /** * \brief Copy LSB bitstream RLC data block to byte aligned buffer. * diff --git a/src/decoding.h b/src/decoding.h index 2cb053d..9c74953 100644 --- a/src/decoding.h +++ b/src/decoding.h @@ -47,6 +47,10 @@ public: struct gprs_rlc_data_info *rlc, const uint8_t *data, GprsCodingScheme cs); + static int rlc_parse_ul_data_header_egprs_type_1( + struct gprs_rlc_data_info *rlc, + const uint8_t *data, + GprsCodingScheme cs); static int rlc_parse_ul_data_header(struct gprs_rlc_data_info *rlc, const uint8_t *data, GprsCodingScheme cs); static unsigned int rlc_copy_to_aligned_buffer( diff --git a/tests/edge/EdgeTest.cpp b/tests/edge/EdgeTest.cpp index c2dfc0b..daaaed2 100644 --- a/tests/edge/EdgeTest.cpp +++ b/tests/edge/EdgeTest.cpp @@ -1250,6 +1250,168 @@ const struct log_info debug_log_info = { ARRAY_SIZE(default_categories), }; +static void setup_bts(BTS *the_bts, uint8_t ts_no, uint8_t cs = 1) +{ + gprs_rlcmac_bts *bts; + gprs_rlcmac_trx *trx; + + 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]; + trx->pdch[ts_no].enable(); +} + +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 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 unsigned fn2bn(unsigned fn) +{ + return (fn % 52) / 4; +} + +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 gprs_rlcmac_ul_tbf *uplink_header_parsing_test(BTS *the_bts, + uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta, + uint8_t ms_class) +{ + GprsMs *ms; + struct pcu_l1_meas meas; + 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}; + uint8_t data[144] = {0}; + struct gprs_rlc_ul_header_egprs_1 *egprs1 = NULL; + + meas.set_rssi(31); + egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data; + 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 a 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); + 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 = 0; + egprs1->pi = 0; + data[6] = 1; + data[6 + 68] = 1; + data[75] = 1; + data[75 + 68] = 1; + pdch = &the_bts->bts_data()->trx[trx_no].pdch[ts_no]; + pdch->rcv_block(&data[0], 143, *fn, &meas); +} + +void uplink_header_type1_test(void) +{ + 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__); + setup_bts(&the_bts, ts_no, 12); + ul_tbf = uplink_header_parsing_test(&the_bts, ts_no, tlli, &fn, + qta, ms_class); + printf("=== end %s ===\n", __func__); +} + int main(int argc, char **argv) { struct vty_app_info pcu_vty_info = {0}; @@ -1271,7 +1433,7 @@ int main(int argc, char **argv) test_rlc_unit_decoder(); test_rlc_unaligned_copy(); test_rlc_unit_encoder(); - + uplink_header_type1_test(); if (getenv("TALLOC_REPORT_FULL")) talloc_report_full(tall_pcu_ctx, stderr); return EXIT_SUCCESS; diff --git a/tests/edge/EdgeTest.ok b/tests/edge/EdgeTest.ok index 9554df3..353f55d 100644 --- a/tests/edge/EdgeTest.ok +++ b/tests/edge/EdgeTest.ok @@ -6,3 +6,5 @@ === end test_rlc_unit_decoder === === start test_rlc_unit_encoder === === end test_rlc_unit_encoder === +=== start uplink_header_type1_test === +=== end uplink_header_type1_test === -- 2.5.0