rlc: Add with_padding argument to gprs_rlc_data_info_init_dl/ul

The offsets of the data areas change when padding is used (see TS
44.060, 9.3.2.1 and Annex J for details).

Extend the parameter lists to pass the with_padding flag and use
that information to compute the correct offsets.

Sponsored-by: On-Waves ehf
diff --git a/src/rlc.cpp b/src/rlc.cpp
index efe4261..ca12e91 100644
--- a/src/rlc.cpp
+++ b/src/rlc.cpp
@@ -282,43 +282,52 @@
 }
 
 static void gprs_rlc_data_header_init(struct gprs_rlc_data_info *rlc,
-	GprsCodingScheme cs, unsigned int header_bits)
+	GprsCodingScheme cs, bool with_padding, unsigned int header_bits)
 {
 	unsigned int i;
+	unsigned int padding_bits = with_padding ? cs.optionalPaddingBits() : 0;
 
 	memset(rlc, 0, sizeof(*rlc));
 
 	rlc->cs = cs;
+	rlc->with_padding = with_padding;
 	rlc->num_data_blocks = cs.numDataBlocks();
 
 	OSMO_ASSERT(rlc->num_data_blocks <= ARRAY_SIZE(rlc->block_info));
 
 	for (i = 0; i < rlc->num_data_blocks; i++) {
-		gprs_rlc_data_block_info_init(&rlc->block_info[i], cs);
+		gprs_rlc_data_block_info_init(&rlc->block_info[i], cs,
+			with_padding);
 
 		rlc->data_offs_bits[i] =
-			header_bits +
+			header_bits + padding_bits +
 			(i+1) * cs.numDataBlockHeaderBits() +
 			i * 8 * rlc->block_info[0].data_len;
 	}
 }
 
 void gprs_rlc_data_info_init_dl(struct gprs_rlc_data_info *rlc,
-	GprsCodingScheme cs)
+	GprsCodingScheme cs, bool with_padding)
 {
-	return gprs_rlc_data_header_init(rlc, cs, cs.numDataHeaderBitsDL());
+	return gprs_rlc_data_header_init(rlc, cs, with_padding,
+		cs.numDataHeaderBitsDL());
 }
 
 void gprs_rlc_data_info_init_ul(struct gprs_rlc_data_info *rlc,
-	GprsCodingScheme cs)
+	GprsCodingScheme cs, bool with_padding)
 {
-	return gprs_rlc_data_header_init(rlc, cs, cs.numDataHeaderBitsUL());
+	return gprs_rlc_data_header_init(rlc, cs, with_padding,
+		cs.numDataHeaderBitsUL());
 }
 
 void gprs_rlc_data_block_info_init(struct gprs_rlc_data_block_info *rdbi,
-	GprsCodingScheme cs)
+	GprsCodingScheme cs, bool with_padding)
 {
-	rdbi->data_len = cs.maxDataBlockBytes();
+	unsigned int data_len = cs.maxDataBlockBytes();
+	if (with_padding)
+		data_len -= cs.optionalPaddingBits() / 8;
+
+	rdbi->data_len = data_len;
 	rdbi->bsn = 0;
 	rdbi->ti  = 0;
 	rdbi->e   = 1;
diff --git a/src/rlc.h b/src/rlc.h
index 8c3a412..f6415b7 100644
--- a/src/rlc.h
+++ b/src/rlc.h
@@ -83,6 +83,7 @@
 	unsigned int rrbp;
 	unsigned int pr;
 	unsigned int num_data_blocks;
+	unsigned int with_padding;
 	unsigned int data_offs_bits[2];
 	struct gprs_rlc_data_block_info block_info[2];
 };
@@ -101,11 +102,11 @@
 };
 
 void gprs_rlc_data_info_init_dl(struct gprs_rlc_data_info *rlc,
-	GprsCodingScheme cs);
+	GprsCodingScheme cs, bool with_padding);
 void gprs_rlc_data_info_init_ul(struct gprs_rlc_data_info *rlc,
-	GprsCodingScheme cs);
+	GprsCodingScheme cs, bool with_padding);
 void gprs_rlc_data_block_info_init(struct gprs_rlc_data_block_info *rdbi,
-	GprsCodingScheme cs);
+	GprsCodingScheme cs, bool with_padding);
 unsigned int gprs_rlc_mcs_cps(GprsCodingScheme cs, int punct, int punct2,
 	int with_padding);
 
diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp
index e567f57..6208b60 100644
--- a/src/tbf_dl.cpp
+++ b/src/tbf_dl.cpp
@@ -540,7 +540,7 @@
 
 	cs = m_rlc.block(index)->cs;
 
-	gprs_rlc_data_info_init_dl(&rlc, cs);
+	gprs_rlc_data_info_init_dl(&rlc, cs, false);
 
 	rlc.usf = 7; /* will be set at scheduler */
 	rlc.pr = 0; /* FIXME: power reduction */
diff --git a/tests/edge/EdgeTest.cpp b/tests/edge/EdgeTest.cpp
index 80997a4..96ea0c1 100644
--- a/tests/edge/EdgeTest.cpp
+++ b/tests/edge/EdgeTest.cpp
@@ -515,7 +515,7 @@
 
 	/* TS 44.060, B.1 */
 	cs = GprsCodingScheme::CS4;
-	gprs_rlc_data_block_info_init(&rdbi, cs);
+	gprs_rlc_data_block_info_init(&rdbi, cs, false);
 	num_chunks = 0;
 	write_offset = 0;
 	memset(data, 0, sizeof(data));
@@ -562,7 +562,7 @@
 	cs = GprsCodingScheme::CS1;
 
 	/* Block 1 */
-	gprs_rlc_data_block_info_init(&rdbi, cs);
+	gprs_rlc_data_block_info_init(&rdbi, cs, false);
 	num_chunks = 0;
 	write_offset = 0;
 	memset(data, 0, sizeof(data));
@@ -582,7 +582,7 @@
 	OSMO_ASSERT(data[1] == 0);
 
 	/* Block 2 */
-	gprs_rlc_data_block_info_init(&rdbi, cs);
+	gprs_rlc_data_block_info_init(&rdbi, cs, false);
 	num_chunks = 0;
 	write_offset = 0;
 	memset(data, 0, sizeof(data));
@@ -615,7 +615,7 @@
 	cs = GprsCodingScheme::CS1;
 
 	/* Block 1 */
-	gprs_rlc_data_block_info_init(&rdbi, cs);
+	gprs_rlc_data_block_info_init(&rdbi, cs, false);
 	num_chunks = 0;
 	write_offset = 0;
 	memset(data, 0, sizeof(data));
@@ -650,7 +650,7 @@
 	cs = GprsCodingScheme::CS1;
 
 	/* Block 1 */
-	gprs_rlc_data_block_info_init(&rdbi, cs);
+	gprs_rlc_data_block_info_init(&rdbi, cs, false);
 	num_chunks = 0;
 	write_offset = 0;
 	memset(data, 0, sizeof(data));
@@ -673,7 +673,7 @@
 	cs = GprsCodingScheme::CS1;
 
 	/* Block 1 */
-	gprs_rlc_data_block_info_init(&rdbi, cs);
+	gprs_rlc_data_block_info_init(&rdbi, cs, false);
 	num_chunks = 0;
 	write_offset = 0;
 	memset(data, 0, sizeof(data));
@@ -696,7 +696,7 @@
 	cs = GprsCodingScheme::CS1;
 
 	/* Block 1 */
-	gprs_rlc_data_block_info_init(&rdbi, cs);
+	gprs_rlc_data_block_info_init(&rdbi, cs, false);
 	num_chunks = 0;
 	write_offset = 0;
 	memset(data, 0, sizeof(data));
@@ -715,7 +715,7 @@
 	OSMO_ASSERT(data[0] == 0);
 
 	/* Block 2 */
-	gprs_rlc_data_block_info_init(&rdbi, cs);
+	gprs_rlc_data_block_info_init(&rdbi, cs, false);
 	num_chunks = 0;
 	write_offset = 0;
 	memset(data, 0, sizeof(data));
@@ -748,7 +748,7 @@
 	cs = GprsCodingScheme::MCS4;
 
 	/* Block 1 */
-	gprs_rlc_data_block_info_init(&rdbi, cs);
+	gprs_rlc_data_block_info_init(&rdbi, cs, false);
 	num_chunks = 0;
 	write_offset = 0;
 	memset(data, 0, sizeof(data));
@@ -800,7 +800,7 @@
 	cs = GprsCodingScheme::MCS2;
 
 	/* Block 1 */
-	gprs_rlc_data_block_info_init(&rdbi, cs);
+	gprs_rlc_data_block_info_init(&rdbi, cs, false);
 	num_chunks = 0;
 	write_offset = 0;
 	memset(data, 0, sizeof(data));
@@ -832,7 +832,7 @@
 	OSMO_ASSERT(data[1] == 0);
 
 	/* Block 2 */
-	gprs_rlc_data_block_info_init(&rdbi, cs);
+	gprs_rlc_data_block_info_init(&rdbi, cs, false);
 	num_chunks = 0;
 	write_offset = 0;
 	memset(data, 0, sizeof(data));
@@ -877,7 +877,7 @@
 	OSMO_ASSERT(data[3] == 0);
 
 	/* Block 3 */
-	gprs_rlc_data_block_info_init(&rdbi, cs);
+	gprs_rlc_data_block_info_init(&rdbi, cs, false);
 	num_chunks = 0;
 	write_offset = 0;
 	memset(data, 0, sizeof(data));
@@ -917,7 +917,7 @@
 	cs = GprsCodingScheme::MCS2;
 
 	/* Block 1 */
-	gprs_rlc_data_block_info_init(&rdbi, cs);
+	gprs_rlc_data_block_info_init(&rdbi, cs, false);
 	num_chunks = 0;
 	write_offset = 0;
 	memset(data, 0, sizeof(data));
@@ -941,7 +941,7 @@
 	cs = GprsCodingScheme::MCS2;
 
 	/* Block 1 */
-	gprs_rlc_data_block_info_init(&rdbi, cs);
+	gprs_rlc_data_block_info_init(&rdbi, cs, false);
 	num_chunks = 0;
 	write_offset = 0;
 	memset(data, 0, sizeof(data));
@@ -966,7 +966,7 @@
 	cs = GprsCodingScheme::MCS2;
 
 	/* Block 1 */
-	gprs_rlc_data_block_info_init(&rdbi, cs);
+	gprs_rlc_data_block_info_init(&rdbi, cs, false);
 	num_chunks = 0;
 	write_offset = 0;
 	memset(data, 0, sizeof(data));
@@ -1018,7 +1018,7 @@
 				block_idx++)
 			{
 				struct gprs_rlc_data_info rlc;
-				gprs_rlc_data_info_init_dl(&rlc, cs);
+				gprs_rlc_data_info_init_dl(&rlc, cs, false);
 
 				memset(bits, pattern, sizeof(bits));
 				Decoding::rlc_copy_to_aligned_buffer(
@@ -1062,12 +1062,12 @@
 	struct gprs_rlc_data_info rlc;
 
 	printf("=== start %s ===\n", __func__);
-	gprs_rlc_data_info_init_dl(&rlc, GprsCodingScheme(GprsCodingScheme::CS1));
+	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);
 
-	gprs_rlc_data_info_init_dl(&rlc, GprsCodingScheme(GprsCodingScheme::MCS1));
+	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);