aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVadim Yanitskiy <axilirator@gmail.com>2020-02-20 04:33:50 +0700
committerlaforge <laforge@osmocom.org>2020-03-02 13:33:23 +0000
commitb47e53b5fa5d7583bcf77e8825684881e6e2d194 (patch)
treef69cebfb9da6f293e4d96a312705d08e4d690206
parent5fc6e010a58409e73e19bd89b540f8c77bd8d397 (diff)
tests/rlcmac: also verify encoding of MS RA Capability
The main idea of this change is to demonstrate a weakness of the CSN.1 codec that most likely causes a unit test breakage in [1]. The problem seems to be that the transitional structures, where the CSN.1 decoder stores the results, do not contain any details about presence of the optional fields (such as M_UINT_OR_NULL). In other words, it's impossible to know whether some optional field is omitted in the encoded message (NULL), or is it just set to 0. This means that the encoder will always include all optional fields, even if they're not present in the original message. [1] Ibb4cbd3f5865415fd547e95fc24ff31df1aed4c0 Change-Id: Ic46d6e56768f516203d27d8e7a5adb77afdf32b7
-rw-r--r--src/gsm_rlcmac.cpp24
-rw-r--r--tests/rlcmac/RLCMACTest.cpp33
-rw-r--r--tests/rlcmac/RLCMACTest.err1
-rw-r--r--tests/rlcmac/RLCMACTest.ok7
4 files changed, 58 insertions, 7 deletions
diff --git a/src/gsm_rlcmac.cpp b/src/gsm_rlcmac.cpp
index 09a46e86..e60ccc71 100644
--- a/src/gsm_rlcmac.cpp
+++ b/src/gsm_rlcmac.cpp
@@ -5766,3 +5766,27 @@ int decode_gsm_ra_cap(bitvec * vector, MS_Radio_Access_capability_t *data)
}
return ret;
}
+
+/* This function is not actually used by osmo-pcu itself, and only needed for
+ * the RLCMAC unit test. Having it here is better than making the internal
+ * CSN.1 definitions (in particular, MS_Radio_Access_capability_t) non-static. */
+int encode_gsm_ra_cap(bitvec *vector, MS_Radio_Access_capability_t *data)
+{
+ unsigned writeIndex = 0;
+ csnStream_t ar;
+ int ret;
+
+ csnStreamInit(&ar, 0, vector->data_len * 8);
+
+ /* recursive csnStreamEncoder call uses LOGPC everywhere, so we need to start the log somewhere... */
+ LOGP(DCSN1, LOGL_INFO, "csnStreamEncoder (RAcap): ");
+ ret = csnStreamEncoder(&ar, CSNDESCR(MS_Radio_Access_capability_t), vector, &writeIndex, data);
+ LOGPC(DCSN1, LOGL_INFO, "\n");
+
+ if (ret > 0) {
+ LOGP(DRLCMACDATA, LOGL_NOTICE, "Got %d remaining bits unhandled by encoder at the end of bitvec\n", ret);
+ ret = 0;
+ }
+
+ return ret;
+}
diff --git a/tests/rlcmac/RLCMACTest.cpp b/tests/rlcmac/RLCMACTest.cpp
index de63fe69..b8506b17 100644
--- a/tests/rlcmac/RLCMACTest.cpp
+++ b/tests/rlcmac/RLCMACTest.cpp
@@ -214,12 +214,16 @@ void testCsnLeftAlignedVarBmpBounds(void *test_ctx)
msgb_free(m);
}
+int encode_gsm_ra_cap(bitvec * vector, MS_Radio_Access_capability_t * data);
+
void testRAcap(void *test_ctx)
{
printf("*** %s ***\n", __func__);
MS_Radio_Access_capability_t data;
memset(&data, 0, sizeof(data));
- bitvec *vector = bitvec_alloc(23, test_ctx);
+ bitvec *bv_dec = bitvec_alloc(23, test_ctx);
+ bitvec *bv_enc = bitvec_alloc(23, test_ctx);
+ unsigned int len_dec, len_enc;
int rc;
/*
MS RA capability 1
@@ -235,9 +239,10 @@ void testRAcap(void *test_ctx)
.... ..00 011. .... = GPRS multislot class: Max Rx-Slot/TDMA:2 Max Tx-Slot/TDMA:2 Max-Sum-Slot/TDMA:3 Tta:3 Ttb:2 Tra:3 Trb:1 Type:1 (3)
...0 .... = GPRS Extended Dynamic Allocation Capability: Not Implemented
*/
- bitvec_unhex(vector, "13a5146200");
+ bitvec_unhex(bv_dec, "13a5146200");
- rc = decode_gsm_ra_cap(vector, &data);
+ printf("=== Test decoding of MS RA Capability ===\n");
+ rc = decode_gsm_ra_cap(bv_dec, &data);
OSMO_ASSERT(rc == 0);
/* Make sure there's 1 value (currently fails due to failed decoding) */
@@ -247,14 +252,30 @@ void testRAcap(void *test_ctx)
printf("GPRS multislot class = %u\n", Decoding::get_ms_class_by_capability(&data));
printf("EGPRS multislot class = %u\n", Decoding::get_egprs_ms_class_by_capability(&data));
+ /* Test encoding of decoded MS RA Capability */
+ printf("=== Test encoding of MS RA Capability ===\n");
+ rc = encode_gsm_ra_cap(bv_enc, &data);
+ printf("encode_gsm_ra_cap() returns %d\n", rc);
+
+ bv_dec->cur_bit = 4;
+ len_dec = bitvec_get_uint(bv_dec, 7);
+ bv_enc->cur_bit = 4;
+ len_enc = bitvec_get_uint(bv_enc, 7);
+
+ /* NOTE: vector2 is expected to be different because there is actually no
+ * way to distinguish between NULL and 0 in MS_Radio_Access_capability_t.
+ * The difference is in length indicator: 29 bits vs 50 bits. */
+ printf("vector1 (len_ind=%u) = %s\n", len_dec, osmo_hexdump(bv_dec->data, bv_dec->data_len));
+ printf("vector2 (len_ind=%u) = %s\n", len_enc, osmo_hexdump(bv_enc->data, bv_enc->data_len));
+
/* Mangle the length indicator (set it to 21) */
unsigned int writeIndex = 4;
- rc = bitvec_write_field(vector, &writeIndex, 21, 7);
+ rc = bitvec_write_field(bv_dec, &writeIndex, 21, 7);
OSMO_ASSERT(rc == 0);
/* Make sure decoding attempt fails */
- printf("Test decoding of a malformed vector (short length indicator)\n");
- rc = decode_gsm_ra_cap(vector, &data);
+ printf("=== Test decoding of a malformed vector (short length indicator) ===\n");
+ rc = decode_gsm_ra_cap(bv_dec, &data);
printf("decode_gsm_ra_cap() returns %d\n", rc);
}
diff --git a/tests/rlcmac/RLCMACTest.err b/tests/rlcmac/RLCMACTest.err
index 52a3cc3a..a7e501e3 100644
--- a/tests/rlcmac/RLCMACTest.err
+++ b/tests/rlcmac/RLCMACTest.err
@@ -30,4 +30,5 @@ DCSN1 INFO csnStreamDecoder (type=2): PayloadType = 1 | spare = 0 | R = 0 | MESS
DCSN1 INFO csnStreamEncoder (type=2): PayloadType = 1 | spare = 0 | R = 0 | MESSAGE_TYPE = 2 | DOWNLINK_TFI = 20 | : Ack_Nack_Description | FINAL_ACK_INDICATION = 1 | STARTING_SEQUENCE_NUMBER = 1 | RECEIVED_BLOCK_BITMAP[0] = 0 | RECEIVED_BLOCK_BITMAP[1] = 0 | RECEIVED_BLOCK_BITMAP[2] = 0 | RECEIVED_BLOCK_BITMAP[3] = 0 | RECEIVED_BLOCK_BITMAP[4] = 0 | RECEIVED_BLOCK_BITMAP[5] = 0 | RECEIVED_BLOCK_BITMAP[6] = 0 | RECEIVED_BLOCK_BITMAP[7] = 1 | : End Ack_Nack_Description | Exist_Channel_Request_Description = 1 | : Channel_Request_Description | PEAK_THROUGHPUT_CLASS = 0 | RADIO_PRIORITY = 0 | RLC_MODE = 0 | LLC_PDU_TYPE = 1 | RLC_OCTET_COUNT = 18 | : End Channel_Request_Description | : Channel_Quality_Report | C_VALUE = 40 | RXQUAL = 1 | SIGN_VAR = 0 | Slot[0].Exist = 0 | Slot[1].Exist = 0 | Slot[2].Exist = 0 | Slot[3].Exist = 0 | Slot[4].Exist = 0 | Slot[5].Exist = 0 | Slot[6].Exist = 0 | Slot[7].Exist = 0 | : End Channel_Quality_Report | Exist_AdditionsR99 = 1 | : AdditionsR99 | Exist_PFI = 0 | : End AdditionsR99 | Padding = 3|43|43|43|43|43|
DCSN1 INFO csnStreamDecoder (type=8): PayloadType = 1 | spare = 0 | R = 0 | MESSAGE_TYPE = 8 | DOWNLINK_TFI = 0 | MS_OUT_OF_MEMORY = 0 | Exist_EGPRS_ChannelQualityReport = 1 | : EGPRS_ChannelQualityReport | : EGPRS_BEP_LinkQualityMeasurements | Exist_MEAN_CV_BEP_GMSK = 0 | Exist_MEAN_CV_BEP_8PSK = 1 | MEAN_BEP_8PSK = 31 | CV_BEP_8PSK = 7 | : End EGPRS_BEP_LinkQualityMeasurements | C_VALUE = 58 | : EGPRS_TimeslotLinkQualityMeasurements | Exist_BEP_MEASUREMENTS = 0 | Exist_INTERFERENCE_MEASUREMENTS = 0 | : End EGPRS_TimeslotLinkQualityMeasurements | : End EGPRS_ChannelQualityReport | Exist_ChannelRequestDescription = 1 | : ChannelRequestDescription | PEAK_THROUGHPUT_CLASS = 6 | RADIO_PRIORITY = 0 | RLC_MODE = 0 | LLC_PDU_TYPE = 1 | RLC_OCTET_COUNT = 62 | : End ChannelRequestDescription | Exist_PFI = 0 | Exist_ExtensionBits = 0 | : EGPRS_AckNack | Desc = 0 | : Desc | FINAL_ACK_INDICATION = 0 | BEGINNING_OF_WINDOW = 1 | END_OF_WINDOW = 1 | STARTING_SEQUENCE_NUMBER = 1187 | Exist_CRBB = 0 | URBB = 127 | URBB = 255 | URBB = 255 | URBB = 238 | URBB = 0 | URBB = 0 | URBB = 0 | URBB = 0 | URBB = 0 | URBB = 0 | URBB = 0 | URBB = 0 | URBB = 0 | : End Desc | : End EGPRS_AckNack | Padding =
DCSN1 INFO csnStreamDecoder (RAcap): MS_RA_capability_value { | Choice MS_RA_capability_value_Choice = 1 | u.Content length = 29 | offset = 4 | RF_Power_Capability = 1 | Exist_A5_bits = 0 | ES_IND = 1 | PS = 0 | VGCS = 0 | VBS = 0 | Exist_Multislot_capability = 1 | : Multislot_capability | Exist_HSCSD_multislot_class = 0 | Exist_GPRS_multislot_class = 1 | GPRS_multislot_class = 3 | GPRS_Extended_Dynamic_Allocation_Capability = 0 | Exist_SM = 0 | Exist_ECSD_multislot_class = 0 | Exist_EGPRS_multislot_class = 1 | EGPRS_multislot_class = 0 | EGPRS_Extended_Dynamic_Allocation_Capability = 0 | Exist_DTM_GPRS_multislot_class = 0 | : End Multislot_capability | Exist_Eight_PSK_Power_Capability = 0 | COMPACT_Interference_Measurement_Capability = 0 | Revision_Level_Indicator = NULL | UMTS_FDD_Radio_Access_Technology_Capability = NULL | UMTS_384_TDD_Radio_Access_Technology_Capability = NULL | CDMA2000_Radio_Access_Technology_Capability = NULL | UMTS_128_TDD_Radio_Access_Technology_Capability = NULL | GERAN_Feature_Package_1 = NULL | Modulation_based_multislot_class_support = NULL | GMSK_MultislotPowerProfile = NULL | EightPSK_MultislotProfile = NULL | MultipleTBF_Capability = NULL | DownlinkAdvancedReceiverPerformance = NULL | ExtendedRLC_MAC_ControlMessageSegmentionsCapability = NULL | DTM_EnhancementsCapability = NULL | PS_HandoverCapability = NULL | MS_RA_capability_value } |
+DCSN1 INFO csnStreamEncoder (RAcap): MS_RA_capability_value { | u.Content = 1 | RF_Power_Capability = 1 | Exist_A5_bits = 0 | ES_IND = 1 | PS = 0 | VGCS = 0 | VBS = 0 | Exist_Multislot_capability = 1 | : Multislot_capability | Exist_HSCSD_multislot_class = 0 | Exist_GPRS_multislot_class = 1 | GPRS_multislot_class = 3 | GPRS_Extended_Dynamic_Allocation_Capability = 0 | Exist_SM = 0 | Exist_ECSD_multislot_class = 0 | Exist_EGPRS_multislot_class = 1 | EGPRS_multislot_class = 0 | EGPRS_Extended_Dynamic_Allocation_Capability = 0 | Exist_DTM_GPRS_multislot_class = 0 | : End Multislot_capability | Exist_Eight_PSK_Power_Capability = 0 | COMPACT_Interference_Measurement_Capability = 0 | Revision_Level_Indicator = 0 | UMTS_FDD_Radio_Access_Technology_Capability = 0 | UMTS_384_TDD_Radio_Access_Technology_Capability = 0 | CDMA2000_Radio_Access_Technology_Capability = 0 | UMTS_128_TDD_Radio_Access_Technology_Capability = 0 | GERAN_Feature_Package_1 = 0 | Exist_Extended_DTM_multislot_class = 0 | Modulation_based_multislot_class_support = 0 | Exist_HighMultislotCapability = 0 | Exist_GERAN_lu_ModeCapability = 0 | GMSK_MultislotPowerProfile = 0 | EightPSK_MultislotProfile = 0 | MultipleTBF_Capability = 0 | DownlinkAdvancedReceiverPerformance = 0 | ExtendedRLC_MAC_ControlMessageSegmentionsCapability = 0 | DTM_EnhancementsCapability = 0 | Exist_DTM_GPRS_HighMultislotClass = 0 | PS_HandoverCapability = 0 | u.Content length = 50 | MS_RA_capability_value } |
DCSN1 INFO csnStreamDecoder (RAcap): MS_RA_capability_value { | Choice MS_RA_capability_value_Choice = 1 | u.Content length = 21 | offset = 4 | RF_Power_Capability = 1 | Exist_A5_bits = 0 | ES_IND = 1 | PS = 0 | VGCS = 0 | VBS = 0 | Exist_Multislot_capability = 1 | : Multislot_capability | Exist_HSCSD_multislot_class = 0 | Exist_GPRS_multislot_class = 1 | GPRS_multislot_class = 3 | GPRS_Extended_Dynamic_Allocation_Capability = 0 | Exist_SM = 0 | Exist_ECSD_multislot_class = 0 | Exist_EGPRS_multislot_class = 1 | DCSN1 ERROR csnStreamDecoder: error NEED_MORE BITS TO UNPACK (-5) at EGPRS_multislot_class (idx 31): End Multislot_capability |
diff --git a/tests/rlcmac/RLCMACTest.ok b/tests/rlcmac/RLCMACTest.ok
index 96c1bfbf..2aea5690 100644
--- a/tests/rlcmac/RLCMACTest.ok
+++ b/tests/rlcmac/RLCMACTest.ok
@@ -124,7 +124,12 @@ vector2 = 40 0a 90 20 00 00 00 00 00 00 00 30 10 01 2a 08 00 13 2b 2b 2b 2b 2b
vector1 == vector2 : TRUE
*** testCsnLeftAlignedVarBmpBounds ***
*** testRAcap ***
+=== Test decoding of MS RA Capability ===
GPRS multislot class = 3
EGPRS multislot class = 0
-Test decoding of a malformed vector (short length indicator)
+=== Test encoding of MS RA Capability ===
+encode_gsm_ra_cap() returns 0
+vector1 (len_ind=29) = 13 a5 14 62 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+vector2 (len_ind=50) = 16 45 14 62 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+=== Test decoding of a malformed vector (short length indicator) ===
decode_gsm_ra_cap() returns -5