[2/2] Add EGPRS header type 1 parsing function in uplink

Submitted by Bhargava Abhyankar on March 31, 2016, 7:25 a.m.

Details

Message ID 1459409114-25865-2-git-send-email-Bhargava.Abhyankar@radisys.com
State New
Series "Series without cover letter"
Headers show

Commit Message

Bhargava Abhyankar March 31, 2016, 7:25 a.m.
Function 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 | 163 +++++++++++++++++++++++++++++++++++++++++++++++-
 tests/edge/EdgeTest.ok  |   2 +
 5 files changed, 224 insertions(+), 10 deletions(-)

Patch hide | download patch | download mbox

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 4d61083..6844856 100644
--- a/src/decoding.cpp
+++ b/src/decoding.cpp
@@ -356,6 +356,8 @@  int Decoding::rlc_parse_ul_data_header(struct gprs_rlc_data_info *rlc,
 		cur_bit = rlc_parse_ul_data_header_egprs_type_2(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",
@@ -482,6 +484,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, const 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 9fb2c85..d787494 100644
--- a/src/decoding.h
+++ b/src/decoding.h
@@ -55,6 +55,10 @@  public:
 		struct gprs_rlc_data_info *rlc,
 		const uint8_t *data,
 		const GprsCodingScheme &cs);
+	static int rlc_parse_ul_data_header_egprs_type_1(
+		struct gprs_rlc_data_info *rlc,
+		const uint8_t *data,
+		const 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..ff080f9 100644
--- a/tests/edge/EdgeTest.cpp
+++ b/tests/edge/EdgeTest.cpp
@@ -1250,6 +1250,167 @@  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);
+
+	/* 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 +1432,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 ===