From b3799106902f1197e51eee981fed71db28800093 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 9 Jun 2021 12:20:56 +0200 Subject: [PATCH 01/31] pdu_test: add UL-SCH unpacking test TV captured in PCAPs. --- lib/test/mac/pdu_test.cc | 113 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/lib/test/mac/pdu_test.cc b/lib/test/mac/pdu_test.cc index 4f10332f5..2cf8e2b25 100644 --- a/lib/test/mac/pdu_test.cc +++ b/lib/test/mac/pdu_test.cc @@ -1020,6 +1020,118 @@ int mac_sch_pdu_unpack_test3() return SRSRAN_SUCCESS; } +// Unpacking of UL-SCH PDU containing Padding, PHR and two SDUs for same LCID +int mac_sch_pdu_unpack_test4() +{ + static uint8_t tv[] = { + 0x3f, 0x3a, 0x23, 0x09, 0x03, 0x1e, 0xd9, 0xd0, 0x84, 0x1d, 0xc4, 0x77, 0xc7, 0x3b, 0xf0, 0x9a, 0x31, 0xc6, 0xb7, + 0x48, 0x61, 0x6e, 0xc3, 0x97, 0x48, 0xa6, 0xe3, 0xac, 0xc0, 0x75, 0x9f, 0xb2, 0xc8, 0xed, 0xb0, 0xad, 0xcc, 0xc2, + 0x0d, 0x28, 0xdd, 0xbb, 0x4b, 0x4c, 0xc5, 0xfc, 0x52, 0x40, 0xc2, 0x09, 0x89, 0x23, 0x77, 0x4c, 0xba, 0xbf, 0xf2, + 0x9d, 0x6b, 0xb2, 0x12, 0x0b, 0x64, 0xda, 0xf8, 0x14, 0x88, 0xc4, 0xd7, 0x95, 0xec, 0xb4, 0x50, 0x37, 0x00, 0x15, + 0x33, 0x52, 0x56, 0xf5, 0x5b, 0xdf, 0x18, 0xd2, 0x2b, 0xd2, 0x92, 0x1d, 0x6f, 0xfd, 0xcf, 0x82, 0x08, 0x33, 0x5c, + 0x00, 0x48, 0xe4, 0xc4, 0x1f, 0x79, 0xb0, 0xd3, 0xca, 0xe8, 0xd3, 0xdf, 0x1b, 0x25, 0x35, 0x11, 0x80, 0x14, 0x29, + 0x52, 0x3f, 0xfc, 0xe4, 0x5c, 0x6b, 0xe2, 0x2b, 0xed, 0xea, 0x5f, 0x4a, 0xeb, 0xa7, 0x2e, 0xaf, 0xc6, 0xa8, 0x60, + 0x99, 0x72, 0x48, 0x6c, 0x51, 0x63, 0x91, 0x87, 0x74, 0x11, 0x9b, 0x9e, 0x63, 0xdb, 0x9a, 0x48, 0x37, 0x05, 0x2a, + 0x63, 0xf3, 0x14, 0xc2, 0x3d, 0xff, 0x69, 0x6b, 0xaf, 0x2f, 0x13, 0x0f, 0xc8, 0x85, 0x57, 0x34, 0xd7, 0xba, 0xc5, + 0x5e, 0x2f, 0xd6, 0xf9, 0xcd, 0x39, 0xd4, 0x67, 0x81, 0x0c, 0x6c, 0xab, 0x6f, 0x5f, 0xc0, 0x31, 0x9c, 0xbf, 0x9a, + 0x08, 0x6e, 0xc9, 0x1b, 0x7d, 0x91, 0xa1, 0xd4, 0xc5, 0x78, 0x8f, 0x8a, 0xd6, 0xbe, 0x60, 0xcf, 0x8b, 0x99, 0xa4, + 0xf2, 0x1b, 0xb0, 0x5e, 0xc6, 0x1f, 0xbe, 0x86, 0x50, 0x5a, 0x46, 0xea, 0x62, 0xb4, 0xb3, 0x7e, 0x32, 0x44, 0x1f, + 0x06, 0x09, 0x97, 0x95, 0x93, 0x6d, 0x53, 0xf3, 0x3c, 0xde, 0x8c, 0xe0, 0xd0, 0xa7, 0x90, 0x2f, 0x6e, 0xaf, 0xed, + 0xf4, 0xff, 0x47, 0x3a, 0xe9, 0xaa, 0xef, 0x9c, 0x28, 0x21, 0xe0, 0x47, 0x27, 0xe9, 0xde, 0xbd, 0x7c, 0x4b, 0x10, + 0x6f, 0x87, 0xef, 0xfc, 0x68, 0xbf, 0xa3, 0xf8, 0xee, 0x11, 0xa8, 0xdb, 0x06, 0xa7, 0x23, 0x40, 0x91, 0xcd, 0x2f, + 0x2d, 0xf5, 0x50, 0x0e, 0x3c, 0x78, 0xf7, 0x1a, 0x35, 0x74, 0x65, 0x45, 0xe3, 0xec, 0x34, 0xdf, 0x54, 0xf4, 0x83, + 0x4d, 0xe2, 0x94, 0xf5, 0xbe, 0x9a, 0x9c, 0xe1, 0xdb, 0x2d, 0xae, 0x0a, 0x5b, 0xa3, 0x5b, 0x69, 0xdf, 0xd3, 0x60, + 0xf9, 0x08, 0xd4, 0x5e, 0x4d, 0xb8, 0x4a, 0x82, 0x97, 0x9f, 0x76, 0x1a, 0xec, 0x58, 0xaf, 0xe1, 0x16, 0x49, 0x7d, + 0xf7, 0x24, 0xab, 0xa5, 0x2f, 0x06, 0x48, 0x8a, 0x6f, 0x27, 0x5d, 0xcf, 0x20, 0x65, 0xa4, 0x7e, 0xb2, 0x5c, 0xc9, + 0x34, 0xf3, 0x68, 0xaa, 0x0e, 0x54, 0x03, 0xbd, 0x35, 0x19, 0x06, 0xb2, 0x11, 0x2b, 0x5d, 0xb6, 0x5a, 0x63, 0xff, + 0xe4, 0xd2, 0x26, 0x41, 0xa2, 0x47, 0xa6, 0x46, 0xc5, 0x58, 0xa2, 0x8e, 0x8d, 0x95, 0xf6, 0x37, 0xa3, 0x4a, 0x3a, + 0x60, 0x7f, 0x54, 0x67, 0x32, 0x65, 0x92, 0x8f, 0x1b, 0xec, 0xf3, 0x1a, 0xd0, 0xc5, 0x41, 0x11, 0x67, 0x88, 0xb7, + 0xad, 0x4d, 0x0f, 0x4f, 0xdc, 0x9c, 0xe5, 0xd2, 0xd4, 0x88, 0x1d, 0x0e, 0xe9, 0x9c, 0x62, 0x50, 0xce, 0xc7, 0xe2, + 0x5e, 0xe3, 0xce, 0x51, 0xfd, 0x9e, 0x16, 0x3e, 0xaf, 0x7e, 0xc6, 0x66, 0x2b, 0x14, 0x75, 0x7b, 0xf0, 0x12, 0x60, + 0xc2, 0xe6, 0xe8, 0xdf, 0xf4, 0xd1, 0x7c, 0x57, 0x21, 0x4a, 0x1e, 0x03, 0xa8, 0x01, 0xd1, 0xf9, 0xff, 0x6f, 0x10, + 0x3d, 0x1e, 0x8e, 0x04, 0x84, 0xb9, 0x18, 0xfa, 0x34, 0x08, 0x0c, 0x94, 0xca, 0xf2, 0x7d, 0xaa, 0xe6, 0x4e, 0x26, + 0x3d, 0x70, 0x70, 0x5c, 0x73, 0x19, 0x5d, 0x45, 0x12, 0x5c, 0xb4, 0x22, 0x9a, 0xd3, 0xb0, 0x9e, 0x57, 0x6a, 0xb6, + 0x51, 0x9e, 0xbe, 0x5d, 0x33, 0x88, 0x4f, 0xb0, 0x32, 0x36, 0xfe, 0x58, 0x73, 0x6e, 0xc9, 0xcf, 0xe2, 0xe2, 0x2d, + 0x27, 0xf4, 0x89, 0xdb, 0x17, 0x23, 0xae, 0xc7, 0xc1, 0x06, 0x31, 0x77, 0x57, 0xd0, 0x35, 0xb5, 0x03, 0xbe, 0x04, + 0xb3, 0xf0, 0x3a, 0xb1, 0x49, 0xae, 0x20, 0x12, 0x7d, 0x02, 0xf4, 0xaa, 0x29, 0xe8, 0x34, 0x04, 0xff, 0x57, 0xb3, + 0xc7, 0x19, 0xb9, 0xf8, 0x90, 0x10, 0xc8, 0xc6, 0xc5, 0xcb, 0x84, 0xca, 0x7e, 0x74, 0x04, 0x30, 0xbd, 0xb2, 0x50, + 0xcf, 0x30, 0x52, 0xc3, 0xda, 0x7b, 0xac, 0x0e, 0x7f, 0xab, 0x66, 0x32, 0x72, 0x7f, 0xeb, 0x6b, 0x0f, 0xfc, 0x33, + 0xd5, 0xc1, 0xff, 0x59, 0x8b, 0x7d, 0xce, 0x90, 0xad, 0x8b, 0x42, 0xfd, 0x5b, 0x72, 0x4f, 0x1e, 0x4d, 0xca, 0xca, + 0x5b, 0x4a, 0x76, 0xc1, 0x7c, 0xe8, 0x40, 0x68, 0x53, 0x50, 0x64, 0x87, 0x25, 0x25, 0x86, 0x7f, 0xb1, 0x03, 0x4d, + 0x41, 0xb1, 0xd8, 0x83, 0xae, 0x33, 0xf6, 0xfe, 0x52, 0x43, 0xc8, 0x1c, 0x9e, 0x12, 0x92, 0x60, 0x8f, 0x7b, 0xa0, + 0xf7, 0xce, 0xf0, 0x5b, 0x55, 0x16, 0x80, 0xdb, 0x95, 0x31, 0xdf, 0xe2, 0x72, 0x90, 0xba, 0xf6, 0x3e, 0xee, 0xec, + 0x3c, 0x40, 0x2f, 0x05, 0x5c, 0xcd, 0x17, 0xef, 0x2d, 0xa6, 0x6a, 0xce, 0x9d, 0x38, 0xbe, 0xf8, 0x8e, 0xd4, 0x79, + 0x69, 0x69, 0xaa, 0x48, 0x4b, 0x1d, 0xd8, 0x06, 0x13, 0x17, 0xf4, 0xff, 0x53, 0x34, 0x2e, 0x58, 0x90, 0xfb, 0x70, + 0x7f, 0x29, 0x16, 0xe9, 0xf7, 0xb4, 0x22, 0xb5, 0xac, 0xb0, 0x8a, 0x25, 0x19, 0xf3, 0xd0, 0x62, 0x3f, 0xed, 0x3a, + 0x45, 0x00, 0x51, 0x39, 0xff, 0xa5, 0x6d, 0x2d, 0xfd, 0xfd, 0x28, 0x6d, 0x7d, 0x51, 0x84, 0x66, 0x48, 0x38, 0x88, + 0xfe, 0xe4, 0x38, 0x88, 0x0a, 0x52, 0x7b, 0xda, 0xb4, 0xba, 0xc7, 0xee, 0xff, 0xc7, 0x40, 0x38, 0xc6, 0xe5, 0xa5, + 0xf3, 0xe2, 0xa3, 0x1b, 0x50, 0x20, 0x6d, 0xd4, 0x86, 0xb5, 0x0c, 0x0f, 0xb3, 0xf0, 0x47, 0x3b, 0xfa, 0x99, 0xb7, + 0xd4, 0x4d, 0x71, 0x9b, 0x3c, 0x71, 0x62, 0x7c, 0xa9, 0x28, 0x61, 0x4f, 0x1b, 0x43, 0xf2, 0x37, 0x93, 0x12, 0xa4, + 0x67, 0x98, 0x59, 0x73, 0xa7, 0x0d, 0x64, 0xef, 0x48, 0x5e, 0x88, 0xff, 0x33, 0xd6, 0x71, 0xce, 0x12, 0xe2, 0x31, + 0x8e, 0x8b, 0x59, 0xef, 0xda, 0x75, 0x32, 0xcc, 0xac, 0xc6, 0xde, 0x50, 0x2d, 0x77, 0xa9, 0xa1, 0x1e, 0xb6, 0x05, + 0x0d, 0xff, 0x63, 0x96, 0xfe, 0x96, 0x6c, 0x6f, 0x65, 0x7e, 0x51, 0x96, 0x0c, 0xdd, 0xef, 0xfb, 0xb7, 0x64, 0x2d, + 0x84, 0x10, 0xf3, 0x62, 0x60, 0x21, 0xd9, 0x0a, 0xc2, 0xf8, 0xc0, 0xc7, 0x05, 0xbf, 0x2a, 0x9b, 0xbe, 0xc1, 0x07, + 0x2d, 0x26, 0x85, 0x7f, 0xbc, 0x91, 0x5c, 0xab, 0x8c, 0x13, 0x10, 0xba, 0x97, 0x20, 0xad, 0xfa, 0x81, 0xce, 0xd3, + 0x8b, 0x90, 0xcb, 0x4b, 0x57, 0xd1, 0x0b, 0x82, 0x6c, 0xc9, 0x43, 0x74, 0xf6, 0x69, 0xf9, 0x75, 0x25, 0x8b, 0xd1, + 0xd0, 0x17, 0xe5, 0xe0, 0xd1, 0x7c, 0x01, 0x7f, 0x76, 0x82, 0x4d, 0x4a, 0x0d, 0xde, 0x15, 0x58, 0x35, 0xe6, 0x63, + 0xb7, 0x53, 0x2c, 0xfa, 0xc7, 0x23, 0x63, 0xc0, 0x98, 0x88, 0x4b, 0x6a, 0x59, 0x63, 0x4f, 0x39, 0x34, 0xcb, 0x3a, + 0xb3, 0x42, 0xbc, 0x01, 0x8c, 0xc9, 0xdf, 0xa1, 0x22, 0x14, 0x88, 0x85, 0xcc, 0xdb, 0xb2, 0xc6, 0xa2, 0xd5, 0x2a, + 0x62, 0x6d, 0xb2, 0xae, 0xd7, 0x0b, 0x11, 0x26, 0x45, 0x45, 0xf2, 0x7f, 0xf9, 0x34, 0x3c, 0xfa, 0xc0, 0x05, 0xd9, + 0x61, 0x27, 0xed, 0xe9, 0xad, 0xb9, 0xc4, 0x5f, 0x80, 0x66, 0x34, 0xaa, 0xc9, 0xa1, 0x5c, 0x77, 0x79, 0x68, 0x88, + 0x9f, 0xad, 0xcd, 0x91, 0x2c, 0xc6, 0xc5, 0x68, 0xc0, 0x85, 0x6e, 0x99, 0xe7, 0x95, 0x87, 0xd0, 0x42, 0x40, 0x95, + 0xa1, 0xc0, 0xfb, 0xd5, 0x6a, 0xc4, 0x77, 0xc7, 0x3b, 0xf0, 0x2f, 0xc3, 0x8f, 0xdc, 0x91, 0x21, 0x08, 0x57}; + + uint8_t* sdu1 = &tv[6]; + uint32_t sdu1_len = 9; + + uint8_t* sdu2 = &tv[15]; + uint32_t sdu2_len = 1048; + + srsran::sch_pdu pdu(5, srslog::fetch_basic_logger("MAC")); + pdu.init_rx(sizeof(tv), true); + pdu.parse_packet(tv); + + TESTASSERT(pdu.nof_subh() == 4); + + // Padding + TESTASSERT(pdu.next()); + TESTASSERT(pdu.get()->is_sdu() == false); + TESTASSERT(pdu.get()->ul_sch_ce_type() == srsran::ul_sch_lcid::PADDING); + + // PHR + TESTASSERT(pdu.next()); + TESTASSERT(pdu.get()->is_sdu() == false); + TESTASSERT(pdu.get()->ul_sch_ce_type() == srsran::ul_sch_lcid::PHR_REPORT); + TESTASSERT(pdu.get()->get_phr() == 7); + + // SDU1 + TESTASSERT(pdu.next()); + TESTASSERT(pdu.get()->is_sdu() == true); + TESTASSERT(pdu.get()->get_sdu_lcid() == 3); + TESTASSERT(pdu.get()->get_payload_size() == sdu1_len); + TESTASSERT(memcmp(sdu1, pdu.get()->get_sdu_ptr(), sdu1_len) == 0); + + // SDU2 + TESTASSERT(pdu.next()); + TESTASSERT(pdu.get()->is_sdu() == true); + TESTASSERT(pdu.get()->get_sdu_lcid() == 3); + TESTASSERT(pdu.get()->get_payload_size() == sdu2_len); + TESTASSERT(memcmp(sdu2, pdu.get()->get_sdu_ptr(), sdu2_len) == 0); + + // end of PDU + TESTASSERT(pdu.next() == false); + + fmt::memory_buffer buffer; + pdu.to_string(buffer); + std::cout << fmt::to_string(buffer) << std::endl; + +#if HAVE_PCAP + pcap_handle->write_ul_crnti(tv, sizeof(tv), 0x1001, true, 1, 0); +#endif + + return SRSRAN_SUCCESS; +} + int mac_slsch_pdu_unpack_test1() { // SL-SCH PDU captures from UXM 5G CV2X @@ -1076,6 +1188,7 @@ int main(int argc, char** argv) TESTASSERT(mac_sch_pdu_unpack_test1() == SRSRAN_SUCCESS); TESTASSERT(mac_sch_pdu_unpack_test2() == SRSRAN_SUCCESS); TESTASSERT(mac_sch_pdu_unpack_test3() == SRSRAN_SUCCESS); + TESTASSERT(mac_sch_pdu_unpack_test4() == SRSRAN_SUCCESS); TESTASSERT(mac_slsch_pdu_unpack_test1() == SRSRAN_SUCCESS); From 46265c58293d2da60002309ffc8988cccdfbe550 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 9 Jun 2021 13:01:41 +0200 Subject: [PATCH 02/31] rlc_am_data_test: add data PDU unpack test TV captured in PCAP --- lib/test/upper/rlc_am_data_test.cc | 82 ++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/lib/test/upper/rlc_am_data_test.cc b/lib/test/upper/rlc_am_data_test.cc index a5c706e67..fc40c1002 100644 --- a/lib/test/upper/rlc_am_data_test.cc +++ b/lib/test/upper/rlc_am_data_test.cc @@ -141,6 +141,87 @@ int test4() return SRSRAN_SUCCESS; } +int test5() +{ + uint8_t tv[] = { + 0x9a, 0x31, 0xc6, 0xb7, 0x48, 0x61, 0x6e, 0xc3, 0x97, 0x48, 0xa6, 0xe3, 0xac, 0xc0, 0x75, 0x9f, 0xb2, 0xc8, 0xed, + 0xb0, 0xad, 0xcc, 0xc2, 0x0d, 0x28, 0xdd, 0xbb, 0x4b, 0x4c, 0xc5, 0xfc, 0x52, 0x40, 0xc2, 0x09, 0x89, 0x23, 0x77, + 0x4c, 0xba, 0xbf, 0xf2, 0x9d, 0x6b, 0xb2, 0x12, 0x0b, 0x64, 0xda, 0xf8, 0x14, 0x88, 0xc4, 0xd7, 0x95, 0xec, 0xb4, + 0x50, 0x37, 0x00, 0x15, 0x33, 0x52, 0x56, 0xf5, 0x5b, 0xdf, 0x18, 0xd2, 0x2b, 0xd2, 0x92, 0x1d, 0x6f, 0xfd, 0xcf, + 0x82, 0x08, 0x33, 0x5c, 0x00, 0x48, 0xe4, 0xc4, 0x1f, 0x79, 0xb0, 0xd3, 0xca, 0xe8, 0xd3, 0xdf, 0x1b, 0x25, 0x35, + 0x11, 0x80, 0x14, 0x29, 0x52, 0x3f, 0xfc, 0xe4, 0x5c, 0x6b, 0xe2, 0x2b, 0xed, 0xea, 0x5f, 0x4a, 0xeb, 0xa7, 0x2e, + 0xaf, 0xc6, 0xa8, 0x60, 0x99, 0x72, 0x48, 0x6c, 0x51, 0x63, 0x91, 0x87, 0x74, 0x11, 0x9b, 0x9e, 0x63, 0xdb, 0x9a, + 0x48, 0x37, 0x05, 0x2a, 0x63, 0xf3, 0x14, 0xc2, 0x3d, 0xff, 0x69, 0x6b, 0xaf, 0x2f, 0x13, 0x0f, 0xc8, 0x85, 0x57, + 0x34, 0xd7, 0xba, 0xc5, 0x5e, 0x2f, 0xd6, 0xf9, 0xcd, 0x39, 0xd4, 0x67, 0x81, 0x0c, 0x6c, 0xab, 0x6f, 0x5f, 0xc0, + 0x31, 0x9c, 0xbf, 0x9a, 0x08, 0x6e, 0xc9, 0x1b, 0x7d, 0x91, 0xa1, 0xd4, 0xc5, 0x78, 0x8f, 0x8a, 0xd6, 0xbe, 0x60, + 0xcf, 0x8b, 0x99, 0xa4, 0xf2, 0x1b, 0xb0, 0x5e, 0xc6, 0x1f, 0xbe, 0x86, 0x50, 0x5a, 0x46, 0xea, 0x62, 0xb4, 0xb3, + 0x7e, 0x32, 0x44, 0x1f, 0x06, 0x09, 0x97, 0x95, 0x93, 0x6d, 0x53, 0xf3, 0x3c, 0xde, 0x8c, 0xe0, 0xd0, 0xa7, 0x90, + 0x2f, 0x6e, 0xaf, 0xed, 0xf4, 0xff, 0x47, 0x3a, 0xe9, 0xaa, 0xef, 0x9c, 0x28, 0x21, 0xe0, 0x47, 0x27, 0xe9, 0xde, + 0xbd, 0x7c, 0x4b, 0x10, 0x6f, 0x87, 0xef, 0xfc, 0x68, 0xbf, 0xa3, 0xf8, 0xee, 0x11, 0xa8, 0xdb, 0x06, 0xa7, 0x23, + 0x40, 0x91, 0xcd, 0x2f, 0x2d, 0xf5, 0x50, 0x0e, 0x3c, 0x78, 0xf7, 0x1a, 0x35, 0x74, 0x65, 0x45, 0xe3, 0xec, 0x34, + 0xdf, 0x54, 0xf4, 0x83, 0x4d, 0xe2, 0x94, 0xf5, 0xbe, 0x9a, 0x9c, 0xe1, 0xdb, 0x2d, 0xae, 0x0a, 0x5b, 0xa3, 0x5b, + 0x69, 0xdf, 0xd3, 0x60, 0xf9, 0x08, 0xd4, 0x5e, 0x4d, 0xb8, 0x4a, 0x82, 0x97, 0x9f, 0x76, 0x1a, 0xec, 0x58, 0xaf, + 0xe1, 0x16, 0x49, 0x7d, 0xf7, 0x24, 0xab, 0xa5, 0x2f, 0x06, 0x48, 0x8a, 0x6f, 0x27, 0x5d, 0xcf, 0x20, 0x65, 0xa4, + 0x7e, 0xb2, 0x5c, 0xc9, 0x34, 0xf3, 0x68, 0xaa, 0x0e, 0x54, 0x03, 0xbd, 0x35, 0x19, 0x06, 0xb2, 0x11, 0x2b, 0x5d, + 0xb6, 0x5a, 0x63, 0xff, 0xe4, 0xd2, 0x26, 0x41, 0xa2, 0x47, 0xa6, 0x46, 0xc5, 0x58, 0xa2, 0x8e, 0x8d, 0x95, 0xf6, + 0x37, 0xa3, 0x4a, 0x3a, 0x60, 0x7f, 0x54, 0x67, 0x32, 0x65, 0x92, 0x8f, 0x1b, 0xec, 0xf3, 0x1a, 0xd0, 0xc5, 0x41, + 0x11, 0x67, 0x88, 0xb7, 0xad, 0x4d, 0x0f, 0x4f, 0xdc, 0x9c, 0xe5, 0xd2, 0xd4, 0x88, 0x1d, 0x0e, 0xe9, 0x9c, 0x62, + 0x50, 0xce, 0xc7, 0xe2, 0x5e, 0xe3, 0xce, 0x51, 0xfd, 0x9e, 0x16, 0x3e, 0xaf, 0x7e, 0xc6, 0x66, 0x2b, 0x14, 0x75, + 0x7b, 0xf0, 0x12, 0x60, 0xc2, 0xe6, 0xe8, 0xdf, 0xf4, 0xd1, 0x7c, 0x57, 0x21, 0x4a, 0x1e, 0x03, 0xa8, 0x01, 0xd1, + 0xf9, 0xff, 0x6f, 0x10, 0x3d, 0x1e, 0x8e, 0x04, 0x84, 0xb9, 0x18, 0xfa, 0x34, 0x08, 0x0c, 0x94, 0xca, 0xf2, 0x7d, + 0xaa, 0xe6, 0x4e, 0x26, 0x3d, 0x70, 0x70, 0x5c, 0x73, 0x19, 0x5d, 0x45, 0x12, 0x5c, 0xb4, 0x22, 0x9a, 0xd3, 0xb0, + 0x9e, 0x57, 0x6a, 0xb6, 0x51, 0x9e, 0xbe, 0x5d, 0x33, 0x88, 0x4f, 0xb0, 0x32, 0x36, 0xfe, 0x58, 0x73, 0x6e, 0xc9, + 0xcf, 0xe2, 0xe2, 0x2d, 0x27, 0xf4, 0x89, 0xdb, 0x17, 0x23, 0xae, 0xc7, 0xc1, 0x06, 0x31, 0x77, 0x57, 0xd0, 0x35, + 0xb5, 0x03, 0xbe, 0x04, 0xb3, 0xf0, 0x3a, 0xb1, 0x49, 0xae, 0x20, 0x12, 0x7d, 0x02, 0xf4, 0xaa, 0x29, 0xe8, 0x34, + 0x04, 0xff, 0x57, 0xb3, 0xc7, 0x19, 0xb9, 0xf8, 0x90, 0x10, 0xc8, 0xc6, 0xc5, 0xcb, 0x84, 0xca, 0x7e, 0x74, 0x04, + 0x30, 0xbd, 0xb2, 0x50, 0xcf, 0x30, 0x52, 0xc3, 0xda, 0x7b, 0xac, 0x0e, 0x7f, 0xab, 0x66, 0x32, 0x72, 0x7f, 0xeb, + 0x6b, 0x0f, 0xfc, 0x33, 0xd5, 0xc1, 0xff, 0x59, 0x8b, 0x7d, 0xce, 0x90, 0xad, 0x8b, 0x42, 0xfd, 0x5b, 0x72, 0x4f, + 0x1e, 0x4d, 0xca, 0xca, 0x5b, 0x4a, 0x76, 0xc1, 0x7c, 0xe8, 0x40, 0x68, 0x53, 0x50, 0x64, 0x87, 0x25, 0x25, 0x86, + 0x7f, 0xb1, 0x03, 0x4d, 0x41, 0xb1, 0xd8, 0x83, 0xae, 0x33, 0xf6, 0xfe, 0x52, 0x43, 0xc8, 0x1c, 0x9e, 0x12, 0x92, + 0x60, 0x8f, 0x7b, 0xa0, 0xf7, 0xce, 0xf0, 0x5b, 0x55, 0x16, 0x80, 0xdb, 0x95, 0x31, 0xdf, 0xe2, 0x72, 0x90, 0xba, + 0xf6, 0x3e, 0xee, 0xec, 0x3c, 0x40, 0x2f, 0x05, 0x5c, 0xcd, 0x17, 0xef, 0x2d, 0xa6, 0x6a, 0xce, 0x9d, 0x38, 0xbe, + 0xf8, 0x8e, 0xd4, 0x79, 0x69, 0x69, 0xaa, 0x48, 0x4b, 0x1d, 0xd8, 0x06, 0x13, 0x17, 0xf4, 0xff, 0x53, 0x34, 0x2e, + 0x58, 0x90, 0xfb, 0x70, 0x7f, 0x29, 0x16, 0xe9, 0xf7, 0xb4, 0x22, 0xb5, 0xac, 0xb0, 0x8a, 0x25, 0x19, 0xf3, 0xd0, + 0x62, 0x3f, 0xed, 0x3a, 0x45, 0x00, 0x51, 0x39, 0xff, 0xa5, 0x6d, 0x2d, 0xfd, 0xfd, 0x28, 0x6d, 0x7d, 0x51, 0x84, + 0x66, 0x48, 0x38, 0x88, 0xfe, 0xe4, 0x38, 0x88, 0x0a, 0x52, 0x7b, 0xda, 0xb4, 0xba, 0xc7, 0xee, 0xff, 0xc7, 0x40, + 0x38, 0xc6, 0xe5, 0xa5, 0xf3, 0xe2, 0xa3, 0x1b, 0x50, 0x20, 0x6d, 0xd4, 0x86, 0xb5, 0x0c, 0x0f, 0xb3, 0xf0, 0x47, + 0x3b, 0xfa, 0x99, 0xb7, 0xd4, 0x4d, 0x71, 0x9b, 0x3c, 0x71, 0x62, 0x7c, 0xa9, 0x28, 0x61, 0x4f, 0x1b, 0x43, 0xf2, + 0x37, 0x93, 0x12, 0xa4, 0x67, 0x98, 0x59, 0x73, 0xa7, 0x0d, 0x64, 0xef, 0x48, 0x5e, 0x88, 0xff, 0x33, 0xd6, 0x71, + 0xce, 0x12, 0xe2, 0x31, 0x8e, 0x8b, 0x59, 0xef, 0xda, 0x75, 0x32, 0xcc, 0xac, 0xc6, 0xde, 0x50, 0x2d, 0x77, 0xa9, + 0xa1, 0x1e, 0xb6, 0x05, 0x0d, 0xff, 0x63, 0x96, 0xfe, 0x96, 0x6c, 0x6f, 0x65, 0x7e, 0x51, 0x96, 0x0c, 0xdd, 0xef, + 0xfb, 0xb7, 0x64, 0x2d, 0x84, 0x10, 0xf3, 0x62, 0x60, 0x21, 0xd9, 0x0a, 0xc2, 0xf8, 0xc0, 0xc7, 0x05, 0xbf, 0x2a, + 0x9b, 0xbe, 0xc1, 0x07, 0x2d, 0x26, 0x85, 0x7f, 0xbc, 0x91, 0x5c, 0xab, 0x8c, 0x13, 0x10, 0xba, 0x97, 0x20, 0xad, + 0xfa, 0x81, 0xce, 0xd3, 0x8b, 0x90, 0xcb, 0x4b, 0x57, 0xd1, 0x0b, 0x82, 0x6c, 0xc9, 0x43, 0x74, 0xf6, 0x69, 0xf9, + 0x75, 0x25, 0x8b, 0xd1, 0xd0, 0x17, 0xe5, 0xe0, 0xd1, 0x7c, 0x01, 0x7f, 0x76, 0x82, 0x4d, 0x4a, 0x0d, 0xde, 0x15, + 0x58, 0x35, 0xe6, 0x63, 0xb7, 0x53, 0x2c, 0xfa, 0xc7, 0x23, 0x63, 0xc0, 0x98, 0x88, 0x4b, 0x6a, 0x59, 0x63, 0x4f, + 0x39, 0x34, 0xcb, 0x3a, 0xb3, 0x42, 0xbc, 0x01, 0x8c, 0xc9, 0xdf, 0xa1, 0x22, 0x14, 0x88, 0x85, 0xcc, 0xdb, 0xb2, + 0xc6, 0xa2, 0xd5, 0x2a, 0x62, 0x6d, 0xb2, 0xae, 0xd7, 0x0b, 0x11, 0x26, 0x45, 0x45, 0xf2, 0x7f, 0xf9, 0x34, 0x3c, + 0xfa, 0xc0, 0x05, 0xd9, 0x61, 0x27, 0xed, 0xe9, 0xad, 0xb9, 0xc4, 0x5f, 0x80, 0x66, 0x34, 0xaa, 0xc9, 0xa1, 0x5c, + 0x77, 0x79, 0x68, 0x88, 0x9f, 0xad, 0xcd, 0x91, 0x2c, 0xc6, 0xc5, 0x68, 0xc0, 0x85, 0x6e, 0x99, 0xe7, 0x95, 0x87, + 0xd0, 0x42, 0x40, 0x95, 0xa1, 0xc0, 0xfb, 0xd5, 0x6a, 0xc4, 0x77, 0xc7, 0x3b, 0xf0, 0x2f, 0xc3, 0x8f, 0xdc, 0x91, + 0x21, 0x08, 0x57}; + + srsran::rlc_amd_pdu_header_t h; + srsran::byte_buffer_t b1; + + memcpy(b1.msg, tv, sizeof(tv)); + b1.N_bytes = sizeof(tv); + uint32_t nof_payload_bytes = sizeof(tv); + rlc_am_read_data_pdu_header(&b1.msg, &nof_payload_bytes, &h); + + TESTASSERT(nof_payload_bytes == 1046); + TESTASSERT(RLC_DC_FIELD_DATA_PDU == h.dc); + TESTASSERT(RLC_FI_FIELD_NOT_START_OR_END_ALIGNED == h.fi); + TESTASSERT(0 == h.N_li); + TESTASSERT(0 == h.lsf); + TESTASSERT(0 == h.p); + TESTASSERT(0 == h.rf); + TESTASSERT(0 == h.so); + TESTASSERT(561 == h.sn); + + return SRSRAN_SUCCESS; +} + int main(int argc, char** argv) { srslog::init(); @@ -149,6 +230,7 @@ int main(int argc, char** argv) TESTASSERT(test2() == SRSRAN_SUCCESS); TESTASSERT(test3() == SRSRAN_SUCCESS); TESTASSERT(test4() == SRSRAN_SUCCESS); + TESTASSERT(test5() == SRSRAN_SUCCESS); return SRSRAN_SUCCESS; } From 878142843e27981b2fe063e7329f4389811008ad Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 8 Jun 2021 15:40:07 +0200 Subject: [PATCH 03/31] rlc_am_lte: add further sanity check when creating status PDU the test verifies that the ACK_SN of a status PDU falls inside the rx_window of the receiver. If not, than the RLC state has been corrupted and the status PDU is likely invalid. --- lib/include/srsran/upper/rlc_am_lte.h | 2 +- lib/src/upper/rlc_am_lte.cc | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/include/srsran/upper/rlc_am_lte.h b/lib/include/srsran/upper/rlc_am_lte.h index e3f316b07..9d1f88d36 100644 --- a/lib/include/srsran/upper/rlc_am_lte.h +++ b/lib/include/srsran/upper/rlc_am_lte.h @@ -574,7 +574,7 @@ int rlc_am_write_status_pdu(rlc_status_pdu_t* status, uint8_t* payload); uint32_t rlc_am_packed_length(rlc_amd_pdu_header_t* header); uint32_t rlc_am_packed_length(rlc_status_pdu_t* status); uint32_t rlc_am_packed_length(rlc_amd_retx_t retx); -bool rlc_am_is_valid_status_pdu(const rlc_status_pdu_t& status); +bool rlc_am_is_valid_status_pdu(const rlc_status_pdu_t& status, uint32_t rx_win_min = 0); bool rlc_am_is_pdu_segment(uint8_t* payload); std::string rlc_am_undelivered_sdu_info_to_string(const std::map& info_queue); void log_rlc_amd_pdu_header_to_string(srslog::log_channel& log_ch, const rlc_amd_pdu_header_t& header); diff --git a/lib/src/upper/rlc_am_lte.cc b/lib/src/upper/rlc_am_lte.cc index 45079e826..6d17307d5 100644 --- a/lib/src/upper/rlc_am_lte.cc +++ b/lib/src/upper/rlc_am_lte.cc @@ -1924,9 +1924,9 @@ int rlc_am_lte::rlc_am_lte_rx::get_status_pdu(rlc_status_pdu_t* status, const ui logger.debug("Removing last NACK SN=%d", status->nacks[status->N_nack].nack_sn); status->N_nack--; // make sure we don't have the current ACK_SN in the NACK list - if (rlc_am_is_valid_status_pdu(*status) == false) { + if (rlc_am_is_valid_status_pdu(*status, vr_r) == false) { // No space to send any NACKs, play safe and just ack lower edge - logger.debug("Resetting ACK_SN and N_nack to initial state"); + logger.warning("Resetting ACK_SN and N_nack to initial state"); status->ack_sn = vr_r; status->N_nack = 0; } @@ -2396,8 +2396,13 @@ int rlc_am_write_status_pdu(rlc_status_pdu_t* status, uint8_t* payload) return tmp.N_bits / 8; } -bool rlc_am_is_valid_status_pdu(const rlc_status_pdu_t& status) +bool rlc_am_is_valid_status_pdu(const rlc_status_pdu_t& status, uint32_t rx_win_min) { + // check if ACK_SN is inside Rx window + if ((MOD + status.ack_sn - rx_win_min) % MOD > RLC_AM_WINDOW_SIZE) { + return false; + } + for (uint32_t i = 0; i < status.N_nack; ++i) { // NACK can't be larger than ACK if ((MOD + status.ack_sn - status.nacks[i].nack_sn) % MOD > RLC_AM_WINDOW_SIZE) { From d51ee722f668a14e5831210250c9a38a590ea8fb Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 8 Jun 2021 15:41:48 +0200 Subject: [PATCH 04/31] rlc_am_test: add unit test for ACK_SN is outside rx window the test uses a malformed status PDU from a PCAP and makes sure the RLC receiver detects such a PDU and raises a warning --- lib/test/upper/rlc_am_control_test.cc | 40 +++++++++++++++++++++++++++ lib/test/upper/rlc_am_test.cc | 1 + 2 files changed, 41 insertions(+) diff --git a/lib/test/upper/rlc_am_control_test.cc b/lib/test/upper/rlc_am_control_test.cc index 9ebc56c31..38ea7481f 100644 --- a/lib/test/upper/rlc_am_control_test.cc +++ b/lib/test/upper/rlc_am_control_test.cc @@ -79,6 +79,45 @@ int malformed_status_pdu_test() return SRSRAN_SUCCESS; } +// Malformed PDU captured in field-test +// 22:48:03.509077 [RLC ] [I] DRB1 Tx status PDU - ACK_SN = 205, N_nack = 98, NACK_SN = +// [752][986][109][110][111][112][113][114][115][116][117][118][119][120][121][122][123][124][125][126][127][128][129] +int malformed_status_pdu_test2() +{ + uint32_t vr_a = 293; + + // Construct a status PDU that ACKs SN 205, which is outside the rx window + srsran::rlc_status_pdu_t status_pdu = {}; + status_pdu.ack_sn = 205; + status_pdu.N_nack = 2; + status_pdu.nacks[0].nack_sn = 752; + status_pdu.nacks[1].nack_sn = 986; + TESTASSERT(rlc_am_is_valid_status_pdu(status_pdu, vr_a) == false); + + // 1 SN after upper edge of Rx window will fail + status_pdu.ack_sn = 806; + TESTASSERT(rlc_am_is_valid_status_pdu(status_pdu, vr_a) == false); + + // The exact upper edge of Rx window should work + status_pdu.ack_sn = 805; + status_pdu.N_nack = 0; + TESTASSERT(rlc_am_is_valid_status_pdu(status_pdu, vr_a) == true); + + // ACK_SN is again outside of rx_window + vr_a = 0; + status_pdu.ack_sn = 742; + status_pdu.N_nack = 0; + TESTASSERT(rlc_am_is_valid_status_pdu(status_pdu, vr_a) == false); + + // ACK_SN is well within rx window + vr_a = 300; + status_pdu.ack_sn = 742; + status_pdu.N_nack = 0; + TESTASSERT(rlc_am_is_valid_status_pdu(status_pdu, vr_a) == true); + + return SRSRAN_SUCCESS; +} + int main(int argc, char** argv) { srslog::init(); @@ -86,6 +125,7 @@ int main(int argc, char** argv) TESTASSERT(simple_status_pdu_test1() == SRSRAN_SUCCESS); TESTASSERT(status_pdu_with_nacks_test1() == SRSRAN_SUCCESS); TESTASSERT(malformed_status_pdu_test() == SRSRAN_SUCCESS); + TESTASSERT(malformed_status_pdu_test2() == SRSRAN_SUCCESS); return SRSRAN_SUCCESS; } diff --git a/lib/test/upper/rlc_am_test.cc b/lib/test/upper/rlc_am_test.cc index d86502df5..e981fc546 100644 --- a/lib/test/upper/rlc_am_test.cc +++ b/lib/test/upper/rlc_am_test.cc @@ -190,6 +190,7 @@ int basic_test() rlc_status_pdu_t status_check = {}; rlc_am_read_status_pdu(status_buf.msg, status_buf.N_bytes, &status_check); TESTASSERT(status_check.ack_sn == 5); // 5 is the last SN that was not received. + TESTASSERT(rlc_am_is_valid_status_pdu(status_check)); // Write status PDU to RLC1 rlc1.write_pdu(status_buf.msg, status_buf.N_bytes); From b862bbc2e68641a5c5a87a8dd31ff8ed18362af4 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 7 Jun 2021 11:55:10 +0200 Subject: [PATCH 05/31] rlc_am_lte: add missing mutex to get_status getter fixws race detected with TSAN --- lib/src/upper/rlc_am_lte.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/src/upper/rlc_am_lte.cc b/lib/src/upper/rlc_am_lte.cc index 6d17307d5..25f10284d 100644 --- a/lib/src/upper/rlc_am_lte.cc +++ b/lib/src/upper/rlc_am_lte.cc @@ -1829,6 +1829,7 @@ void rlc_am_lte::rlc_am_lte_rx::reset_status() bool rlc_am_lte::rlc_am_lte_rx::get_do_status() { + std::lock_guard lock(mutex); return do_status; } From 69b7a7eb1945b8c16cfe3fce135a7291159e2ab6 Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 9 Jun 2021 15:14:18 +0100 Subject: [PATCH 06/31] bugfix,srsenb: the lcids beloging to SRB1 and SRB2 were not being reactivated correctly during intra-eNB handover --- srsenb/src/stack/rrc/mac_controller.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsenb/src/stack/rrc/mac_controller.cc b/srsenb/src/stack/rrc/mac_controller.cc index 247d8052f..e42414597 100644 --- a/srsenb/src/stack/rrc/mac_controller.cc +++ b/srsenb/src/stack/rrc/mac_controller.cc @@ -283,7 +283,7 @@ void mac_controller::handle_intraenb_ho_cmd(const asn1::rrc::rrc_conn_recfg_r8_i // Stop any SRB UL (including SRs) for (uint32_t i = srb_to_lcid(lte_srb::srb1); i <= srb_to_lcid(lte_srb::srb2); ++i) { - next_sched_ue_cfg.ue_bearers[i].direction = sched_interface::ue_bearer_cfg_t::DL; + current_sched_ue_cfg.ue_bearers[i].direction = sched_interface::ue_bearer_cfg_t::DL; } update_mac(mac_controller::config_tx); From 99960c72fa99d502c7700448fc042d44adce807a Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 9 Jun 2021 16:04:34 +0100 Subject: [PATCH 07/31] bugfix,srsenb: extend rrc mobility unit test for intraenb handover --- srsenb/test/rrc/rrc_mobility_test.cc | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/srsenb/test/rrc/rrc_mobility_test.cc b/srsenb/test/rrc/rrc_mobility_test.cc index 0f9bf4173..95f5a843f 100644 --- a/srsenb/test/rrc/rrc_mobility_test.cc +++ b/srsenb/test/rrc/rrc_mobility_test.cc @@ -473,6 +473,9 @@ int test_intraenb_mobility(srsran::log_sink_spy& spy, test_event test_params) TESTASSERT(recfg_r8.meas_cfg.meas_gap_cfg.type().value == setup_opts::setup); TESTASSERT((1 + recfg_r8.meas_cfg.meas_gap_cfg.setup().gap_offset.type().value) * 40u == tester.cfg.cell_list[1].meas_cfg.meas_gap_period); + auto* ue_cfg = &tester.mac.ue_db[tester.rnti]; + TESTASSERT(ue_cfg->ue_bearers[srb_to_lcid(lte_srb::srb1)].direction == srsenb::sched_interface::ue_bearer_cfg_t::DL); + TESTASSERT(ue_cfg->ue_bearers[srb_to_lcid(lte_srb::srb2)].direction == srsenb::sched_interface::ue_bearer_cfg_t::DL); /* Test Case: The UE sends a C-RNTI CE. Bearers are reestablished, PHY is configured */ tester.pdcp.last_sdu.sdu = nullptr; @@ -480,8 +483,14 @@ int test_intraenb_mobility(srsran::log_sink_spy& spy, test_event test_params) TESTASSERT(tester.rlc.ue_db[tester.rnti].reest_sdu_counter == 0); TESTASSERT(tester.pdcp.last_sdu.sdu == nullptr); TESTASSERT(tester.phy.phy_cfg_set); - TESTASSERT(tester.phy.last_cfg.size() == 1 and tester.mac.ue_db[tester.rnti].supported_cc_list.size() == 1); - TESTASSERT(tester.phy.last_cfg[0].enb_cc_idx == tester.mac.ue_db[tester.rnti].supported_cc_list[0].enb_cc_idx); + TESTASSERT(tester.phy.last_cfg.size() == 1 and ue_cfg->supported_cc_list.size() == 1); + TESTASSERT(tester.phy.last_cfg[0].enb_cc_idx == ue_cfg->supported_cc_list[0].enb_cc_idx); + TESTASSERT(ue_cfg->ue_bearers[srb_to_lcid(lte_srb::srb0)].direction == + srsenb::sched_interface::ue_bearer_cfg_t::BOTH); + TESTASSERT(ue_cfg->ue_bearers[srb_to_lcid(lte_srb::srb1)].direction == + srsenb::sched_interface::ue_bearer_cfg_t::BOTH); + TESTASSERT(ue_cfg->ue_bearers[srb_to_lcid(lte_srb::srb2)].direction == + srsenb::sched_interface::ue_bearer_cfg_t::BOTH); /* Test Case: The UE receives a duplicate C-RNTI CE. Nothing should happen */ if (test_params == test_event::duplicate_crnti_ce) { @@ -497,13 +506,13 @@ int test_intraenb_mobility(srsran::log_sink_spy& spy, test_event test_params) test_helpers::copy_msg_to_buffer(pdu, recfg_complete); tester.rrc.write_pdu(tester.rnti, srb_to_lcid(lte_srb::srb2), std::move(pdu)); TESTASSERT(tester.pdcp.last_sdu.sdu == nullptr); - sched_interface::ue_cfg_t& ue_cfg = tester.mac.ue_db[tester.rnti]; - TESTASSERT(ue_cfg.pucch_cfg.sr_configured); - TESTASSERT(ue_cfg.pucch_cfg.n_pucch_sr == phy_cfg_ded.sched_request_cfg.setup().sr_pucch_res_idx); - TESTASSERT(ue_cfg.pucch_cfg.I_sr == phy_cfg_ded.sched_request_cfg.setup().sr_cfg_idx); - TESTASSERT(ue_cfg.supported_cc_list[0].dl_cfg.cqi_report.pmi_idx == + ue_cfg = &tester.mac.ue_db[tester.rnti]; + TESTASSERT(ue_cfg->pucch_cfg.sr_configured); + TESTASSERT(ue_cfg->pucch_cfg.n_pucch_sr == phy_cfg_ded.sched_request_cfg.setup().sr_pucch_res_idx); + TESTASSERT(ue_cfg->pucch_cfg.I_sr == phy_cfg_ded.sched_request_cfg.setup().sr_cfg_idx); + TESTASSERT(ue_cfg->supported_cc_list[0].dl_cfg.cqi_report.pmi_idx == phy_cfg_ded.cqi_report_cfg.cqi_report_periodic.setup().cqi_pmi_cfg_idx); - TESTASSERT(ue_cfg.pucch_cfg.n_pucch == phy_cfg_ded.cqi_report_cfg.cqi_report_periodic.setup().cqi_pucch_res_idx); + TESTASSERT(ue_cfg->pucch_cfg.n_pucch == phy_cfg_ded.cqi_report_cfg.cqi_report_periodic.setup().cqi_pucch_res_idx); /* Test Case: The RRC should be able to start a new handover */ uint8_t meas_report[] = {0x08, 0x10, 0x38, 0x74, 0x00, 0x05, 0xBC, 0x80}; // PCI == 1 From 94959b531815e35bca465e9b19724792c3114833 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Thu, 10 Jun 2021 10:47:32 +0200 Subject: [PATCH 08/31] srsue,test: reorganize test folders and move to components like we in PHY --- srsue/CMakeLists.txt | 1 - srsue/src/CMakeLists.txt | 1 + srsue/src/phy/CMakeLists.txt | 2 + .../{test/phy => src/phy/test}/CMakeLists.txt | 0 .../phy => src/phy/test}/nr_cell_search_rf.cc | 0 .../phy/test}/nr_cell_search_test.cc | 0 .../phy => src/phy/test}/scell_search_test.cc | 0 .../{test/phy => src/phy/test}/ue_phy_test.cc | 0 srsue/src/stack/mac/CMakeLists.txt | 2 + srsue/{ => src/stack/mac}/test/CMakeLists.txt | 11 ------ srsue/{ => src/stack/mac}/test/mac_test.cc | 0 srsue/src/stack/rrc/CMakeLists.txt | 2 + .../stack/rrc/test}/CMakeLists.txt | 24 +----------- .../stack/rrc/test}/rrc_cell_test.cc | 0 .../stack/rrc/test}/rrc_meas_test.cc | 0 .../stack/rrc/test}/rrc_phy_ctrl_test.cc | 0 .../stack/rrc/test}/rrc_reconfig_test.cc | 0 .../stack/rrc/test}/ue_rrc_nr_test.cc | 0 srsue/src/stack/upper/CMakeLists.txt | 2 + srsue/src/stack/upper/test/CMakeLists.txt | 39 +++++++++++++++++++ .../upper => src/stack/upper/test}/gw_test.cc | 0 .../stack/upper/test}/nas_test.cc | 0 .../stack/upper/test}/pcsc_usim_test.cc | 0 .../stack/upper/test}/tft_test.cc | 0 .../stack/upper/test}/usim_test.cc | 0 srsue/src/test/CMakeLists.txt | 15 +++++++ srsue/{ => src}/test/metrics_test.cc | 0 srsue/{ => src}/test/ttcn3/CMakeLists.txt | 0 srsue/{ => src}/test/ttcn3/README.md | 0 srsue/{ => src}/test/ttcn3/hdr/dut_utils.h | 0 .../{ => src}/test/ttcn3/hdr/lte_ttcn3_phy.h | 0 .../{ => src}/test/ttcn3/hdr/swappable_sink.h | 0 srsue/{ => src}/test/ttcn3/hdr/ttcn3_common.h | 0 .../test/ttcn3/hdr/ttcn3_drb_interface.h | 0 .../{ => src}/test/ttcn3/hdr/ttcn3_helpers.h | 0 .../test/ttcn3/hdr/ttcn3_interfaces.h | 0 .../test/ttcn3/hdr/ttcn3_ip_ctrl_interface.h | 0 .../test/ttcn3/hdr/ttcn3_ip_sock_interface.h | 0 .../test/ttcn3/hdr/ttcn3_port_handler.h | 0 .../test/ttcn3/hdr/ttcn3_srb_interface.h | 0 .../test/ttcn3/hdr/ttcn3_sys_interface.h | 0 srsue/{ => src}/test/ttcn3/hdr/ttcn3_syssim.h | 0 srsue/{ => src}/test/ttcn3/hdr/ttcn3_ue.h | 0 .../test/ttcn3/hdr/ttcn3_ut_interface.h | 0 srsue/{ => src}/test/ttcn3/src/CMakeLists.txt | 2 +- .../{ => src}/test/ttcn3/src/lte_ttcn3_phy.cc | 0 srsue/{ => src}/test/ttcn3/src/ttcn3_dut.cc | 0 .../{ => src}/test/ttcn3/src/ttcn3_syssim.cc | 2 +- srsue/{ => src}/test/ttcn3/src/ttcn3_ue.cc | 2 +- .../{ => src}/test/ttcn3/test/CMakeLists.txt | 2 +- .../test/ttcn3/test/rapidjson_test.cc | 1 - .../test/ttcn3/test/ttcn3_if_handler_test.cc | 0 52 files changed, 68 insertions(+), 40 deletions(-) rename srsue/{test/phy => src/phy/test}/CMakeLists.txt (100%) rename srsue/{test/phy => src/phy/test}/nr_cell_search_rf.cc (100%) rename srsue/{test/phy => src/phy/test}/nr_cell_search_test.cc (100%) rename srsue/{test/phy => src/phy/test}/scell_search_test.cc (100%) rename srsue/{test/phy => src/phy/test}/ue_phy_test.cc (100%) rename srsue/{ => src/stack/mac}/test/CMakeLists.txt (52%) rename srsue/{ => src/stack/mac}/test/mac_test.cc (100%) rename srsue/{test/upper => src/stack/rrc/test}/CMakeLists.txt (68%) rename srsue/{test/upper => src/stack/rrc/test}/rrc_cell_test.cc (100%) rename srsue/{test/upper => src/stack/rrc/test}/rrc_meas_test.cc (100%) rename srsue/{test/upper => src/stack/rrc/test}/rrc_phy_ctrl_test.cc (100%) rename srsue/{test/upper => src/stack/rrc/test}/rrc_reconfig_test.cc (100%) rename srsue/{test/upper => src/stack/rrc/test}/ue_rrc_nr_test.cc (100%) create mode 100644 srsue/src/stack/upper/test/CMakeLists.txt rename srsue/{test/upper => src/stack/upper/test}/gw_test.cc (100%) rename srsue/{test/upper => src/stack/upper/test}/nas_test.cc (100%) rename srsue/{test/upper => src/stack/upper/test}/pcsc_usim_test.cc (100%) rename srsue/{test/upper => src/stack/upper/test}/tft_test.cc (100%) rename srsue/{test/upper => src/stack/upper/test}/usim_test.cc (100%) create mode 100644 srsue/src/test/CMakeLists.txt rename srsue/{ => src}/test/metrics_test.cc (100%) rename srsue/{ => src}/test/ttcn3/CMakeLists.txt (100%) rename srsue/{ => src}/test/ttcn3/README.md (100%) rename srsue/{ => src}/test/ttcn3/hdr/dut_utils.h (100%) rename srsue/{ => src}/test/ttcn3/hdr/lte_ttcn3_phy.h (100%) rename srsue/{ => src}/test/ttcn3/hdr/swappable_sink.h (100%) rename srsue/{ => src}/test/ttcn3/hdr/ttcn3_common.h (100%) rename srsue/{ => src}/test/ttcn3/hdr/ttcn3_drb_interface.h (100%) rename srsue/{ => src}/test/ttcn3/hdr/ttcn3_helpers.h (100%) rename srsue/{ => src}/test/ttcn3/hdr/ttcn3_interfaces.h (100%) rename srsue/{ => src}/test/ttcn3/hdr/ttcn3_ip_ctrl_interface.h (100%) rename srsue/{ => src}/test/ttcn3/hdr/ttcn3_ip_sock_interface.h (100%) rename srsue/{ => src}/test/ttcn3/hdr/ttcn3_port_handler.h (100%) rename srsue/{ => src}/test/ttcn3/hdr/ttcn3_srb_interface.h (100%) rename srsue/{ => src}/test/ttcn3/hdr/ttcn3_sys_interface.h (100%) rename srsue/{ => src}/test/ttcn3/hdr/ttcn3_syssim.h (100%) rename srsue/{ => src}/test/ttcn3/hdr/ttcn3_ue.h (100%) rename srsue/{ => src}/test/ttcn3/hdr/ttcn3_ut_interface.h (100%) rename srsue/{ => src}/test/ttcn3/src/CMakeLists.txt (93%) rename srsue/{ => src}/test/ttcn3/src/lte_ttcn3_phy.cc (100%) rename srsue/{ => src}/test/ttcn3/src/ttcn3_dut.cc (100%) rename srsue/{ => src}/test/ttcn3/src/ttcn3_syssim.cc (99%) rename srsue/{ => src}/test/ttcn3/src/ttcn3_ue.cc (99%) rename srsue/{ => src}/test/ttcn3/test/CMakeLists.txt (80%) rename srsue/{ => src}/test/ttcn3/test/rapidjson_test.cc (98%) rename srsue/{ => src}/test/ttcn3/test/ttcn3_if_handler_test.cc (100%) diff --git a/srsue/CMakeLists.txt b/srsue/CMakeLists.txt index 60f3376a0..76bb4503a 100644 --- a/srsue/CMakeLists.txt +++ b/srsue/CMakeLists.txt @@ -31,7 +31,6 @@ link_directories( # Add subdirectories ######################################################################## add_subdirectory(src) -add_subdirectory(test) ######################################################################## # Default configuration files diff --git a/srsue/src/CMakeLists.txt b/srsue/src/CMakeLists.txt index aa6809c9f..1bd3e1725 100644 --- a/srsue/src/CMakeLists.txt +++ b/srsue/src/CMakeLists.txt @@ -8,6 +8,7 @@ add_subdirectory(phy) add_subdirectory(stack) +add_subdirectory(test) # Link libstdc++ and libgcc if(BUILD_STATIC) diff --git a/srsue/src/phy/CMakeLists.txt b/srsue/src/phy/CMakeLists.txt index bc668bb57..d1e45cdaf 100644 --- a/srsue/src/phy/CMakeLists.txt +++ b/srsue/src/phy/CMakeLists.txt @@ -6,6 +6,8 @@ # the distribution. # +add_subdirectory(test) + file(GLOB_RECURSE SOURCES "*.cc") add_library(srsue_phy STATIC ${SOURCES}) diff --git a/srsue/test/phy/CMakeLists.txt b/srsue/src/phy/test/CMakeLists.txt similarity index 100% rename from srsue/test/phy/CMakeLists.txt rename to srsue/src/phy/test/CMakeLists.txt diff --git a/srsue/test/phy/nr_cell_search_rf.cc b/srsue/src/phy/test/nr_cell_search_rf.cc similarity index 100% rename from srsue/test/phy/nr_cell_search_rf.cc rename to srsue/src/phy/test/nr_cell_search_rf.cc diff --git a/srsue/test/phy/nr_cell_search_test.cc b/srsue/src/phy/test/nr_cell_search_test.cc similarity index 100% rename from srsue/test/phy/nr_cell_search_test.cc rename to srsue/src/phy/test/nr_cell_search_test.cc diff --git a/srsue/test/phy/scell_search_test.cc b/srsue/src/phy/test/scell_search_test.cc similarity index 100% rename from srsue/test/phy/scell_search_test.cc rename to srsue/src/phy/test/scell_search_test.cc diff --git a/srsue/test/phy/ue_phy_test.cc b/srsue/src/phy/test/ue_phy_test.cc similarity index 100% rename from srsue/test/phy/ue_phy_test.cc rename to srsue/src/phy/test/ue_phy_test.cc diff --git a/srsue/src/stack/mac/CMakeLists.txt b/srsue/src/stack/mac/CMakeLists.txt index 66bdb43c9..1670ce449 100644 --- a/srsue/src/stack/mac/CMakeLists.txt +++ b/srsue/src/stack/mac/CMakeLists.txt @@ -6,6 +6,8 @@ # the distribution. # +add_subdirectory(test) + set(SOURCES demux.cc dl_harq.cc mac.cc mux.cc proc_bsr.cc proc_phr.cc proc_ra.cc proc_sr.cc ul_harq.cc) add_library(srsue_mac STATIC ${SOURCES}) target_link_libraries(srsue_mac srsue_mac_common ${ATOMIC_LIBS}) \ No newline at end of file diff --git a/srsue/test/CMakeLists.txt b/srsue/src/stack/mac/test/CMakeLists.txt similarity index 52% rename from srsue/test/CMakeLists.txt rename to srsue/src/stack/mac/test/CMakeLists.txt index 28af94179..d9008b75c 100644 --- a/srsue/test/CMakeLists.txt +++ b/srsue/src/stack/mac/test/CMakeLists.txt @@ -6,17 +6,6 @@ # the distribution. # -add_subdirectory(phy) -add_subdirectory(upper) - -if (ENABLE_TTCN3) - add_subdirectory(ttcn3) -endif (ENABLE_TTCN3) - -add_executable(metrics_test metrics_test.cc ../src/metrics_stdout.cc ../src/metrics_csv.cc) -target_link_libraries(metrics_test srsran_phy srsran_common) -add_test(metrics_test metrics_test -o ${CMAKE_CURRENT_BINARY_DIR}/ue_metrics.csv) - add_executable(mac_test mac_test.cc) target_link_libraries(mac_test srsue_mac srsue_phy srsran_common srsran_mac srsran_phy srsran_radio srsran_asn1 rrc_asn1 ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) add_test(mac_test mac_test) \ No newline at end of file diff --git a/srsue/test/mac_test.cc b/srsue/src/stack/mac/test/mac_test.cc similarity index 100% rename from srsue/test/mac_test.cc rename to srsue/src/stack/mac/test/mac_test.cc diff --git a/srsue/src/stack/rrc/CMakeLists.txt b/srsue/src/stack/rrc/CMakeLists.txt index 25ff70553..c73e0f1e3 100644 --- a/srsue/src/stack/rrc/CMakeLists.txt +++ b/srsue/src/stack/rrc/CMakeLists.txt @@ -6,6 +6,8 @@ # the distribution. # +add_subdirectory(test) + set(SOURCES rrc.cc rrc_procedures.cc rrc_meas.cc rrc_cell.cc phy_controller.cc) add_library(srsue_rrc STATIC ${SOURCES}) diff --git a/srsue/test/upper/CMakeLists.txt b/srsue/src/stack/rrc/test/CMakeLists.txt similarity index 68% rename from srsue/test/upper/CMakeLists.txt rename to srsue/src/stack/rrc/test/CMakeLists.txt index f3e3cc3db..9a79ce608 100644 --- a/srsue/test/upper/CMakeLists.txt +++ b/srsue/src/stack/rrc/test/CMakeLists.txt @@ -6,15 +6,6 @@ # the distribution. # -add_executable(usim_test usim_test.cc) -target_link_libraries(usim_test srsue_upper srsran_upper srsran_phy rrc_asn1) -add_test(usim_test usim_test) - -if(HAVE_PCSC) - add_executable(pcsc_usim_test pcsc_usim_test.cc) - target_link_libraries(pcsc_usim_test srsue_upper srsran_upper srsran_phy) -endif(HAVE_PCSC) - add_executable(rrc_reconfig_test rrc_reconfig_test.cc) target_link_libraries(rrc_reconfig_test srsue_upper srsran_upper srsran_phy rrc_asn1) add_test(rrc_reconfig_test rrc_reconfig_test) @@ -23,18 +14,6 @@ add_executable(rrc_meas_test rrc_meas_test.cc) target_link_libraries(rrc_meas_test srsue_rrc srsue_upper srsran_upper srsran_phy rrc_asn1 rrc_nr_asn1) add_test(rrc_meas_test rrc_meas_test) -add_executable(nas_test nas_test.cc) -target_link_libraries(nas_test srsue_upper srsran_upper srsran_phy rrc_asn1) -add_test(nas_test nas_test) - -add_executable(gw_test gw_test.cc) -target_link_libraries(gw_test srsue_upper srsran_upper srsran_phy) -add_test(gw_test gw_test) - -add_executable(tft_test tft_test.cc) -target_link_libraries(tft_test srsue_upper srsran_upper srsran_phy) -add_test(tft_test tft_test) - add_executable(rrc_phy_ctrl_test rrc_phy_ctrl_test.cc) target_link_libraries(rrc_phy_ctrl_test srsran_common srsue_rrc ${ATOMIC_LIBS}) add_test(rrc_phy_ctrl_test rrc_phy_ctrl_test) @@ -54,5 +33,4 @@ if (NOT ${BUILD_CMD} STREQUAL "") add_custom_command(TARGET ip_test POST_BUILD COMMAND ${BUILD_CMD}) else(NOT ${BUILD_CMD} STREQUAL "") message(STATUS "No post-build command defined") -endif (NOT ${BUILD_CMD} STREQUAL "") - +endif (NOT ${BUILD_CMD} STREQUAL "") \ No newline at end of file diff --git a/srsue/test/upper/rrc_cell_test.cc b/srsue/src/stack/rrc/test/rrc_cell_test.cc similarity index 100% rename from srsue/test/upper/rrc_cell_test.cc rename to srsue/src/stack/rrc/test/rrc_cell_test.cc diff --git a/srsue/test/upper/rrc_meas_test.cc b/srsue/src/stack/rrc/test/rrc_meas_test.cc similarity index 100% rename from srsue/test/upper/rrc_meas_test.cc rename to srsue/src/stack/rrc/test/rrc_meas_test.cc diff --git a/srsue/test/upper/rrc_phy_ctrl_test.cc b/srsue/src/stack/rrc/test/rrc_phy_ctrl_test.cc similarity index 100% rename from srsue/test/upper/rrc_phy_ctrl_test.cc rename to srsue/src/stack/rrc/test/rrc_phy_ctrl_test.cc diff --git a/srsue/test/upper/rrc_reconfig_test.cc b/srsue/src/stack/rrc/test/rrc_reconfig_test.cc similarity index 100% rename from srsue/test/upper/rrc_reconfig_test.cc rename to srsue/src/stack/rrc/test/rrc_reconfig_test.cc diff --git a/srsue/test/upper/ue_rrc_nr_test.cc b/srsue/src/stack/rrc/test/ue_rrc_nr_test.cc similarity index 100% rename from srsue/test/upper/ue_rrc_nr_test.cc rename to srsue/src/stack/rrc/test/ue_rrc_nr_test.cc diff --git a/srsue/src/stack/upper/CMakeLists.txt b/srsue/src/stack/upper/CMakeLists.txt index d027ba02c..9d814f985 100644 --- a/srsue/src/stack/upper/CMakeLists.txt +++ b/srsue/src/stack/upper/CMakeLists.txt @@ -6,6 +6,8 @@ # the distribution. # +add_subdirectory(test) + set(SOURCES nas.cc nas_emm_state.cc nas_idle_procedures.cc gw.cc usim_base.cc usim.cc tft_packet_filter.cc) if(HAVE_PCSC) diff --git a/srsue/src/stack/upper/test/CMakeLists.txt b/srsue/src/stack/upper/test/CMakeLists.txt new file mode 100644 index 000000000..54f6b5b83 --- /dev/null +++ b/srsue/src/stack/upper/test/CMakeLists.txt @@ -0,0 +1,39 @@ +# +# Copyright 2013-2021 Software Radio Systems Limited +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the distribution. +# + +add_executable(usim_test usim_test.cc) +target_link_libraries(usim_test srsue_upper srsran_upper srsran_phy rrc_asn1) +add_test(usim_test usim_test) + +if(HAVE_PCSC) + add_executable(pcsc_usim_test pcsc_usim_test.cc) + target_link_libraries(pcsc_usim_test srsue_upper srsran_upper srsran_phy) +endif(HAVE_PCSC) + +add_executable(nas_test nas_test.cc) +target_link_libraries(nas_test srsue_upper srsran_upper srsran_phy rrc_asn1) +add_test(nas_test nas_test) + +add_executable(gw_test gw_test.cc) +target_link_libraries(gw_test srsue_upper srsran_upper srsran_phy) +add_test(gw_test gw_test) + +add_executable(tft_test tft_test.cc) +target_link_libraries(tft_test srsue_upper srsran_upper srsran_phy) +add_test(tft_test tft_test) + +######################################################################## +# Option to run command after build (useful for remote builds) +######################################################################## +if (NOT ${BUILD_CMD} STREQUAL "") + message(STATUS "Added custom post-build command: ${BUILD_CMD}") + add_custom_command(TARGET ip_test POST_BUILD COMMAND ${BUILD_CMD}) +else(NOT ${BUILD_CMD} STREQUAL "") + message(STATUS "No post-build command defined") +endif (NOT ${BUILD_CMD} STREQUAL "") + diff --git a/srsue/test/upper/gw_test.cc b/srsue/src/stack/upper/test/gw_test.cc similarity index 100% rename from srsue/test/upper/gw_test.cc rename to srsue/src/stack/upper/test/gw_test.cc diff --git a/srsue/test/upper/nas_test.cc b/srsue/src/stack/upper/test/nas_test.cc similarity index 100% rename from srsue/test/upper/nas_test.cc rename to srsue/src/stack/upper/test/nas_test.cc diff --git a/srsue/test/upper/pcsc_usim_test.cc b/srsue/src/stack/upper/test/pcsc_usim_test.cc similarity index 100% rename from srsue/test/upper/pcsc_usim_test.cc rename to srsue/src/stack/upper/test/pcsc_usim_test.cc diff --git a/srsue/test/upper/tft_test.cc b/srsue/src/stack/upper/test/tft_test.cc similarity index 100% rename from srsue/test/upper/tft_test.cc rename to srsue/src/stack/upper/test/tft_test.cc diff --git a/srsue/test/upper/usim_test.cc b/srsue/src/stack/upper/test/usim_test.cc similarity index 100% rename from srsue/test/upper/usim_test.cc rename to srsue/src/stack/upper/test/usim_test.cc diff --git a/srsue/src/test/CMakeLists.txt b/srsue/src/test/CMakeLists.txt new file mode 100644 index 000000000..c0289e189 --- /dev/null +++ b/srsue/src/test/CMakeLists.txt @@ -0,0 +1,15 @@ +# +# Copyright 2013-2021 Software Radio Systems Limited +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the distribution. +# + +if (ENABLE_TTCN3) + add_subdirectory(ttcn3) +endif (ENABLE_TTCN3) + +add_executable(metrics_test metrics_test.cc ../metrics_stdout.cc ../metrics_csv.cc) +target_link_libraries(metrics_test srsran_phy srsran_common) +add_test(metrics_test metrics_test -o ${CMAKE_CURRENT_BINARY_DIR}/ue_metrics.csv) \ No newline at end of file diff --git a/srsue/test/metrics_test.cc b/srsue/src/test/metrics_test.cc similarity index 100% rename from srsue/test/metrics_test.cc rename to srsue/src/test/metrics_test.cc diff --git a/srsue/test/ttcn3/CMakeLists.txt b/srsue/src/test/ttcn3/CMakeLists.txt similarity index 100% rename from srsue/test/ttcn3/CMakeLists.txt rename to srsue/src/test/ttcn3/CMakeLists.txt diff --git a/srsue/test/ttcn3/README.md b/srsue/src/test/ttcn3/README.md similarity index 100% rename from srsue/test/ttcn3/README.md rename to srsue/src/test/ttcn3/README.md diff --git a/srsue/test/ttcn3/hdr/dut_utils.h b/srsue/src/test/ttcn3/hdr/dut_utils.h similarity index 100% rename from srsue/test/ttcn3/hdr/dut_utils.h rename to srsue/src/test/ttcn3/hdr/dut_utils.h diff --git a/srsue/test/ttcn3/hdr/lte_ttcn3_phy.h b/srsue/src/test/ttcn3/hdr/lte_ttcn3_phy.h similarity index 100% rename from srsue/test/ttcn3/hdr/lte_ttcn3_phy.h rename to srsue/src/test/ttcn3/hdr/lte_ttcn3_phy.h diff --git a/srsue/test/ttcn3/hdr/swappable_sink.h b/srsue/src/test/ttcn3/hdr/swappable_sink.h similarity index 100% rename from srsue/test/ttcn3/hdr/swappable_sink.h rename to srsue/src/test/ttcn3/hdr/swappable_sink.h diff --git a/srsue/test/ttcn3/hdr/ttcn3_common.h b/srsue/src/test/ttcn3/hdr/ttcn3_common.h similarity index 100% rename from srsue/test/ttcn3/hdr/ttcn3_common.h rename to srsue/src/test/ttcn3/hdr/ttcn3_common.h diff --git a/srsue/test/ttcn3/hdr/ttcn3_drb_interface.h b/srsue/src/test/ttcn3/hdr/ttcn3_drb_interface.h similarity index 100% rename from srsue/test/ttcn3/hdr/ttcn3_drb_interface.h rename to srsue/src/test/ttcn3/hdr/ttcn3_drb_interface.h diff --git a/srsue/test/ttcn3/hdr/ttcn3_helpers.h b/srsue/src/test/ttcn3/hdr/ttcn3_helpers.h similarity index 100% rename from srsue/test/ttcn3/hdr/ttcn3_helpers.h rename to srsue/src/test/ttcn3/hdr/ttcn3_helpers.h diff --git a/srsue/test/ttcn3/hdr/ttcn3_interfaces.h b/srsue/src/test/ttcn3/hdr/ttcn3_interfaces.h similarity index 100% rename from srsue/test/ttcn3/hdr/ttcn3_interfaces.h rename to srsue/src/test/ttcn3/hdr/ttcn3_interfaces.h diff --git a/srsue/test/ttcn3/hdr/ttcn3_ip_ctrl_interface.h b/srsue/src/test/ttcn3/hdr/ttcn3_ip_ctrl_interface.h similarity index 100% rename from srsue/test/ttcn3/hdr/ttcn3_ip_ctrl_interface.h rename to srsue/src/test/ttcn3/hdr/ttcn3_ip_ctrl_interface.h diff --git a/srsue/test/ttcn3/hdr/ttcn3_ip_sock_interface.h b/srsue/src/test/ttcn3/hdr/ttcn3_ip_sock_interface.h similarity index 100% rename from srsue/test/ttcn3/hdr/ttcn3_ip_sock_interface.h rename to srsue/src/test/ttcn3/hdr/ttcn3_ip_sock_interface.h diff --git a/srsue/test/ttcn3/hdr/ttcn3_port_handler.h b/srsue/src/test/ttcn3/hdr/ttcn3_port_handler.h similarity index 100% rename from srsue/test/ttcn3/hdr/ttcn3_port_handler.h rename to srsue/src/test/ttcn3/hdr/ttcn3_port_handler.h diff --git a/srsue/test/ttcn3/hdr/ttcn3_srb_interface.h b/srsue/src/test/ttcn3/hdr/ttcn3_srb_interface.h similarity index 100% rename from srsue/test/ttcn3/hdr/ttcn3_srb_interface.h rename to srsue/src/test/ttcn3/hdr/ttcn3_srb_interface.h diff --git a/srsue/test/ttcn3/hdr/ttcn3_sys_interface.h b/srsue/src/test/ttcn3/hdr/ttcn3_sys_interface.h similarity index 100% rename from srsue/test/ttcn3/hdr/ttcn3_sys_interface.h rename to srsue/src/test/ttcn3/hdr/ttcn3_sys_interface.h diff --git a/srsue/test/ttcn3/hdr/ttcn3_syssim.h b/srsue/src/test/ttcn3/hdr/ttcn3_syssim.h similarity index 100% rename from srsue/test/ttcn3/hdr/ttcn3_syssim.h rename to srsue/src/test/ttcn3/hdr/ttcn3_syssim.h diff --git a/srsue/test/ttcn3/hdr/ttcn3_ue.h b/srsue/src/test/ttcn3/hdr/ttcn3_ue.h similarity index 100% rename from srsue/test/ttcn3/hdr/ttcn3_ue.h rename to srsue/src/test/ttcn3/hdr/ttcn3_ue.h diff --git a/srsue/test/ttcn3/hdr/ttcn3_ut_interface.h b/srsue/src/test/ttcn3/hdr/ttcn3_ut_interface.h similarity index 100% rename from srsue/test/ttcn3/hdr/ttcn3_ut_interface.h rename to srsue/src/test/ttcn3/hdr/ttcn3_ut_interface.h diff --git a/srsue/test/ttcn3/src/CMakeLists.txt b/srsue/src/test/ttcn3/src/CMakeLists.txt similarity index 93% rename from srsue/test/ttcn3/src/CMakeLists.txt rename to srsue/src/test/ttcn3/src/CMakeLists.txt index 943df04fb..6fc2619c6 100644 --- a/srsue/test/ttcn3/src/CMakeLists.txt +++ b/srsue/src/test/ttcn3/src/CMakeLists.txt @@ -29,4 +29,4 @@ set(LINK_LIBRARIES srsue_stack target_link_libraries(ttcn3_dut ${LINK_LIBRARIES}) -include_directories(${PROJECT_SOURCE_DIR}/srsue/test/ttcn3/hdr) +include_directories(${PROJECT_SOURCE_DIR}/srsue/src/test/ttcn3/hdr) diff --git a/srsue/test/ttcn3/src/lte_ttcn3_phy.cc b/srsue/src/test/ttcn3/src/lte_ttcn3_phy.cc similarity index 100% rename from srsue/test/ttcn3/src/lte_ttcn3_phy.cc rename to srsue/src/test/ttcn3/src/lte_ttcn3_phy.cc diff --git a/srsue/test/ttcn3/src/ttcn3_dut.cc b/srsue/src/test/ttcn3/src/ttcn3_dut.cc similarity index 100% rename from srsue/test/ttcn3/src/ttcn3_dut.cc rename to srsue/src/test/ttcn3/src/ttcn3_dut.cc diff --git a/srsue/test/ttcn3/src/ttcn3_syssim.cc b/srsue/src/test/ttcn3/src/ttcn3_syssim.cc similarity index 99% rename from srsue/test/ttcn3/src/ttcn3_syssim.cc rename to srsue/src/test/ttcn3/src/ttcn3_syssim.cc index 5c9b81d50..ab6c51fe3 100644 --- a/srsue/test/ttcn3/src/ttcn3_syssim.cc +++ b/srsue/src/test/ttcn3/src/ttcn3_syssim.cc @@ -10,7 +10,7 @@ * */ -#include "srsue/test/ttcn3/hdr/ttcn3_syssim.h" +#include "ttcn3_syssim.h" #include "dut_utils.h" #include "srsran/mac/pdu_queue.h" #include "srsran/srslog/srslog.h" diff --git a/srsue/test/ttcn3/src/ttcn3_ue.cc b/srsue/src/test/ttcn3/src/ttcn3_ue.cc similarity index 99% rename from srsue/test/ttcn3/src/ttcn3_ue.cc rename to srsue/src/test/ttcn3/src/ttcn3_ue.cc index adf274da0..f6ebabd9b 100644 --- a/srsue/test/ttcn3/src/ttcn3_ue.cc +++ b/srsue/src/test/ttcn3/src/ttcn3_ue.cc @@ -10,7 +10,7 @@ * */ -#include "srsue/test/ttcn3/hdr/ttcn3_ue.h" +#include "ttcn3_ue.h" #include "lte_ttcn3_phy.h" #include "srsue/hdr/stack/ue_stack_lte.h" #include diff --git a/srsue/test/ttcn3/test/CMakeLists.txt b/srsue/src/test/ttcn3/test/CMakeLists.txt similarity index 80% rename from srsue/test/ttcn3/test/CMakeLists.txt rename to srsue/src/test/ttcn3/test/CMakeLists.txt index 2e46bd4f1..92dd6a4c5 100644 --- a/srsue/test/ttcn3/test/CMakeLists.txt +++ b/srsue/src/test/ttcn3/test/CMakeLists.txt @@ -6,7 +6,7 @@ # the distribution. # -include_directories(${PROJECT_SOURCE_DIR}/srsue/test/ttcn3/hdr) +include_directories(${PROJECT_SOURCE_DIR}/srsue/src/test/ttcn3/hdr) add_executable(rapidjson_test rapidjson_test.cc) target_link_libraries(rapidjson_test srsran_common) diff --git a/srsue/test/ttcn3/test/rapidjson_test.cc b/srsue/src/test/ttcn3/test/rapidjson_test.cc similarity index 98% rename from srsue/test/ttcn3/test/rapidjson_test.cc rename to srsue/src/test/ttcn3/test/rapidjson_test.cc index e7c56060f..5bb0e2155 100644 --- a/srsue/test/ttcn3/test/rapidjson_test.cc +++ b/srsue/src/test/ttcn3/test/rapidjson_test.cc @@ -13,7 +13,6 @@ #include "srsran/common/test_common.h" #include "ttcn3_helpers.h" #include -#include #include #include diff --git a/srsue/test/ttcn3/test/ttcn3_if_handler_test.cc b/srsue/src/test/ttcn3/test/ttcn3_if_handler_test.cc similarity index 100% rename from srsue/test/ttcn3/test/ttcn3_if_handler_test.cc rename to srsue/src/test/ttcn3/test/ttcn3_if_handler_test.cc From 676080d6afb29faef0ed46a8eeda4a8a36a9a022 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 10 Jun 2021 19:09:29 +0200 Subject: [PATCH 09/31] Added macro SRSRAN_VEC_SAFE_CMA --- lib/include/srsran/phy/utils/vector.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/include/srsran/phy/utils/vector.h b/lib/include/srsran/phy/utils/vector.h index e3f922ca9..087cb8009 100644 --- a/lib/include/srsran/phy/utils/vector.h +++ b/lib/include/srsran/phy/utils/vector.h @@ -50,6 +50,9 @@ extern "C" { // Cumulative moving average #define SRSRAN_VEC_CMA(data, average, n) ((average) + ((data) - (average)) / ((n) + 1)) +// Cumulative moving average +#define SRSRAN_VEC_SAFE_CMA(data, average, n) (isnormal(average) ? SRSRAN_VEC_CMA(data, average, n) : (data)) + // Proportional moving average #define SRSRAN_VEC_PMA(average1, n1, average2, n2) (((average1) * (n1) + (average2) * (n2)) / ((n1) + (n2))) From 4bfe092a244522ae1fd30d00286db51d3ec2485a Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 10 Jun 2021 19:11:26 +0200 Subject: [PATCH 10/31] Added multi-command line in srsenb --- srsenb/src/main.cc | 101 ++++++++++++++++++++++++++++----------------- 1 file changed, 62 insertions(+), 39 deletions(-) diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index 888bcd985..416444b10 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -441,6 +441,63 @@ void parse_args(all_args_t* args, int argc, char* argv[]) static bool do_metrics = false; static bool do_padding = false; +static void execute_cmd(metrics_stdout* metrics, srsenb::enb_command_interface* control, const string& cmd_line) +{ + vector cmd; + srsran::string_parse_list(cmd_line, ' ', cmd); + if (cmd[0] == "t") { + do_metrics = !do_metrics; + if (do_metrics) { + cout << "Enter t to stop trace." << endl; + } else { + cout << "Enter t to restart trace." << endl; + } + metrics->toggle_print(do_metrics); + } else if (cmd[0] == "sleep") { + if (cmd.size() != 2) { + cout << "Usage: " << cmd[0] << " [number of seconds]" << endl; + return; + } + + int nseconds = srsran::string_cast(cmd[1]); + if (nseconds <= 0) { + return; + } + + std::this_thread::sleep_for(std::chrono::seconds(nseconds)); + + } else if (cmd[0] == "p") { + do_padding = !do_padding; + if (do_padding) { + cout << "Enter p to stop padding." << endl; + } else { + cout << "Enter p to restart padding." << endl; + } + control->toggle_padding(); + } else if (cmd[0] == "q") { + raise(SIGTERM); + } else if (cmd[0] == "cell_gain") { + if (cmd.size() != 3) { + cout << "Usage: " << cmd[0] << " [cell identifier] [gain in dB]" << endl; + return; + } + + // Parse command arguments + uint32_t cell_id = srsran::string_cast(cmd[1]); + float gain_db = srsran::string_cast(cmd[2]); + + // Set cell gain + control->cmd_cell_gain(cell_id, gain_db); + } else { + cout << "Available commands: " << endl; + cout << " t: starts console trace" << endl; + cout << " q: quit srsenb" << endl; + cout << " cell_gain: set relative cell gain" << endl; + cout << " p: starts MAC padding" << endl; + cout << endl; + } +} + static void* input_loop(metrics_stdout* metrics, srsenb::enb_command_interface* control) { struct pollfd pfd = {STDIN_FILENO, POLLIN, 0}; @@ -454,45 +511,11 @@ static void* input_loop(metrics_stdout* metrics, srsenb::enb_command_interface* cout << "Closing stdin thread." << endl; break; } else if (not input_line.empty()) { - vector cmd; - srsran::string_parse_list(input_line, ' ', cmd); - if (cmd[0] == "t") { - do_metrics = !do_metrics; - if (do_metrics) { - cout << "Enter t to stop trace." << endl; - } else { - cout << "Enter t to restart trace." << endl; - } - metrics->toggle_print(do_metrics); - } else if (cmd[0] == "p") { - do_padding = !do_padding; - if (do_padding) { - cout << "Enter p to stop padding." << endl; - } else { - cout << "Enter p to restart padding." << endl; - } - control->toggle_padding(); - } else if (cmd[0] == "q") { - raise(SIGTERM); - } else if (cmd[0] == "cell_gain") { - if (cmd.size() != 3) { - cout << "Usage: " << cmd[0] << " [cell identifier] [gain in dB]" << endl; - continue; - } - - // Parse command arguments - uint32_t cell_id = srsran::string_cast(cmd[1]); - float gain_db = srsran::string_cast(cmd[2]); - - // Set cell gain - control->cmd_cell_gain(cell_id, gain_db); - } else { - cout << "Available commands: " << endl; - cout << " t: starts console trace" << endl; - cout << " q: quit srsenb" << endl; - cout << " cell_gain: set relative cell gain" << endl; - cout << " p: starts MAC padding" << endl; - cout << endl; + list cmd_list; + srsran::string_parse_list(input_line, ';', cmd_list); + + for (const string& cmd : cmd_list) { + execute_cmd(metrics, control, cmd); } } } From fc5d0697439fb23e210a89fc69ac31f84cb94c5e Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 10 Jun 2021 19:31:09 +0200 Subject: [PATCH 11/31] SRSUE: Default PHY measurements to NAN --- srsue/hdr/phy/phy_common.h | 44 +++++++------- srsue/src/phy/lte/cc_worker.cc | 5 ++ srsue/src/phy/phy.cc | 4 ++ srsue/src/phy/phy_common.cc | 101 ++++++++++++++++----------------- 4 files changed, 81 insertions(+), 73 deletions(-) diff --git a/srsue/hdr/phy/phy_common.h b/srsue/hdr/phy/phy_common.h index 3acbd80df..d283ddf7d 100644 --- a/srsue/hdr/phy/phy_common.h +++ b/srsue/hdr/phy/phy_common.h @@ -168,6 +168,12 @@ public: */ uint32_t get_ul_earfcn(uint32_t dl_earfcn); + /** + * @brief Resets measurements from a given CC + * @param cc_idx CC index + */ + void reset_measurements(uint32_t cc_idx); + void update_measurements(uint32_t cc_idx, const srsran_chest_dl_res_t& chest_res, srsran_dl_sf_cfg_t sf_cfg_dl, @@ -218,32 +224,26 @@ public: } } } - void reset_neighbour_cells() - { - for (uint32_t i = 0; i < SRSRAN_MAX_CARRIERS; i++) { - avg_rsrp_neigh[i] = NAN; - } - } private: std::mutex meas_mutex; - float pathloss[SRSRAN_MAX_CARRIERS] = {}; - float cur_pathloss = 0.0f; - float cur_pusch_power = 0.0f; - float avg_rsrp[SRSRAN_MAX_CARRIERS] = {}; - float avg_rsrp_dbm[SRSRAN_MAX_CARRIERS] = {}; - float avg_rsrq_db[SRSRAN_MAX_CARRIERS] = {}; - float avg_rssi_dbm[SRSRAN_MAX_CARRIERS] = {}; - float avg_cfo_hz[SRSRAN_MAX_CARRIERS] = {}; - float rx_gain_offset = 0.0f; - float avg_sinr_db[SRSRAN_MAX_CARRIERS] = {}; - float avg_snr_db[SRSRAN_MAX_CARRIERS] = {}; - float avg_noise[SRSRAN_MAX_CARRIERS] = {}; - float avg_rsrp_neigh[SRSRAN_MAX_CARRIERS] = {}; - - uint32_t pcell_report_period = 0; - uint32_t rssi_read_cnt = 0; + float cur_pathloss = 0.0f; + float cur_pusch_power = 0.0f; + float rx_gain_offset = 0.0f; + std::array pathloss = {}; + std::array avg_rsrp = {}; + std::array avg_rsrp_dbm = {}; + std::array avg_rsrq_db = {}; + std::array avg_rssi_dbm = {}; + std::array avg_cfo_hz = {}; + std::array avg_sinr_db = {}; + std::array avg_snr_db = {}; + std::array avg_noise = {}; + std::array avg_rsrp_neigh = {}; + + static constexpr uint32_t pcell_report_period = 20; + uint32_t rssi_read_cnt = 0; rsrp_insync_itf* insync_itf = nullptr; diff --git a/srsue/src/phy/lte/cc_worker.cc b/srsue/src/phy/lte/cc_worker.cc index 913e5beae..ddafb7efe 100644 --- a/srsue/src/phy/lte/cc_worker.cc +++ b/srsue/src/phy/lte/cc_worker.cc @@ -549,6 +549,11 @@ void cc_worker::decode_phich() void cc_worker::update_measurements(std::vector& serving_cells, cf_t* rssi_power_buffer) { + // Do not update any measurement if the CC is not configured to prevent false or inaccurate data + if (not phy->cell_state.is_configured(cc_idx)) { + return; + } + phy->update_measurements( cc_idx, ue_dl.chest_res, sf_cfg_dl, ue_dl_cfg.cfg.pdsch.rs_power, serving_cells, rssi_power_buffer); } diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index 3c22ade56..12de63ba3 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -529,6 +529,10 @@ bool phy::set_scell(srsran_cell_t cell_info, uint32_t cc_idx, uint32_t earfcn) } } + // Reset measurements for the given CC after all workers finished processing and have been configured to ensure the + // measurements are not overwritten + common.reset_measurements(cc_idx); + // Change frequency only if the earfcn was modified if (earfcn_is_different) { double dl_freq = srsran_band_fd(earfcn) * 1e6; diff --git a/srsue/src/phy/phy_common.cc b/srsue/src/phy/phy_common.cc index 0b70dbddf..4803d5fce 100644 --- a/srsue/src/phy/phy_common.cc +++ b/srsue/src/phy/phy_common.cc @@ -611,8 +611,31 @@ void phy_common::update_cfo_measurement(uint32_t cc_idx, float cfo_hz) { std::unique_lock lock(meas_mutex); - // use SNR EMA coefficient for averaging - avg_cfo_hz[cc_idx] = SRSRAN_VEC_EMA(cfo_hz, avg_cfo_hz[cc_idx], args->snr_ema_coeff); + // Use SNR EMA coefficient for averaging + avg_cfo_hz[cc_idx] = SRSRAN_VEC_SAFE_EMA(cfo_hz, avg_cfo_hz[cc_idx], args->snr_ema_coeff); +} + +void phy_common::reset_measurements(uint32_t cc_idx) +{ + // If the CC index exceeds the maximum number of carriers, reset them all + if (cc_idx >= SRSRAN_MAX_CARRIERS) { + for (uint32_t cc = 0; cc < SRSRAN_MAX_CARRIERS; cc++) { + reset_measurements(cc); + } + } + + // Default all metrics to NAN to prevent providing invalid information on traces and other layers + std::unique_lock lock(meas_mutex); + pathloss[cc_idx] = NAN; + avg_rsrp[cc_idx] = NAN; + avg_rsrp_dbm[cc_idx] = NAN; + avg_rsrq_db[cc_idx] = NAN; + avg_rssi_dbm[cc_idx] = NAN; + avg_cfo_hz[cc_idx] = NAN; + avg_sinr_db[cc_idx] = NAN; + avg_snr_db[cc_idx] = NAN; + avg_noise[cc_idx] = NAN; + avg_rsrp_neigh[cc_idx] = NAN; } void phy_common::update_measurements(uint32_t cc_idx, @@ -644,7 +667,7 @@ void phy_common::update_measurements(uint32_t cc_idx, 30) : 0; if (std::isnormal(rssi_dbm)) { - avg_rssi_dbm[0] = SRSRAN_VEC_EMA(rssi_dbm, avg_rssi_dbm[0], args->snr_ema_coeff); + avg_rssi_dbm[0] = SRSRAN_VEC_SAFE_EMA(rssi_dbm, avg_rssi_dbm[0], args->snr_ema_coeff); } rx_gain_offset = get_radio()->get_rx_gain() + args->rx_gain_offset; @@ -658,21 +681,17 @@ void phy_common::update_measurements(uint32_t cc_idx, // Average RSRQ over DEFAULT_MEAS_PERIOD_MS then sent to RRC float rsrq_db = chest_res.rsrq_db; if (std::isnormal(rsrq_db)) { - if (!(sf_cfg_dl.tti % pcell_report_period) || !std::isnormal(avg_rsrq_db[cc_idx])) { - avg_rsrq_db[cc_idx] = rsrq_db; - } else { - avg_rsrq_db[cc_idx] = SRSRAN_VEC_CMA(rsrq_db, avg_rsrq_db[cc_idx], sf_cfg_dl.tti % pcell_report_period); + // Reset average RSRQ measurement + if (sf_cfg_dl.tti % pcell_report_period == 0) { + avg_rsrq_db[cc_idx] = NAN; } + avg_rsrq_db[cc_idx] = SRSRAN_VEC_SAFE_CMA(rsrq_db, avg_rsrq_db[cc_idx], sf_cfg_dl.tti % pcell_report_period); } // Average RSRP taken from CRS float rsrp_lin = chest_res.rsrp; if (std::isnormal(rsrp_lin)) { - if (!std::isnormal(avg_rsrp[cc_idx])) { - avg_rsrp[cc_idx] = rsrp_lin; - } else { - avg_rsrp[cc_idx] = SRSRAN_VEC_EMA(rsrp_lin, avg_rsrp[cc_idx], snr_ema_coeff); - } + avg_rsrp[cc_idx] = SRSRAN_VEC_SAFE_EMA(rsrp_lin, avg_rsrp[cc_idx], snr_ema_coeff); } /* Correct absolute power measurements by RX gain offset */ @@ -680,11 +699,11 @@ void phy_common::update_measurements(uint32_t cc_idx, // Serving cell RSRP measurements are averaged over DEFAULT_MEAS_PERIOD_MS then sent to RRC if (std::isnormal(rsrp_dbm)) { - if (!(sf_cfg_dl.tti % pcell_report_period) || !std::isnormal(avg_rsrp_dbm[cc_idx])) { - avg_rsrp_dbm[cc_idx] = rsrp_dbm; - } else { - avg_rsrp_dbm[cc_idx] = SRSRAN_VEC_CMA(rsrp_dbm, avg_rsrp_dbm[cc_idx], sf_cfg_dl.tti % pcell_report_period); + // Reset average RSRP measurement + if (sf_cfg_dl.tti % pcell_report_period == 0) { + avg_rsrp_dbm[cc_idx] = NAN; } + avg_rsrp_dbm[cc_idx] = SRSRAN_VEC_SAFE_CMA(rsrp_dbm, avg_rsrp_dbm[cc_idx], sf_cfg_dl.tti % pcell_report_period); } // Compute PL @@ -693,11 +712,7 @@ void phy_common::update_measurements(uint32_t cc_idx, // Average noise float cur_noise = chest_res.noise_estimate; if (std::isnormal(cur_noise)) { - if (!std::isnormal(avg_noise[cc_idx])) { - avg_noise[cc_idx] = cur_noise; - } else { - avg_noise[cc_idx] = SRSRAN_VEC_EMA(cur_noise, avg_noise[cc_idx], snr_ema_coeff); - } + avg_noise[cc_idx] = SRSRAN_VEC_SAFE_EMA(cur_noise, avg_noise[cc_idx], snr_ema_coeff); } // Calculate SINR using CRS from neighbours if are detected @@ -714,20 +729,12 @@ void phy_common::update_measurements(uint32_t cc_idx, // Average sinr in the log domain if (std::isnormal(sinr_db)) { - if (!std::isnormal(avg_sinr_db[cc_idx])) { - avg_sinr_db[cc_idx] = sinr_db; - } else { - avg_sinr_db[cc_idx] = SRSRAN_VEC_EMA(sinr_db, avg_sinr_db[cc_idx], snr_ema_coeff); - } + avg_sinr_db[cc_idx] = SRSRAN_VEC_SAFE_EMA(sinr_db, avg_sinr_db[cc_idx], snr_ema_coeff); } // Average snr in the log domain if (std::isnormal(chest_res.snr_db)) { - if (!std::isnormal(avg_snr_db[cc_idx])) { - avg_snr_db[cc_idx] = chest_res.snr_db; - } else { - avg_snr_db[cc_idx] = SRSRAN_VEC_EMA(chest_res.snr_db, avg_snr_db[cc_idx], snr_ema_coeff); - } + avg_snr_db[cc_idx] = SRSRAN_VEC_SAFE_EMA(chest_res.snr_db, avg_snr_db[cc_idx], snr_ema_coeff); } // Store metrics @@ -742,9 +749,9 @@ void phy_common::update_measurements(uint32_t cc_idx, set_ch_metrics(cc_idx, ch); - // Prepare measurements for serving cells - bool active = cell_state.is_configured(cc_idx); - if (active && ((sf_cfg_dl.tti % pcell_report_period) == pcell_report_period - 1)) { + // Prepare measurements for serving cells - skip if any measurement is invalid assuming pure zeros are not possible + if (std::isnormal(avg_rsrp_dbm[cc_idx]) and + std::isnormal(avg_cfo_hz[cc_idx] and ((sf_cfg_dl.tti % pcell_report_period) == pcell_report_period - 1))) { phy_meas_t meas = {}; meas.rsrp = avg_rsrp_dbm[cc_idx]; meas.rsrq = avg_rsrq_db[cc_idx]; @@ -866,25 +873,17 @@ void phy_common::reset() { reset_radio(); - sr_enabled = false; - cur_pathloss = 0; - cur_pusch_power = 0; - sr_last_tx_tti = -1; - pcell_report_period = 20; - last_ri = 0; + sr_enabled = false; + cur_pathloss = 0; + cur_pusch_power = 0; + sr_last_tx_tti = -1; + last_ri = 0; - { - std::unique_lock lock(meas_mutex); - ZERO_OBJECT(pathloss); - ZERO_OBJECT(avg_sinr_db); - ZERO_OBJECT(avg_snr_db); - ZERO_OBJECT(avg_rsrp); - ZERO_OBJECT(avg_rsrp_dbm); - ZERO_OBJECT(avg_rsrq_db); - } - cell_state.reset(); + // Reset all measurements + reset_measurements(SRSRAN_MAX_CARRIERS); - reset_neighbour_cells(); + // Reset all SCell states + cell_state.reset(); // Note: Using memset to reset these members is forbidden because they are real objects, not plain arrays. { From 63de6913518d553c1388591033fb5d7597c7562a Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 10 Jun 2021 19:36:41 +0200 Subject: [PATCH 12/31] SRSENB: Added sleep command description --- srsenb/src/main.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index 416444b10..972db6b88 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -458,14 +458,11 @@ static void execute_cmd(metrics_stdout* metrics, srsenb::enb_command_interface* cout << "Usage: " << cmd[0] << " [number of seconds]" << endl; return; } - int nseconds = srsran::string_cast(cmd[1]); if (nseconds <= 0) { return; } - std::this_thread::sleep_for(std::chrono::seconds(nseconds)); - } else if (cmd[0] == "p") { do_padding = !do_padding; if (do_padding) { @@ -493,6 +490,7 @@ static void execute_cmd(metrics_stdout* metrics, srsenb::enb_command_interface* cout << " t: starts console trace" << endl; cout << " q: quit srsenb" << endl; cout << " cell_gain: set relative cell gain" << endl; + cout << " sleep: pauses the commmand line operation for a given time in seconds" << endl; cout << " p: starts MAC padding" << endl; cout << endl; } From 8743713bb12669320392bc56e89ce2db31c1359c Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 10 Jun 2021 19:46:33 +0200 Subject: [PATCH 13/31] Fix compilation --- lib/include/srsran/phy/utils/vector.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/include/srsran/phy/utils/vector.h b/lib/include/srsran/phy/utils/vector.h index 087cb8009..ce8566eb4 100644 --- a/lib/include/srsran/phy/utils/vector.h +++ b/lib/include/srsran/phy/utils/vector.h @@ -51,7 +51,11 @@ extern "C" { #define SRSRAN_VEC_CMA(data, average, n) ((average) + ((data) - (average)) / ((n) + 1)) // Cumulative moving average +#ifdef __cplusplus +#define SRSRAN_VEC_SAFE_CMA(data, average, n) (std::isnormal(average) ? SRSRAN_VEC_CMA(data, average, n) : (data)) +#else #define SRSRAN_VEC_SAFE_CMA(data, average, n) (isnormal(average) ? SRSRAN_VEC_CMA(data, average, n) : (data)) +#endif // Proportional moving average #define SRSRAN_VEC_PMA(average1, n1, average2, n2) (((average1) * (n1) + (average2) * (n2)) / ((n1) + (n2))) @@ -60,7 +64,12 @@ extern "C" { #define SRSRAN_VEC_EMA(data, average, alpha) ((alpha) * (data) + (1 - alpha) * (average)) // Safe exponential moving average +#ifdef __cplusplus +#define SRSRAN_VEC_SAFE_EMA(data, average, alpha) \ + (std::isnormal(average) ? SRSRAN_VEC_EMA(data, average, alpha) : (data)) +#else #define SRSRAN_VEC_SAFE_EMA(data, average, alpha) (isnormal(average) ? SRSRAN_VEC_EMA(data, average, alpha) : (data)) +#endif static inline float srsran_convert_amplitude_to_dB(float v) { From 19f30aa65258dfc58c5a5b4f444c6ba984b8969f Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 11 Jun 2021 12:26:42 +0200 Subject: [PATCH 14/31] rlc_am_lte: fix handling of out-of-order status PDUs before processing incoming status PDUs we should be checking if the ACK_SN falls within our current Tx window. If not the PDU will be dropped. Without the check we were incorrectly processing the status PDU and because the sequence number wrap around wasn't working correctly if ACK_SN is smaller than vt_a we were corrupting our Tx window. --- lib/src/upper/rlc_am_lte.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/src/upper/rlc_am_lte.cc b/lib/src/upper/rlc_am_lte.cc index 25f10284d..afa6c511d 100644 --- a/lib/src/upper/rlc_am_lte.cc +++ b/lib/src/upper/rlc_am_lte.cc @@ -1189,6 +1189,16 @@ void rlc_am_lte::rlc_am_lte_tx::handle_control_pdu(uint8_t* payload, uint32_t no retx_queue.clear(); } + // make sure ACK_SN is within our Tx window + if ((MOD + status.ack_sn - vt_a) % MOD > RLC_AM_WINDOW_SIZE) { + logger.error("%s Received invalid status PDU (ack_sn=%d < vt_a=%d). Dropping PDU.", RB_NAME, status.ack_sn, vt_a); + return; + } + if ((MOD + vt_s - status.ack_sn) % MOD > RLC_AM_WINDOW_SIZE) { + logger.error("%s Received invalid status PDU (ack_sn=%d > vt_s=%d). Dropping PDU.", RB_NAME, status.ack_sn, vt_s); + return; + } + // Handle ACKs and NACKs bool update_vt_a = true; uint32_t i = vt_a; From fa7a8fb687612600fde23a7c89255db2a714f947 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 11 Jun 2021 12:29:06 +0200 Subject: [PATCH 15/31] rlc_am_test: add testcase for processing out-of-order status PDUs --- lib/test/upper/rlc_am_test.cc | 85 +++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/lib/test/upper/rlc_am_test.cc b/lib/test/upper/rlc_am_test.cc index e981fc546..85fcdfcc3 100644 --- a/lib/test/upper/rlc_am_test.cc +++ b/lib/test/upper/rlc_am_test.cc @@ -3359,6 +3359,86 @@ bool incorrect_status_pdu_test() rlc1.write_pdu(status_buf.msg, status_buf.N_bytes); TESTASSERT(tester.protocol_failure_triggered == true); + return SRSRAN_SUCCESS; +} + +/// The test checks the correct detection of an out-of-order status PDUs +/// In contrast to the without explicitly NACK-ing specific SNs +bool incorrect_status_pdu_test2() +{ + rlc_am_tester tester; + srsran::timer_handler timers(8); + int len = 0; + + rlc_am_lte rlc1(srslog::fetch_basic_logger("RLC_AM_1"), 1, &tester, &tester, &timers); + rlc_am_lte rlc2(srslog::fetch_basic_logger("RLC_AM_2"), 1, &tester, &tester, &timers); + + if (not rlc1.configure(rlc_config_t::default_rlc_am_config())) { + return -1; + } + + // Push 5 SDUs into RLC1 + const uint32_t n_sdus = 10; + unique_byte_buffer_t sdu_bufs[n_sdus]; + for (uint32_t i = 0; i < n_sdus; i++) { + sdu_bufs[i] = srsran::make_byte_buffer(); + sdu_bufs[i]->N_bytes = 1; // Give each buffer a size of 1 byte + sdu_bufs[i]->msg[0] = i; // Write the index into the buffer + rlc1.write_sdu(std::move(sdu_bufs[i])); + } + + // Read 5 PDUs from RLC1 (1 byte each) + const uint32_t n_pdus = n_sdus; + byte_buffer_t pdu_bufs[n_pdus]; + for (uint32_t i = 0; i < n_pdus; i++) { + len = rlc1.read_pdu(pdu_bufs[i].msg, 3); // 2 byte header + 1 byte payload + pdu_bufs[i].N_bytes = len; + } + + TESTASSERT(0 == rlc1.get_buffer_state()); + + // Construct a status PDU that ACKs all SNs + rlc_status_pdu_t status_pdu = {}; + status_pdu.ack_sn = 5; + status_pdu.N_nack = 0; + TESTASSERT(rlc_am_is_valid_status_pdu(status_pdu)); + + // pack PDU and write to RLC + byte_buffer_t status_buf; + rlc_am_write_status_pdu(&status_pdu, &status_buf); + rlc1.write_pdu(status_buf.msg, status_buf.N_bytes); + + TESTASSERT(tester.protocol_failure_triggered == false); + + // construct a valid but conflicting status PDU that acks a lower SN and requests SN=1 for retx + status_pdu.ack_sn = 3; + status_pdu.N_nack = 1; + status_pdu.nacks[0].nack_sn = 1; + TESTASSERT(rlc_am_is_valid_status_pdu(status_pdu)); + + // pack and write to RLC again + rlc_am_write_status_pdu(&status_pdu, &status_buf); + rlc1.write_pdu(status_buf.msg, status_buf.N_bytes); + + // the PDU should be dropped + + // resend first Status PDU again + status_pdu.ack_sn = 5; + status_pdu.N_nack = 0; + TESTASSERT(rlc_am_is_valid_status_pdu(status_pdu)); + + // pack and write to RLC again + rlc_am_write_status_pdu(&status_pdu, &status_buf); + rlc1.write_pdu(status_buf.msg, status_buf.N_bytes); + + // now ack all + status_pdu.ack_sn = n_pdus; + status_pdu.N_nack = 0; + TESTASSERT(rlc_am_is_valid_status_pdu(status_pdu)); + + // pack and write to RLC again + rlc_am_write_status_pdu(&status_pdu, &status_buf); + rlc1.write_pdu(status_buf.msg, status_buf.N_bytes); return SRSRAN_SUCCESS; } @@ -3758,6 +3838,11 @@ int main(int argc, char** argv) exit(-1); }; + if (incorrect_status_pdu_test2()) { + printf("incorrect_status_pdu_test2 failed\n"); + exit(-1); + }; + if (discard_test()) { printf("discard_test failed\n"); exit(-1); From e8983b88f032bb8826238a9ff2ce2c86fd95c769 Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 11 Jun 2021 15:13:50 +0100 Subject: [PATCH 16/31] refactor: use enb_cc_idx instead of ue_cc_idx in mac::ue --- .../srsran/interfaces/sched_interface.h | 8 +- srsenb/hdr/stack/mac/mac.h | 4 +- srsenb/hdr/stack/mac/sched.h | 8 +- srsenb/hdr/stack/mac/ue.h | 12 +-- srsenb/src/stack/mac/mac.cc | 28 +++---- srsenb/src/stack/mac/sched.cc | 28 ++++--- srsenb/src/stack/mac/ue.cc | 82 ++++++++++--------- 7 files changed, 83 insertions(+), 87 deletions(-) diff --git a/lib/include/srsran/interfaces/sched_interface.h b/lib/include/srsran/interfaces/sched_interface.h index f526fe56b..a86076a86 100644 --- a/lib/include/srsran/interfaces/sched_interface.h +++ b/lib/include/srsran/interfaces/sched_interface.h @@ -304,10 +304,10 @@ public: virtual int ul_sched(uint32_t tti, uint32_t enb_cc_idx, ul_sched_res_t& sched_result) = 0; /* Custom */ - virtual void set_dl_tti_mask(uint8_t* tti_mask, uint32_t nof_sfs) = 0; - virtual std::array get_enb_ue_cc_map(uint16_t rnti) = 0; - virtual std::array get_scell_activation_mask(uint16_t rnti) = 0; - virtual int ul_buffer_add(uint16_t rnti, uint32_t lcid, uint32_t bytes) = 0; + virtual void set_dl_tti_mask(uint8_t* tti_mask, uint32_t nof_sfs) = 0; + virtual std::array get_enb_ue_cc_map(uint16_t rnti) = 0; + virtual std::array get_enb_ue_activ_cc_map(uint16_t rnti) = 0; + virtual int ul_buffer_add(uint16_t rnti, uint32_t lcid, uint32_t bytes) = 0; }; } // namespace srsenb diff --git a/srsenb/hdr/stack/mac/mac.h b/srsenb/hdr/stack/mac/mac.h index 284b6db3c..f7a8e50e7 100644 --- a/srsenb/hdr/stack/mac/mac.h +++ b/srsenb/hdr/stack/mac/mac.h @@ -105,10 +105,8 @@ public: const uint8_t mcch_payload_length) override; private: - static const uint32_t cfi = 3; - bool check_ue_active(uint16_t rnti); - uint16_t allocate_ue(); + uint16_t allocate_ue(uint32_t enb_cc_idx); bool is_valid_rnti_unprotected(uint16_t rnti); srslog::basic_logger& logger; diff --git a/srsenb/hdr/stack/mac/sched.h b/srsenb/hdr/stack/mac/sched.h index b67d9b9a1..4441a2aca 100644 --- a/srsenb/hdr/stack/mac/sched.h +++ b/srsenb/hdr/stack/mac/sched.h @@ -72,10 +72,10 @@ public: /* Custom functions */ - void set_dl_tti_mask(uint8_t* tti_mask, uint32_t nof_sfs) final; - std::array get_enb_ue_cc_map(uint16_t rnti) final; - std::array get_scell_activation_mask(uint16_t rnti) final; - int ul_buffer_add(uint16_t rnti, uint32_t lcid, uint32_t bytes) final; + void set_dl_tti_mask(uint8_t* tti_mask, uint32_t nof_sfs) final; + std::array get_enb_ue_cc_map(uint16_t rnti) final; + std::array get_enb_ue_activ_cc_map(uint16_t rnti) final; + int ul_buffer_add(uint16_t rnti, uint32_t lcid, uint32_t bytes) final; class carrier_sched; diff --git a/srsenb/hdr/stack/mac/ue.h b/srsenb/hdr/stack/mac/ue.h index 3cce3e59e..3e247b97d 100644 --- a/srsenb/hdr/stack/mac/ue.h +++ b/srsenb/hdr/stack/mac/ue.h @@ -122,7 +122,7 @@ class ue : public srsran::read_pdu_interface, public mac_ta_ue_interface { public: ue(uint16_t rnti, - uint32_t nof_prb, + uint32_t enb_cc_idx, sched_interface* sched, rrc_interface_mac* rrc_, rlc_interface_mac* rlc, @@ -145,7 +145,7 @@ public: void set_active(bool active) { active_state.store(active, std::memory_order_relaxed); } bool is_active() const { return active_state.load(std::memory_order_relaxed); } - uint8_t* generate_pdu(uint32_t ue_cc_idx, + uint8_t* generate_pdu(uint32_t enb_cc_idx, uint32_t harq_pid, uint32_t tb_idx, const sched_interface::dl_sched_pdu_t pdu[sched_interface::MAX_RLC_PDU_LIST], @@ -154,12 +154,12 @@ public: uint8_t* generate_mch_pdu(uint32_t harq_pid, sched_interface::dl_pdu_mch_t sched, uint32_t nof_pdu_elems, uint32_t grant_size); - srsran_softbuffer_tx_t* get_tx_softbuffer(uint32_t ue_cc_idx, uint32_t harq_process, uint32_t tb_idx); - srsran_softbuffer_rx_t* get_rx_softbuffer(uint32_t ue_cc_idx, uint32_t tti); + srsran_softbuffer_tx_t* get_tx_softbuffer(uint32_t enb_cc_idx, uint32_t harq_process, uint32_t tb_idx); + srsran_softbuffer_rx_t* get_rx_softbuffer(uint32_t enb_cc_idx, uint32_t tti); - uint8_t* request_buffer(uint32_t tti, uint32_t ue_cc_idx, const uint32_t len); + uint8_t* request_buffer(uint32_t tti, uint32_t enb_cc_idx, uint32_t len); void process_pdu(srsran::unique_byte_buffer_t pdu, uint32_t grant_nof_prbs); - srsran::unique_byte_buffer_t release_pdu(uint32_t tti, uint32_t ue_cc_idx); + srsran::unique_byte_buffer_t release_pdu(uint32_t tti, uint32_t enb_cc_idx); void clear_old_buffers(uint32_t tti); void metrics_read(mac_ue_metrics_t* metrics_); diff --git a/srsenb/src/stack/mac/mac.cc b/srsenb/src/stack/mac/mac.cc index a97224bac..2a2c246a2 100644 --- a/srsenb/src/stack/mac/mac.cc +++ b/srsenb/src/stack/mac/mac.cc @@ -314,14 +314,7 @@ int mac::push_pdu(uint32_t tti_rx, return SRSRAN_ERROR; } - std::array enb_ue_cc_map = scheduler.get_enb_ue_cc_map(rnti); - if (enb_ue_cc_map[enb_cc_idx] < 0) { - logger.error("User rnti=0x%x is not activated for carrier %d", rnti, enb_cc_idx); - return SRSRAN_ERROR; - } - uint32_t ue_cc_idx = enb_ue_cc_map[enb_cc_idx]; - - srsran::unique_byte_buffer_t pdu = ue_db[rnti]->release_pdu(tti_rx, ue_cc_idx); + srsran::unique_byte_buffer_t pdu = ue_db[rnti]->release_pdu(tti_rx, enb_cc_idx); if (pdu == nullptr) { logger.warning("Could not find MAC UL PDU for rnti=0x%x, cc=%d, tti=%d", rnti, enb_cc_idx, tti_rx); return SRSRAN_ERROR; @@ -454,7 +447,7 @@ bool mac::is_valid_rnti_unprotected(uint16_t rnti) return true; } -uint16_t mac::allocate_ue() +uint16_t mac::allocate_ue(uint32_t enb_cc_idx) { ue* inserted_ue = nullptr; uint16_t rnti = SRSRAN_INVALID_RNTI; @@ -473,7 +466,7 @@ uint16_t mac::allocate_ue() // Allocate and initialize UE object unique_rnti_ptr ue_ptr = make_rnti_obj( - rnti, rnti, args.nof_prb, &scheduler, rrc_h, rlc_h, phy_h, logger, cells.size(), softbuffer_pool.get()); + rnti, rnti, enb_cc_idx, &scheduler, rrc_h, rlc_h, phy_h, logger, cells.size(), softbuffer_pool.get()); // Add UE to rnti map srsran::rwlock_write_guard rw_lock(rwlock); @@ -502,7 +495,7 @@ uint16_t mac::allocate_ue() uint16_t mac::reserve_new_crnti(const sched_interface::ue_cfg_t& ue_cfg) { - uint16_t rnti = allocate_ue(); + uint16_t rnti = allocate_ue(ue_cfg.supported_cc_list[0].enb_cc_idx); if (rnti == SRSRAN_INVALID_RNTI) { return rnti; } @@ -523,7 +516,7 @@ void mac::rach_detected(uint32_t tti, uint32_t enb_cc_idx, uint32_t preamble_idx auto rach_tprof_meas = rach_tprof.start(); stack_task_queue.push([this, tti, enb_cc_idx, preamble_idx, time_adv, rach_tprof_meas]() mutable { - uint16_t rnti = allocate_ue(); + uint16_t rnti = allocate_ue(enb_cc_idx); if (rnti == SRSRAN_INVALID_RNTI) { return; } @@ -612,7 +605,7 @@ int mac::get_dl_sched(uint32_t tti_tx_dl, dl_sched_list_t& dl_sched_res_list) for (uint32_t tb = 0; tb < SRSRAN_MAX_TB; tb++) { dl_sched_res->pdsch[n].softbuffer_tx[tb] = - ue_db[rnti]->get_tx_softbuffer(sched_result.data[i].dci.ue_cc_idx, sched_result.data[i].dci.pid, tb); + ue_db[rnti]->get_tx_softbuffer(enb_cc_idx, sched_result.data[i].dci.pid, tb); // If the Rx soft-buffer is not given, abort transmission if (dl_sched_res->pdsch[n].softbuffer_tx[tb] == nullptr) { @@ -621,7 +614,7 @@ int mac::get_dl_sched(uint32_t tti_tx_dl, dl_sched_list_t& dl_sched_res_list) if (sched_result.data[i].nof_pdu_elems[tb] > 0) { /* Get PDU if it's a new transmission */ - dl_sched_res->pdsch[n].data[tb] = ue_db[rnti]->generate_pdu(sched_result.data[i].dci.ue_cc_idx, + dl_sched_res->pdsch[n].data[tb] = ue_db[rnti]->generate_pdu(enb_cc_idx, sched_result.data[i].dci.pid, tb, sched_result.data[i].pdu[tb], @@ -927,8 +920,7 @@ int mac::get_ul_sched(uint32_t tti_tx_ul, ul_sched_list_t& ul_sched_res_list) phy_ul_sched_res->pusch[n].pid = TTI_RX(tti_tx_ul) % SRSRAN_FDD_NOF_HARQ; phy_ul_sched_res->pusch[n].needs_pdcch = sched_result.pusch[i].needs_pdcch; phy_ul_sched_res->pusch[n].dci = sched_result.pusch[i].dci; - phy_ul_sched_res->pusch[n].softbuffer_rx = - ue_db[rnti]->get_rx_softbuffer(sched_result.pusch[i].dci.ue_cc_idx, tti_tx_ul); + phy_ul_sched_res->pusch[n].softbuffer_rx = ue_db[rnti]->get_rx_softbuffer(enb_cc_idx, tti_tx_ul); // If the Rx soft-buffer is not given, abort reception if (phy_ul_sched_res->pusch[n].softbuffer_rx == nullptr) { @@ -939,7 +931,7 @@ int mac::get_ul_sched(uint32_t tti_tx_ul, ul_sched_list_t& ul_sched_res_list) srsran_softbuffer_rx_reset_tbs(phy_ul_sched_res->pusch[n].softbuffer_rx, sched_result.pusch[i].tbs * 8); } phy_ul_sched_res->pusch[n].data = - ue_db[rnti]->request_buffer(tti_tx_ul, sched_result.pusch[i].dci.ue_cc_idx, sched_result.pusch[i].tbs); + ue_db[rnti]->request_buffer(tti_tx_ul, enb_cc_idx, sched_result.pusch[i].tbs); if (phy_ul_sched_res->pusch[n].data) { phy_ul_sched_res->nof_grants++; } else { @@ -986,7 +978,7 @@ void mac::write_mcch(const srsran::sib2_mbms_t* sib2_, memcpy(mcch_payload_buffer, mcch_payload, mcch_payload_length * sizeof(uint8_t)); current_mcch_length = mcch_payload_length; ue_db[SRSRAN_MRNTI] = std::unique_ptr{ - new ue(SRSRAN_MRNTI, args.nof_prb, &scheduler, rrc_h, rlc_h, phy_h, logger, cells.size(), softbuffer_pool.get())}; + new ue(SRSRAN_MRNTI, 0, &scheduler, rrc_h, rlc_h, phy_h, logger, cells.size(), softbuffer_pool.get())}; rrc_h->add_user(SRSRAN_MRNTI, {}); } diff --git a/srsenb/src/stack/mac/sched.cc b/srsenb/src/stack/mac/sched.cc index 833b0c389..fc7040163 100644 --- a/srsenb/src/stack/mac/sched.cc +++ b/srsenb/src/stack/mac/sched.cc @@ -267,18 +267,22 @@ std::array sched::get_enb_ue_cc_map(uint16_t rnti) return ret; } -std::array sched::get_scell_activation_mask(uint16_t rnti) -{ - std::array scell_mask = {}; - ue_db_access_locked(rnti, [this, &scell_mask](sched_ue& ue) { - for (size_t enb_cc_idx = 0; enb_cc_idx < carrier_schedulers.size(); ++enb_cc_idx) { - const sched_ue_cell* cc_ue = ue.find_ue_carrier(enb_cc_idx); - if (cc_ue != nullptr and (cc_ue->cc_state() == cc_st::active or cc_ue->cc_state() == cc_st::activating)) { - scell_mask[cc_ue->get_ue_cc_idx()] = true; - } - } - }); - return scell_mask; +std::array sched::get_enb_ue_activ_cc_map(uint16_t rnti) +{ + std::array ret{}; + ret.fill(-1); // -1 for inactive & non-existent carriers + ue_db_access_locked( + rnti, + [this, &ret](sched_ue& ue) { + for (size_t enb_cc_idx = 0; enb_cc_idx < carrier_schedulers.size(); ++enb_cc_idx) { + const sched_ue_cell* cc_ue = ue.find_ue_carrier(enb_cc_idx); + if (cc_ue != nullptr and (cc_ue->cc_state() == cc_st::active or cc_ue->cc_state() == cc_st::activating)) { + ret[enb_cc_idx] = cc_ue->get_ue_cc_idx(); + } + } + }, + __PRETTY_FUNCTION__); + return ret; } /******************************************************* diff --git a/srsenb/src/stack/mac/ue.cc b/srsenb/src/stack/mac/ue.cc index 426e907ed..00e8c9287 100644 --- a/srsenb/src/stack/mac/ue.cc +++ b/srsenb/src/stack/mac/ue.cc @@ -173,7 +173,7 @@ void cc_buffer_handler::reset() } ue::ue(uint16_t rnti_, - uint32_t nof_prb_, + uint32_t enb_cc_idx, sched_interface* sched_, rrc_interface_mac* rrc_, rlc_interface_mac* rlc_, @@ -195,7 +195,7 @@ ue::ue(uint16_t rnti_, cc_buffers(nof_cells_) { // Allocate buffer for PCell - cc_buffers[0].allocate_cc(softbuffer_pool->make()); + cc_buffers[enb_cc_idx].allocate_cc(softbuffer_pool->make()); } ue::~ue() {} @@ -220,31 +220,31 @@ void ue::start_pcap(srsran::mac_pcap* pcap_) pcap = pcap_; } -srsran_softbuffer_rx_t* ue::get_rx_softbuffer(uint32_t ue_cc_idx, uint32_t tti) +srsran_softbuffer_rx_t* ue::get_rx_softbuffer(uint32_t enb_cc_idx, uint32_t tti) { - if ((size_t)ue_cc_idx >= cc_buffers.size()) { - ERROR("UE CC Index (%d/%zd) out-of-range", ue_cc_idx, cc_buffers.size()); + if ((size_t)enb_cc_idx >= cc_buffers.size() or cc_buffers[enb_cc_idx].empty()) { + ERROR("eNB CC Index (%d/%zd) out-of-range", enb_cc_idx, cc_buffers.size()); return nullptr; } - return &cc_buffers[ue_cc_idx].get_rx_softbuffer(tti); + return &cc_buffers[enb_cc_idx].get_rx_softbuffer(tti); } -srsran_softbuffer_tx_t* ue::get_tx_softbuffer(uint32_t ue_cc_idx, uint32_t harq_process, uint32_t tb_idx) +srsran_softbuffer_tx_t* ue::get_tx_softbuffer(uint32_t enb_cc_idx, uint32_t harq_process, uint32_t tb_idx) { - if ((size_t)ue_cc_idx >= cc_buffers.size()) { - ERROR("UE CC Index (%d/%zd) out-of-range", ue_cc_idx, cc_buffers.size()); + if ((size_t)enb_cc_idx >= cc_buffers.size() or cc_buffers[enb_cc_idx].empty()) { + ERROR("eNB CC Index (%d/%zd) out-of-range", enb_cc_idx, cc_buffers.size()); return nullptr; } - return &cc_buffers[ue_cc_idx].get_tx_softbuffer(harq_process, tb_idx); + return &cc_buffers[enb_cc_idx].get_tx_softbuffer(harq_process, tb_idx); } -uint8_t* ue::request_buffer(uint32_t tti, uint32_t ue_cc_idx, const uint32_t len) +uint8_t* ue::request_buffer(uint32_t tti, uint32_t enb_cc_idx, uint32_t len) { srsran_assert(len > 0, "UE buffers: Requesting buffer for zero bytes"); std::unique_lock lock(rx_buffers_mutex); - return cc_buffers[ue_cc_idx].get_rx_used_buffers().request_pdu(tti_point(tti), len); + return cc_buffers[enb_cc_idx].get_rx_used_buffers().request_pdu(tti_point(tti), len); } void ue::clear_old_buffers(uint32_t tti) @@ -377,10 +377,10 @@ void ue::process_pdu(srsran::unique_byte_buffer_t pdu, uint32_t grant_nof_prbs) logger.debug("MAC PDU processed"); } -srsran::unique_byte_buffer_t ue::release_pdu(uint32_t tti, uint32_t ue_cc_idx) +srsran::unique_byte_buffer_t ue::release_pdu(uint32_t tti, uint32_t enb_cc_idx) { std::lock_guard lock(rx_buffers_mutex); - return cc_buffers[ue_cc_idx].get_rx_used_buffers().release_pdu(tti_point(tti)); + return cc_buffers[enb_cc_idx].get_rx_used_buffers().release_pdu(tti_point(tti)); } bool ue::process_ce(srsran::sch_subh* subh, uint32_t grant_nof_prbs) @@ -500,13 +500,19 @@ void ue::allocate_ce(srsran::sch_pdu* pdu, uint32_t lcid) break; case srsran::dl_sch_lcid::SCELL_ACTIVATION: if (pdu->new_subh()) { - std::array active_scell_list = sched->get_scell_activation_mask(rnti); + std::array active_ccs = sched->get_enb_ue_activ_cc_map(rnti); + std::array active_scell_list{}; + for (int ue_cc_idx : active_ccs) { + if (ue_cc_idx > 0) { + active_scell_list[ue_cc_idx] = true; + } + } if (pdu->get()->set_scell_activation_cmd(active_scell_list)) { phy->set_activation_deactivation_scell(rnti, active_scell_list); // Allocate and initialize Rx/Tx softbuffers for new carriers (exclude PCell) - for (size_t i = 0; i < std::min(active_scell_list.size(), cc_buffers.size()); ++i) { - if (active_scell_list[i] and cc_buffers[i].empty()) { - cc_buffers[i].allocate_cc(softbuffer_pool->make()); + for (size_t cc = 0; cc < cc_buffers.size(); ++cc) { + if (active_ccs[cc] >= 0 and cc_buffers[cc].empty()) { + cc_buffers[cc].allocate_cc(softbuffer_pool->make()); } } } else { @@ -522,7 +528,7 @@ void ue::allocate_ce(srsran::sch_pdu* pdu, uint32_t lcid) } } -uint8_t* ue::generate_pdu(uint32_t ue_cc_idx, +uint8_t* ue::generate_pdu(uint32_t enb_cc_idx, uint32_t harq_pid, uint32_t tb_idx, const sched_interface::dl_sched_pdu_t pdu[sched_interface::MAX_RLC_PDU_LIST], @@ -531,30 +537,26 @@ uint8_t* ue::generate_pdu(uint32_t ue_cc_idx, { std::lock_guard lock(mutex); uint8_t* ret = nullptr; - if (rlc) { - if (ue_cc_idx < SRSRAN_MAX_CARRIERS && harq_pid < SRSRAN_FDD_NOF_HARQ && tb_idx < SRSRAN_MAX_TB) { - srsran::byte_buffer_t* buffer = cc_buffers[ue_cc_idx].get_tx_payload_buffer(harq_pid, tb_idx); - buffer->clear(); - mac_msg_dl.init_tx(buffer, grant_size, false); - for (uint32_t i = 0; i < nof_pdu_elems; i++) { - if (pdu[i].lcid <= (uint32_t)srsran::ul_sch_lcid::PHR_REPORT) { - allocate_sdu(&mac_msg_dl, pdu[i].lcid, pdu[i].nbytes); - } else { - allocate_ce(&mac_msg_dl, pdu[i].lcid); - } - } - ret = mac_msg_dl.write_packet(logger); - if (logger.info.enabled()) { - fmt::memory_buffer str_buffer; - mac_msg_dl.to_string(str_buffer); - logger.info("0x%x %s", rnti, srsran::to_c_str(str_buffer)); + if (enb_cc_idx < SRSRAN_MAX_CARRIERS && harq_pid < SRSRAN_FDD_NOF_HARQ && tb_idx < SRSRAN_MAX_TB) { + srsran::byte_buffer_t* buffer = cc_buffers[enb_cc_idx].get_tx_payload_buffer(harq_pid, tb_idx); + buffer->clear(); + mac_msg_dl.init_tx(buffer, grant_size, false); + for (uint32_t i = 0; i < nof_pdu_elems; i++) { + if (pdu[i].lcid <= (uint32_t)srsran::ul_sch_lcid::PHR_REPORT) { + allocate_sdu(&mac_msg_dl, pdu[i].lcid, pdu[i].nbytes); + } else { + allocate_ce(&mac_msg_dl, pdu[i].lcid); } - } else { - logger.error( - "Invalid parameters calling generate_pdu: cc_idx=%d, harq_pid=%d, tb_idx=%d", ue_cc_idx, harq_pid, tb_idx); + } + ret = mac_msg_dl.write_packet(logger); + if (logger.info.enabled()) { + fmt::memory_buffer str_buffer; + mac_msg_dl.to_string(str_buffer); + logger.info("0x%x %s", rnti, srsran::to_c_str(str_buffer)); } } else { - std::cout << "Error ue not configured (must call config() first" << std::endl; + logger.error( + "Invalid parameters calling generate_pdu: cc_idx=%d, harq_pid=%d, tb_idx=%d", enb_cc_idx, harq_pid, tb_idx); } return ret; } From f55e1c5a734ae301e0efb0aacddae0dbb89423d4 Mon Sep 17 00:00:00 2001 From: Francisco Date: Mon, 14 Jun 2021 11:29:55 +0100 Subject: [PATCH 17/31] fix,srsenb: start stack before the radio to avoid stack methods to be called when stack is not fully initialized --- srsenb/hdr/stack/enb_stack_lte.h | 2 +- srsenb/src/enb.cc | 16 ++++++++-------- srsenb/src/stack/enb_stack_lte.cc | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/srsenb/hdr/stack/enb_stack_lte.h b/srsenb/hdr/stack/enb_stack_lte.h index 6e0ef91ec..0cd47e7db 100644 --- a/srsenb/hdr/stack/enb_stack_lte.h +++ b/srsenb/hdr/stack/enb_stack_lte.h @@ -140,7 +140,7 @@ private: phy_interface_stack_lte* phy = nullptr; // state - bool started = false; + std::atomic started{false}; srsran::dyn_blocking_queue pending_stack_metrics; }; diff --git a/srsenb/src/enb.cc b/srsenb/src/enb.cc index 004f81025..ef041c38f 100644 --- a/srsenb/src/enb.cc +++ b/srsenb/src/enb.cc @@ -70,6 +70,14 @@ int enb::init(const all_args_t& args_) return SRSRAN_ERROR; } + // Only init Stack if both radio and PHY could be initialized + if (ret == SRSRAN_SUCCESS) { + if (lte_stack->init(args.stack, rrc_cfg, lte_phy.get()) != SRSRAN_SUCCESS) { + srsran::console("Error initializing stack.\n"); + ret = SRSRAN_ERROR; + } + } + // Init Radio if (lte_radio->init(args.rf, lte_phy.get())) { srsran::console("Error initializing radio.\n"); @@ -84,14 +92,6 @@ int enb::init(const all_args_t& args_) } } - // Only init Stack if both radio and PHY could be initialized - if (ret == SRSRAN_SUCCESS) { - if (lte_stack->init(args.stack, rrc_cfg, lte_phy.get()) != SRSRAN_SUCCESS) { - srsran::console("Error initializing stack.\n"); - ret = SRSRAN_ERROR; - } - } - stack = std::move(lte_stack); phy = std::move(lte_phy); radio = std::move(lte_radio); diff --git a/srsenb/src/stack/enb_stack_lte.cc b/srsenb/src/stack/enb_stack_lte.cc index c98db892f..84cb4997b 100644 --- a/srsenb/src/stack/enb_stack_lte.cc +++ b/srsenb/src/stack/enb_stack_lte.cc @@ -226,7 +226,7 @@ bool enb_stack_lte::get_metrics(stack_metrics_t* metrics) void enb_stack_lte::run_thread() { - while (started) { + while (started.load(std::memory_order_relaxed)) { task_sched.run_next_task(); } } From 4cf5a8b25aa04581ac9e7fd036ee040ad5dab95f Mon Sep 17 00:00:00 2001 From: Francisco Date: Mon, 14 Jun 2021 12:21:38 +0100 Subject: [PATCH 18/31] fix: avoid configuring the phy mbsfn from the rrc, when phy is not fully initialized --- srsenb/src/enb.cc | 1 - srsenb/src/stack/rrc/rrc.cc | 8 ++++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/srsenb/src/enb.cc b/srsenb/src/enb.cc index ef041c38f..1d81bc0e9 100644 --- a/srsenb/src/enb.cc +++ b/srsenb/src/enb.cc @@ -70,7 +70,6 @@ int enb::init(const all_args_t& args_) return SRSRAN_ERROR; } - // Only init Stack if both radio and PHY could be initialized if (ret == SRSRAN_SUCCESS) { if (lte_stack->init(args.stack, rrc_cfg, lte_phy.get()) != SRSRAN_SUCCESS) { srsran::console("Error initializing stack.\n"); diff --git a/srsenb/src/stack/rrc/rrc.cc b/srsenb/src/stack/rrc/rrc.cc index 428f840ad..d1717cf94 100644 --- a/srsenb/src/stack/rrc/rrc.cc +++ b/srsenb/src/stack/rrc/rrc.cc @@ -848,8 +848,12 @@ void rrc::configure_mbsfn_sibs() pmch_item->data_mcs = mbms_mcs; pmch_item->mch_sched_period = srsran::pmch_info_t::mch_sched_period_t::rf64; pmch_item->sf_alloc_end = 64 * 6; - phy->configure_mbsfn(&sibs2, &sibs13, mcch_t); - mac->write_mcch(&sibs2, &sibs13, &mcch_t, mcch_payload_buffer, current_mcch_length); + + // Configure PHY when PHY is done being initialized + task_sched.defer_task([this, sibs2, sibs13, mcch_t]() mutable { + phy->configure_mbsfn(&sibs2, &sibs13, mcch_t); + mac->write_mcch(&sibs2, &sibs13, &mcch_t, mcch_payload_buffer, current_mcch_length); + }); } int rrc::pack_mcch() From 6ababf401b7103aa221a55f7ec4281a9783f3829 Mon Sep 17 00:00:00 2001 From: Francisco Date: Thu, 10 Jun 2021 16:02:18 +0100 Subject: [PATCH 19/31] feature,sched: allow setting initial DL CQI in enb.conf --- lib/include/srsran/interfaces/enb_rrc_interface_types.h | 1 - lib/include/srsran/interfaces/sched_interface.h | 2 +- srsenb/enb.conf.example | 2 ++ srsenb/src/enb_cfg_parser.cc | 1 - srsenb/src/main.cc | 1 + srsenb/src/stack/mac/sched_ue_ctrl/sched_ue_cell.cc | 6 ++---- srsenb/src/stack/rrc/rrc.cc | 1 - srsenb/test/mac/sched_test_utils.h | 1 - 8 files changed, 6 insertions(+), 9 deletions(-) diff --git a/lib/include/srsran/interfaces/enb_rrc_interface_types.h b/lib/include/srsran/interfaces/enb_rrc_interface_types.h index f5d6f4497..443c873f0 100644 --- a/lib/include/srsran/interfaces/enb_rrc_interface_types.h +++ b/lib/include/srsran/interfaces/enb_rrc_interface_types.h @@ -59,7 +59,6 @@ struct cell_cfg_t { double ul_freq_hz; int target_pucch_sinr_db; int target_pusch_sinr_db; - uint32_t initial_dl_cqi; bool enable_phr_handling; int min_phr_thres; asn1::rrc::mob_ctrl_info_s::t304_e_ t304; diff --git a/lib/include/srsran/interfaces/sched_interface.h b/lib/include/srsran/interfaces/sched_interface.h index a86076a86..5155887d9 100644 --- a/lib/include/srsran/interfaces/sched_interface.h +++ b/lib/include/srsran/interfaces/sched_interface.h @@ -64,6 +64,7 @@ public: uint32_t min_tpc_tti_interval = 1; float ul_snr_avg_alpha = 0.05; int init_ul_snr_value = 5; + int init_dl_cqi = 5; }; struct cell_cfg_t { @@ -100,7 +101,6 @@ public: uint32_t nrb_cqi; uint32_t ncs_an; - uint32_t initial_dl_cqi; uint32_t srs_subframe_config; uint32_t srs_subframe_offset; diff --git a/srsenb/enb.conf.example b/srsenb/enb.conf.example index c656f6a55..cd64805c6 100644 --- a/srsenb/enb.conf.example +++ b/srsenb/enb.conf.example @@ -176,6 +176,7 @@ enable = false # min_tpc_tti_interval: Minimum TTI interval between TPCs different than 1 # ul_snr_avg_alpha: Exponential Average alpha coefficient used in estimation of UL SNR # init_ul_snr_value: Initial UL SNR value used for computing MCS in the first UL grant +# init_dl_cqi: DL CQI value used before any CQI report is available to the eNB # ##################################################################### [scheduler] @@ -198,6 +199,7 @@ enable = false #min_tpc_tti_interval = 1 #ul_snr_avg_alpha=0.05 #init_ul_snr_value=5 +#init_dl_cqi=5 ##################################################################### # eMBMS configuration options diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index cd48cc887..49dda24e2 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -758,7 +758,6 @@ static int parse_cell_list(all_args_t* args, rrc_cfg_t* rrc_cfg, Setting& root) parse_default_field(cell_cfg.ul_earfcn, cellroot, "ul_earfcn", 0u); // will be derived from DL EARFCN If not set parse_default_field( cell_cfg.root_seq_idx, cellroot, "root_seq_idx", rrc_cfg->sibs[1].sib2().rr_cfg_common.prach_cfg.root_seq_idx); - parse_default_field(cell_cfg.initial_dl_cqi, cellroot, "initial_dl_cqi", 5u); parse_default_field(cell_cfg.meas_cfg.meas_gap_period, cellroot, "meas_gap_period", 0u); if (cellroot.exists("meas_gap_offset_subframe")) { cell_cfg.meas_cfg.meas_gap_offset_subframe.resize(cellroot["meas_gap_offset_subframe"].getLength()); diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index 972db6b88..8ebf978b3 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -158,6 +158,7 @@ void parse_args(all_args_t* args, int argc, char* argv[]) ("scheduler.min_tpc_tti_interval", bpo::value(&args->stack.mac.sched.min_tpc_tti_interval)->default_value(1), "Minimum TTI interval between positive or negative TPCs") ("scheduler.ul_snr_avg_alpha", bpo::value(&args->stack.mac.sched.ul_snr_avg_alpha)->default_value(0.05), "Exponential Average alpha coefficient used in estimation of UL SNR") ("scheduler.init_ul_snr_value", bpo::value(&args->stack.mac.sched.init_ul_snr_value)->default_value(5), "Initial UL SNR value used for computing MCS in the first UL grant") + ("scheduler.init_dl_cqi", bpo::value(&args->stack.mac.sched.init_dl_cqi)->default_value(5), "DL CQI value used before any CQI report is available to the eNB") /* Downlink Channel emulator section */ diff --git a/srsenb/src/stack/mac/sched_ue_ctrl/sched_ue_cell.cc b/srsenb/src/stack/mac/sched_ue_ctrl/sched_ue_cell.cc index ba600ed03..f3add09f4 100644 --- a/srsenb/src/stack/mac/sched_ue_ctrl/sched_ue_cell.cc +++ b/srsenb/src/stack/mac/sched_ue_ctrl/sched_ue_cell.cc @@ -48,10 +48,8 @@ sched_ue_cell::sched_ue_cell(uint16_t rnti_, const sched_cell_params_t& cell_cfg fixed_mcs_ul(cell_cfg_.sched_cfg->pusch_mcs), current_tti(current_tti_), max_aggr_level(cell_cfg_.sched_cfg->max_aggr_level >= 0 ? cell_cfg_.sched_cfg->max_aggr_level : 3), - dl_cqi_ctxt(cell_cfg_.nof_prb(), 0, 1) + dl_cqi_ctxt(cell_cfg_.nof_prb(), 0, cell_cfg_.sched_cfg->init_dl_cqi) { - clear_feedback(); - float target_bler = cell_cfg->sched_cfg->target_bler; delta_inc = cell_cfg->sched_cfg->adaptive_link_step_size; // delta_{down} of OLLA delta_dec = (1 - target_bler) * delta_inc / target_bler; @@ -157,7 +155,7 @@ void sched_ue_cell::clear_feedback() dl_ri_tti_rx = tti_point{}; dl_pmi = 0; dl_pmi_tti_rx = tti_point{}; - dl_cqi_ctxt.reset_cqi(ue_cc_idx == 0 ? cell_cfg->cfg.initial_dl_cqi : 1); + dl_cqi_ctxt.reset_cqi(ue_cc_idx == 0 ? cell_cfg->sched_cfg->init_dl_cqi : 1); ul_cqi_tti_rx = tti_point{}; } diff --git a/srsenb/src/stack/rrc/rrc.cc b/srsenb/src/stack/rrc/rrc.cc index d1717cf94..eedc915a8 100644 --- a/srsenb/src/stack/rrc/rrc.cc +++ b/srsenb/src/stack/rrc/rrc.cc @@ -646,7 +646,6 @@ void rrc::config_mac() item.prach_freq_offset = cfg.sibs[1].sib2().rr_cfg_common.prach_cfg.prach_cfg_info.prach_freq_offset; item.maxharq_msg3tx = cfg.sibs[1].sib2().rr_cfg_common.rach_cfg_common.max_harq_msg3_tx; item.enable_64qam = cfg.sibs[1].sib2().rr_cfg_common.pusch_cfg_common.pusch_cfg_basic.enable64_qam; - item.initial_dl_cqi = cfg.cell_list[ccidx].initial_dl_cqi; item.target_pucch_ul_sinr = cfg.cell_list[ccidx].target_pucch_sinr_db; item.target_pusch_ul_sinr = cfg.cell_list[ccidx].target_pusch_sinr_db; item.enable_phr_handling = cfg.cell_list[ccidx].enable_phr_handling; diff --git a/srsenb/test/mac/sched_test_utils.h b/srsenb/test/mac/sched_test_utils.h index f21734ce0..ed1745ef2 100644 --- a/srsenb/test/mac/sched_test_utils.h +++ b/srsenb/test/mac/sched_test_utils.h @@ -49,7 +49,6 @@ inline srsenb::sched_interface::cell_cfg_t generate_default_cell_cfg(uint32_t no cell_cfg.prach_freq_offset = (cell_cfg_phy.nof_prb == 6) ? 0 : 4; cell_cfg.prach_rar_window = 3; cell_cfg.maxharq_msg3tx = 3; - cell_cfg.initial_dl_cqi = 6; cell_cfg.target_pusch_ul_sinr = -1; cell_cfg.target_pucch_ul_sinr = -1; cell_cfg.enable_phr_handling = false; From 2a009eb340a7bf458df2c4f3f650ecf16868f9f8 Mon Sep 17 00:00:00 2001 From: Francisco Date: Thu, 10 Jun 2021 13:02:10 +0100 Subject: [PATCH 20/31] sched,feature: Enable configuring maximum coderate for SIB allocations --- lib/include/srsran/interfaces/sched_interface.h | 1 + srsenb/enb.conf.example | 2 ++ srsenb/src/main.cc | 1 + srsenb/src/stack/mac/sched_phy_ch/sched_dci.cc | 4 ++-- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/include/srsran/interfaces/sched_interface.h b/lib/include/srsran/interfaces/sched_interface.h index 5155887d9..e9549b244 100644 --- a/lib/include/srsran/interfaces/sched_interface.h +++ b/lib/include/srsran/interfaces/sched_interface.h @@ -65,6 +65,7 @@ public: float ul_snr_avg_alpha = 0.05; int init_ul_snr_value = 5; int init_dl_cqi = 5; + float max_sib_coderate = 0.8; }; struct cell_cfg_t { diff --git a/srsenb/enb.conf.example b/srsenb/enb.conf.example index cd64805c6..1a7cfa492 100644 --- a/srsenb/enb.conf.example +++ b/srsenb/enb.conf.example @@ -177,6 +177,7 @@ enable = false # ul_snr_avg_alpha: Exponential Average alpha coefficient used in estimation of UL SNR # init_ul_snr_value: Initial UL SNR value used for computing MCS in the first UL grant # init_dl_cqi: DL CQI value used before any CQI report is available to the eNB +# max_sib_coderate: Upper bound on SIB and RAR grants coderate # ##################################################################### [scheduler] @@ -200,6 +201,7 @@ enable = false #ul_snr_avg_alpha=0.05 #init_ul_snr_value=5 #init_dl_cqi=5 +#max_sib_coderate=0.8 ##################################################################### # eMBMS configuration options diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index 8ebf978b3..1d9119457 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -159,6 +159,7 @@ void parse_args(all_args_t* args, int argc, char* argv[]) ("scheduler.ul_snr_avg_alpha", bpo::value(&args->stack.mac.sched.ul_snr_avg_alpha)->default_value(0.05), "Exponential Average alpha coefficient used in estimation of UL SNR") ("scheduler.init_ul_snr_value", bpo::value(&args->stack.mac.sched.init_ul_snr_value)->default_value(5), "Initial UL SNR value used for computing MCS in the first UL grant") ("scheduler.init_dl_cqi", bpo::value(&args->stack.mac.sched.init_dl_cqi)->default_value(5), "DL CQI value used before any CQI report is available to the eNB") + ("scheduler.max_sib_coderate", bpo::value(&args->stack.mac.sched.max_sib_coderate)->default_value(0.8), "Upper bound on SIB and RAR grants coderate") /* Downlink Channel emulator section */ diff --git a/srsenb/src/stack/mac/sched_phy_ch/sched_dci.cc b/srsenb/src/stack/mac/sched_phy_ch/sched_dci.cc index 2df511b97..3756b9438 100644 --- a/srsenb/src/stack/mac/sched_phy_ch/sched_dci.cc +++ b/srsenb/src/stack/mac/sched_phy_ch/sched_dci.cc @@ -189,8 +189,8 @@ int generate_ra_bc_dci_format1a_common(srsran_dci_dl_t& dci, const sched_cell_params_t& cell_params, uint32_t current_cfi) { - static const uint32_t Qm = 2, bc_rar_cqi = 4; - static const float max_ctrl_coderate = std::min(srsran_cqi_to_coderate(bc_rar_cqi + 1, false), 0.932F * Qm); + static const uint32_t Qm = 2; + static const float max_ctrl_coderate = std::min(cell_params.sched_cfg->max_sib_coderate, 0.932F * Qm); // Calculate I_tbs for this TBS int tbs = static_cast(req_bytes) * 8; From c111b23255bbc78be528d68f1586f8c287a90269 Mon Sep 17 00:00:00 2001 From: Francisco Date: Mon, 14 Jun 2021 16:15:20 +0100 Subject: [PATCH 21/31] config,enb: change the max sib coderate to 0.3 --- srsenb/enb.conf.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsenb/enb.conf.example b/srsenb/enb.conf.example index 1a7cfa492..36b3ee83e 100644 --- a/srsenb/enb.conf.example +++ b/srsenb/enb.conf.example @@ -201,7 +201,7 @@ enable = false #ul_snr_avg_alpha=0.05 #init_ul_snr_value=5 #init_dl_cqi=5 -#max_sib_coderate=0.8 +#max_sib_coderate=0.3 ##################################################################### # eMBMS configuration options From 9139f88b31f8922435334d6d84406a1bdbf7e2d1 Mon Sep 17 00:00:00 2001 From: Francisco Date: Mon, 14 Jun 2021 16:08:59 +0100 Subject: [PATCH 22/31] fix,srsue: defer enqueuing of the rrc reconf complete message to avoid that it goes in the UL grant whose PDCCH was scheduled in the TTI as the PDSCH that carried the HO command --- srsue/src/stack/rrc/rrc_procedures.cc | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/srsue/src/stack/rrc/rrc_procedures.cc b/srsue/src/stack/rrc/rrc_procedures.cc index 47f9daabb..d391c2d4f 100644 --- a/srsue/src/stack/rrc/rrc_procedures.cc +++ b/srsue/src/stack/rrc/rrc_procedures.cc @@ -1742,16 +1742,20 @@ srsran::proc_outcome_t rrc::ho_proc::init(const asn1::rrc::rrc_conn_recfg_s& rrc return proc_outcome_t::yield; // wait for t304 expiry } - // Have RRCReconfComplete message ready when Msg3 is sent - rrc_ptr->send_rrc_con_reconfig_complete(); + // Note: We delay the enqueuing of RRC Reconf Complete message to avoid that the message goes in an UL grant + // directed at the old RNTI. + rrc_ptr->task_sched.defer_callback(4, [this]() { + // Have RRCReconfComplete message ready when Msg3 is sent + rrc_ptr->send_rrc_con_reconfig_complete(); - // SCell addition/removal can take some time to compute. Enqueue in a background task and do it in the end. - rrc_ptr->apply_scell_config(&recfg_r8, false); + // SCell addition/removal can take some time to compute. Enqueue in a background task and do it in the end. + rrc_ptr->apply_scell_config(&recfg_r8, false); - // Send PDCP status report if configured - rrc_ptr->pdcp->send_status_report(); + // Send PDCP status report if configured + rrc_ptr->pdcp->send_status_report(); - Info("Finished HO configuration. Waiting PHY to synchronize with target cell"); + Info("Finished HO configuration. Waiting PHY to synchronize with target cell"); + }); return proc_outcome_t::yield; } From 2cd8ba3a1ad70b544e9eca624ee8a6fefea95955 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 14 Jun 2021 16:48:56 +0200 Subject: [PATCH 23/31] PDCCH test skips 100PRB for ARM --- lib/src/phy/phch/test/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/src/phy/phch/test/CMakeLists.txt b/lib/src/phy/phch/test/CMakeLists.txt index ad3361e6f..249e97542 100644 --- a/lib/src/phy/phch/test/CMakeLists.txt +++ b/lib/src/phy/phch/test/CMakeLists.txt @@ -199,6 +199,10 @@ add_executable(pdcch_test pdcch_test.c) target_link_libraries(pdcch_test srsran_phy) foreach (nof_prb 6 15 25 50 75 100) + # Currently, the ARM platforms srsRAN has been tested are not capable of running 100PRB. So, skip 100 PRB in ARM + if (HAVE_NEON AND (${nof_prb} EQUAL 100)) + continue() + endif () foreach (nof_ports 1 2) foreach (cfi 1 2 3) foreach (snr auto 15 300) From d7204df896b717c111000f87b74cd91250aae200 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 14 Jun 2021 12:33:57 +0200 Subject: [PATCH 24/31] rlc_am_lte: check rx window first when receiving status PDU move rx window check up so no actions are taken when receiving malformed status PDU --- lib/src/upper/rlc_am_lte.cc | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/lib/src/upper/rlc_am_lte.cc b/lib/src/upper/rlc_am_lte.cc index afa6c511d..30dc53afa 100644 --- a/lib/src/upper/rlc_am_lte.cc +++ b/lib/src/upper/rlc_am_lte.cc @@ -1170,13 +1170,24 @@ void rlc_am_lte::rlc_am_lte_tx::handle_control_pdu(uint8_t* payload, uint32_t no std::unique_lock lock(mutex); - logger.info(payload, nof_bytes, "%s Rx control PDU", RB_NAME); + logger.debug(payload, nof_bytes, "%s Rx control PDU", RB_NAME); rlc_status_pdu_t status; rlc_am_read_status_pdu(payload, nof_bytes, &status); log_rlc_am_status_pdu_to_string(logger.info, "%s Rx Status PDU: %s", &status, RB_NAME); + // make sure ACK_SN is within our Tx window + if (((MOD + status.ack_sn - vt_a) % MOD > RLC_AM_WINDOW_SIZE) || + ((MOD + vt_s - status.ack_sn) % MOD > RLC_AM_WINDOW_SIZE)) { + logger.warning("%s Received invalid status PDU (ack_sn=%d, vt_a=%d, vt_s=%d). Dropping PDU.", + RB_NAME, + status.ack_sn, + vt_a, + vt_s); + return; + } + // Sec 5.2.2.2, stop poll reTx timer if status PDU comprises a positive _or_ negative acknowledgement // for the RLC data PDU with sequence number poll_sn if (poll_retx_timer.is_valid() && (TX_MOD_BASE(poll_sn) < TX_MOD_BASE(status.ack_sn))) { @@ -1189,16 +1200,6 @@ void rlc_am_lte::rlc_am_lte_tx::handle_control_pdu(uint8_t* payload, uint32_t no retx_queue.clear(); } - // make sure ACK_SN is within our Tx window - if ((MOD + status.ack_sn - vt_a) % MOD > RLC_AM_WINDOW_SIZE) { - logger.error("%s Received invalid status PDU (ack_sn=%d < vt_a=%d). Dropping PDU.", RB_NAME, status.ack_sn, vt_a); - return; - } - if ((MOD + vt_s - status.ack_sn) % MOD > RLC_AM_WINDOW_SIZE) { - logger.error("%s Received invalid status PDU (ack_sn=%d > vt_s=%d). Dropping PDU.", RB_NAME, status.ack_sn, vt_s); - return; - } - // Handle ACKs and NACKs bool update_vt_a = true; uint32_t i = vt_a; From 475c033440f6d1e06b2a94595a2c5167ce5395ad Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 14 Jun 2021 12:38:14 +0200 Subject: [PATCH 25/31] rlc_am_test: extend status PDU test add full test with malformed status PDU --- lib/test/upper/rlc_am_test.cc | 44 ++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/lib/test/upper/rlc_am_test.cc b/lib/test/upper/rlc_am_test.cc index 85fcdfcc3..3ceff8f75 100644 --- a/lib/test/upper/rlc_am_test.cc +++ b/lib/test/upper/rlc_am_test.cc @@ -3376,8 +3376,11 @@ bool incorrect_status_pdu_test2() if (not rlc1.configure(rlc_config_t::default_rlc_am_config())) { return -1; } + if (not rlc2.configure(rlc_config_t::default_rlc_am_config())) { + return -1; + } - // Push 5 SDUs into RLC1 + // Push 10 SDUs into RLC1 const uint32_t n_sdus = 10; unique_byte_buffer_t sdu_bufs[n_sdus]; for (uint32_t i = 0; i < n_sdus; i++) { @@ -3387,12 +3390,15 @@ bool incorrect_status_pdu_test2() rlc1.write_sdu(std::move(sdu_bufs[i])); } - // Read 5 PDUs from RLC1 (1 byte each) + // Read 10 PDUs from RLC1 (1 byte each) and push half of them to RLC2 const uint32_t n_pdus = n_sdus; byte_buffer_t pdu_bufs[n_pdus]; for (uint32_t i = 0; i < n_pdus; i++) { len = rlc1.read_pdu(pdu_bufs[i].msg, 3); // 2 byte header + 1 byte payload pdu_bufs[i].N_bytes = len; + if (i < 5) { + rlc2.write_pdu(pdu_bufs[i].msg, pdu_bufs[i].N_bytes); + } } TESTASSERT(0 == rlc1.get_buffer_state()); @@ -3431,14 +3437,34 @@ bool incorrect_status_pdu_test2() rlc_am_write_status_pdu(&status_pdu, &status_buf); rlc1.write_pdu(status_buf.msg, status_buf.N_bytes); - // now ack all - status_pdu.ack_sn = n_pdus; - status_pdu.N_nack = 0; - TESTASSERT(rlc_am_is_valid_status_pdu(status_pdu)); + // Step timers until reordering timeout expires + int cnt = 5; + while (cnt--) { + timers.step_all(); + } - // pack and write to RLC again - rlc_am_write_status_pdu(&status_pdu, &status_buf); - rlc1.write_pdu(status_buf.msg, status_buf.N_bytes); + // retransmit all outstanding PDUs + for (int i = 0; i < 5; i++) { + byte_buffer_t retx; + retx.N_bytes = rlc1.read_pdu(retx.msg, 3); + rlc2.write_pdu(retx.msg, retx.N_bytes); + + // Step timers until reordering timeout expires + int cnt = 5; + while (cnt--) { + timers.step_all(); + } + + // read status + byte_buffer_t status_buf; + status_buf.N_bytes = rlc2.read_pdu(status_buf.msg, 10); + rlc1.write_pdu(status_buf.msg, status_buf.N_bytes); + } + + TESTASSERT(tester.sdus.size() == n_sdus); + for (uint32_t i = 0; i < tester.sdus.size(); i++) { + TESTASSERT(tester.sdus[i]->N_bytes == 1); + } return SRSRAN_SUCCESS; } From ef4c978d720c78134efa1d30c015bfac03c20276 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 14 Jun 2021 18:46:14 +0200 Subject: [PATCH 26/31] Optimized byte random generator --- lib/src/phy/utils/random.cpp | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/lib/src/phy/utils/random.cpp b/lib/src/phy/utils/random.cpp index b71c9a646..848a7745b 100644 --- a/lib/src/phy/utils/random.cpp +++ b/lib/src/phy/utils/random.cpp @@ -36,6 +36,23 @@ public: return dist(*mt19937); } + void byte_vector(uint8_t* buffer, uint32_t n) + { + if (buffer == NULL || n == 0) { + return; + } + + uint32_t i = 0; + uint32_t* buffer_u32 = (uint32_t*)buffer; + for (; i < n / sizeof(uint32_t); i++) { + buffer_u32[i] = (uint32_t)(*mt19937)(); + } + i *= (uint32_t)sizeof(uint32_t); + for (; i < n; i++) { + buffer[i] = (uint8_t)((*mt19937)() & 0xffUL); + } + } + float gauss_dist(float sigma) { std::normal_distribution dist(sigma); @@ -115,9 +132,11 @@ bool srsran_random_bool(srsran_random_t q, float prob_true) void srsran_random_bit_vector(srsran_random_t q, uint8_t* c, uint32_t nsamples) { - for (uint32_t i = 0; i < nsamples; i++) { - c[i] = (uint8_t)srsran_random_uniform_int_dist(q, 0, 1); + if (q == nullptr) { + return; } + auto* h = (random_wrap*)q; + h->byte_vector(c, nsamples); } void srsran_random_free(srsran_random_t q) From d2a19c3043e5f62d092d74b3e25291bd60b91193 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 14 Jun 2021 18:47:08 +0200 Subject: [PATCH 27/31] SCH minimum number of iterations to 2 to reduce systematic false alarm probability --- lib/src/phy/phch/sch.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/src/phy/phch/sch.c b/lib/src/phy/phch/sch.c index 50e41e0ec..aa2499d86 100644 --- a/lib/src/phy/phch/sch.c +++ b/lib/src/phy/phch/sch.c @@ -23,6 +23,7 @@ #include #include +#define SRSRAN_PDSCH_MIN_TDEC_ITERS 2 #define SRSRAN_PDSCH_MAX_TDEC_ITERS 10 #ifdef LV_HAVE_SSE @@ -433,8 +434,9 @@ bool decode_tb_cb(srsran_sch_t* q, crc_ptr = &q->crc_tb; } - // CRC is OK - if (!srsran_crc_checksum_byte(crc_ptr, &data[cb_idx * rlen / 8], len_crc)) { + // CRC is OK and ran the minimum number of iterations + if (!srsran_crc_checksum_byte(crc_ptr, &data[cb_idx * rlen / 8], len_crc) && + (cb_noi >= SRSRAN_PDSCH_MIN_TDEC_ITERS)) { softbuffer->cb_crc[cb_idx] = true; early_stop = true; From cf09044453f6885e06ed778d543952e73d544907 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 15 Jun 2021 11:03:05 +0200 Subject: [PATCH 28/31] Optimised random bit (unpacked) and byte (packed) generator --- lib/include/srsran/phy/utils/bit.h | 8 ++++++++ lib/include/srsran/phy/utils/random.h | 2 ++ lib/src/phy/utils/random.cpp | 26 +++++++++++++++++++++++++- lib/test/phy/phy_dl_test.c | 4 +--- 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/lib/include/srsran/phy/utils/bit.h b/lib/include/srsran/phy/utils/bit.h index c9267a441..77e55a0b7 100644 --- a/lib/include/srsran/phy/utils/bit.h +++ b/lib/include/srsran/phy/utils/bit.h @@ -26,6 +26,10 @@ #include "srsran/config.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct { uint32_t nof_bits; uint16_t* interleaver; @@ -78,4 +82,8 @@ SRSRAN_API uint32_t srsran_bit_diff(const uint8_t* x, const uint8_t* y, int nbit SRSRAN_API uint32_t srsran_bit_count(uint32_t n); +#ifdef __cplusplus +} +#endif + #endif // SRSRAN_BIT_H diff --git a/lib/include/srsran/phy/utils/random.h b/lib/include/srsran/phy/utils/random.h index 4383f2d0c..7eab3c180 100644 --- a/lib/include/srsran/phy/utils/random.h +++ b/lib/include/srsran/phy/utils/random.h @@ -39,6 +39,8 @@ SRSRAN_API float srsran_random_gauss_dist(srsran_random_t q, float std_dev); SRSRAN_API bool srsran_random_bool(srsran_random_t q, float prob_true); +SRSRAN_API void srsran_random_byte_vector(srsran_random_t q, uint8_t* c, uint32_t nsamples); + SRSRAN_API void srsran_random_bit_vector(srsran_random_t q, uint8_t* c, uint32_t nsamples); SRSRAN_API void srsran_random_free(srsran_random_t q); diff --git a/lib/src/phy/utils/random.cpp b/lib/src/phy/utils/random.cpp index 848a7745b..04a01f3be 100644 --- a/lib/src/phy/utils/random.cpp +++ b/lib/src/phy/utils/random.cpp @@ -11,6 +11,7 @@ */ #include "srsran/phy/utils/random.h" +#include "srsran/phy/utils/bit.h" #include #include @@ -53,6 +54,20 @@ public: } } + void bit_vector(uint8_t* buffer, uint32_t n) + { + if (buffer == NULL || n == 0) { + return; + } + + uint32_t i = 0; + uint8_t* ptr = buffer; + for (; i < n / 32; i++) { + srsran_bit_unpack((uint32_t)(*mt19937)(), &ptr, 32); + } + srsran_bit_unpack((uint32_t)(*mt19937)(), &ptr, n - i * 32); + } + float gauss_dist(float sigma) { std::normal_distribution dist(sigma); @@ -130,7 +145,7 @@ bool srsran_random_bool(srsran_random_t q, float prob_true) return srsran_random_uniform_real_dist(q, 0, 1) < prob_true; } -void srsran_random_bit_vector(srsran_random_t q, uint8_t* c, uint32_t nsamples) +void srsran_random_byte_vector(srsran_random_t q, uint8_t* c, uint32_t nsamples) { if (q == nullptr) { return; @@ -139,6 +154,15 @@ void srsran_random_bit_vector(srsran_random_t q, uint8_t* c, uint32_t nsamples) h->byte_vector(c, nsamples); } +void srsran_random_bit_vector(srsran_random_t q, uint8_t* c, uint32_t nsamples) +{ + if (q == nullptr) { + return; + } + auto* h = (random_wrap*)q; + h->bit_vector(c, nsamples); +} + void srsran_random_free(srsran_random_t q) { if (q) { diff --git a/lib/test/phy/phy_dl_test.c b/lib/test/phy/phy_dl_test.c index 07b95edb7..78c9ed5c5 100644 --- a/lib/test/phy/phy_dl_test.c +++ b/lib/test/phy/phy_dl_test.c @@ -524,9 +524,7 @@ int main(int argc, char** argv) for (uint32_t sf_idx = 0; sf_idx < nof_subframes; sf_idx++) { /* Generate random data */ for (int j = 0; j < SRSRAN_MAX_TB; j++) { - for (int i = 0; i < MAX_DATABUFFER_SIZE; i++) { - data_tx[j][i] = (uint8_t)srsran_random_uniform_int_dist(random, 0, 255); - } + srsran_random_byte_vector(random, data_tx[j], MAX_DATABUFFER_SIZE); } /* From d5234b5f65850025df2e9a4a9fef33e17f42d56e Mon Sep 17 00:00:00 2001 From: Francisco Date: Tue, 15 Jun 2021 15:02:38 +0100 Subject: [PATCH 29/31] sched,bugfix: avoid using UL SNR average in tpc control loop --- srsenb/hdr/stack/mac/sched_ue_ctrl/tpc.h | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/srsenb/hdr/stack/mac/sched_ue_ctrl/tpc.h b/srsenb/hdr/stack/mac/sched_ue_ctrl/tpc.h index 0c7df3634..de37dd6a6 100644 --- a/srsenb/hdr/stack/mac/sched_ue_ctrl/tpc.h +++ b/srsenb/hdr/stack/mac/sched_ue_ctrl/tpc.h @@ -112,6 +112,7 @@ public: } else { ch_snr.acc_tpc_values = 0; ch_snr.snr_avg.push(ch_snr.pending_snr, ch_snr.last_snr_sample_count); + ch_snr.last_snr_sample = ch_snr.pending_snr; ch_snr.last_snr_sample_count = 1; } ch_snr.pending_snr = null_snr; @@ -166,7 +167,7 @@ private: float target_snr_dB = cc == PUSCH_CODE ? target_pusch_snr_dB : target_pucch_snr_dB; if (target_snr_dB < 0) { - // undefined target sinr case, or no more PHR + // undefined target SINR case return encode_tpc_delta(0); } if ((tti_count - ch_snr.last_tpc_tti_count) < min_tpc_tti_interval) { @@ -176,12 +177,13 @@ private: if (cc == PUSCH_CODE and last_phr < 0 and not ch_snr.phr_flag) { // if negative PHR and PUSCH logger.info("TPC: rnti=0x%x, PUSCH command=0 due to PHR=%d<0", rnti, last_phr); - ch_snr.phr_flag = true; - return encode_tpc_delta(-1); + ch_snr.phr_flag = true; + ch_snr.pending_delta = -1; + return encode_tpc_delta(ch_snr.pending_delta); } // target SINR is finite and there is power headroom - float diff = target_snr_dB - ch_snr.snr_avg.value(); + float diff = target_snr_dB - ch_snr.last_snr_sample; diff -= ch_snr.win_tpc_values.value() + ch_snr.acc_tpc_values; if (diff >= 1) { ch_snr.pending_delta = diff > 3 ? 3 : 1; @@ -194,6 +196,15 @@ private: ch_snr.pending_delta = -1; ch_snr.last_tpc_tti_count = tti_count; } + if (ch_snr.pending_delta != 0) { + logger.debug("TPC: rnti=0x%x, %s command=%d, last SNR=%d, SNR average=%f, diff_acc=%f", + rnti, + cc == PUSCH_CODE ? "PUSCH" : "PUCCH", + encode_tpc_delta(ch_snr.pending_delta), + ch_snr.last_snr_sample, + ch_snr.snr_avg.value(), + diff); + } return encode_tpc_delta(ch_snr.pending_delta); } @@ -221,6 +232,7 @@ private: // SNR average estimation with irregular sample spacing uint32_t last_snr_sample_count = 1; // jump in spacing srsran::exp_average_irreg_sampling snr_avg; + int last_snr_sample; // Accumulation of past TPC commands srsran::sliding_sum win_tpc_values; int8_t pending_delta = 0; @@ -228,7 +240,9 @@ private: uint32_t last_tpc_tti_count = 0; explicit ul_ch_snr_estim(float exp_avg_alpha, int initial_snr) : - snr_avg(exp_avg_alpha, initial_snr), win_tpc_values(FDD_HARQ_DELAY_UL_MS + FDD_HARQ_DELAY_DL_MS) + snr_avg(exp_avg_alpha, initial_snr), + win_tpc_values(FDD_HARQ_DELAY_UL_MS + FDD_HARQ_DELAY_DL_MS), + last_snr_sample(initial_snr) {} }; std::array snr_estim_list; From 5a82a63bb558a3eee5d601a9e1bcb0fcdf4d4969 Mon Sep 17 00:00:00 2001 From: Francisco Date: Tue, 15 Jun 2021 20:25:27 +0100 Subject: [PATCH 30/31] bugfix,srsenb: fix intraenb handover softbuffer allocation during handover --- .../srsran/interfaces/enb_mac_interfaces.h | 6 +-- srsenb/hdr/stack/mac/mac.h | 4 +- srsenb/hdr/stack/mac/ue.h | 10 +++-- srsenb/src/stack/mac/mac.cc | 39 +++++++++---------- srsenb/src/stack/mac/ue.cc | 16 +++++--- srsenb/src/stack/rrc/mac_controller.cc | 6 +-- srsenb/test/common/dummy_classes.h | 4 +- srsenb/test/rrc/test_helpers.h | 6 +-- 8 files changed, 48 insertions(+), 43 deletions(-) diff --git a/lib/include/srsran/interfaces/enb_mac_interfaces.h b/lib/include/srsran/interfaces/enb_mac_interfaces.h index 4dd8fbf38..5bd493f88 100644 --- a/lib/include/srsran/interfaces/enb_mac_interfaces.h +++ b/lib/include/srsran/interfaces/enb_mac_interfaces.h @@ -212,8 +212,8 @@ public: virtual int cell_cfg(const std::vector& cell_cfg) = 0; /* Manages UE configuration context */ - virtual int ue_cfg(uint16_t rnti, sched_interface::ue_cfg_t* cfg) = 0; - virtual int ue_rem(uint16_t rnti) = 0; + virtual int ue_cfg(uint16_t rnti, const sched_interface::ue_cfg_t* cfg) = 0; + virtual int ue_rem(uint16_t rnti) = 0; /** * Called after Msg3 reception to set the UE C-RNTI, resolve contention, and alter the UE's configuration in the @@ -223,7 +223,7 @@ public: * @param crnti chosen C-RNTI for the UE * @param cfg new UE scheduler configuration */ - virtual int ue_set_crnti(uint16_t temp_crnti, uint16_t crnti, sched_interface::ue_cfg_t* cfg) = 0; + virtual int ue_set_crnti(uint16_t temp_crnti, uint16_t crnti, const sched_interface::ue_cfg_t& cfg) = 0; /* Manages UE bearers and associated configuration */ virtual int bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, sched_interface::ue_bearer_cfg_t* cfg) = 0; diff --git a/srsenb/hdr/stack/mac/mac.h b/srsenb/hdr/stack/mac/mac.h index f7a8e50e7..23b40a658 100644 --- a/srsenb/hdr/stack/mac/mac.h +++ b/srsenb/hdr/stack/mac/mac.h @@ -77,9 +77,9 @@ public: int cell_cfg(const std::vector& cell_cfg) override; /* Manages UE scheduling context */ - int ue_cfg(uint16_t rnti, sched_interface::ue_cfg_t* cfg) override; + int ue_cfg(uint16_t rnti, const sched_interface::ue_cfg_t* cfg) override; int ue_rem(uint16_t rnti) override; - int ue_set_crnti(uint16_t temp_crnti, uint16_t crnti, sched_interface::ue_cfg_t* cfg) override; + int ue_set_crnti(uint16_t temp_crnti, uint16_t crnti, const sched_interface::ue_cfg_t& cfg) override; // Indicates that the PHY config dedicated has been enabled or not void phy_config_enabled(uint16_t rnti, bool enabled) override; diff --git a/srsenb/hdr/stack/mac/ue.h b/srsenb/hdr/stack/mac/ue.h index 3e247b97d..77d7354a5 100644 --- a/srsenb/hdr/stack/mac/ue.h +++ b/srsenb/hdr/stack/mac/ue.h @@ -132,9 +132,11 @@ public: srsran::obj_pool_itf* softbuffer_pool); virtual ~ue(); - void reset(); - void start_pcap(srsran::mac_pcap* pcap_); - void start_pcap_net(srsran::mac_pcap_net* pcap_net_); + void reset(); + void start_pcap(srsran::mac_pcap* pcap_); + void start_pcap_net(srsran::mac_pcap_net* pcap_net_); + void ue_cfg(const sched_interface::ue_cfg_t& ue_cfg); + void set_tti(uint32_t tti); uint16_t get_rnti() const { return rnti; } uint32_t set_ta(int ta) override; @@ -214,7 +216,7 @@ private: std::mutex mutex; std::mutex rx_buffers_mutex; - const uint8_t UL_CC_IDX = 0; ///< Passed to write CC index in PCAP (TODO: use actual CC idx) + static const uint8_t UL_CC_IDX = 0; ///< Passed to write CC index in PCAP }; } // namespace srsenb diff --git a/srsenb/src/stack/mac/mac.cc b/srsenb/src/stack/mac/mac.cc index 2a2c246a2..144e2dd5b 100644 --- a/srsenb/src/stack/mac/mac.cc +++ b/srsenb/src/stack/mac/mac.cc @@ -165,7 +165,7 @@ void mac::phy_config_enabled(uint16_t rnti, bool enabled) } // Update UE configuration -int mac::ue_cfg(uint16_t rnti, sched_interface::ue_cfg_t* cfg) +int mac::ue_cfg(uint16_t rnti, const sched_interface::ue_cfg_t* cfg) { srsran::rwlock_read_guard lock(rwlock); if (not check_ue_active(rnti)) { @@ -177,10 +177,12 @@ int mac::ue_cfg(uint16_t rnti, sched_interface::ue_cfg_t* cfg) ue_ptr->start_ta(); // Update Scheduler configuration - if (cfg != nullptr and scheduler.ue_cfg(rnti, *cfg) == SRSRAN_ERROR) { - logger.error("Registering new UE rnti=0x%x to SCHED", rnti); + if (scheduler.ue_cfg(rnti, *cfg) == SRSRAN_ERROR) { + logger.error("Registering UE rnti=0x%x to SCHED", rnti); return SRSRAN_ERROR; } + ue_ptr->ue_cfg(*cfg); + return SRSRAN_SUCCESS; } @@ -211,7 +213,7 @@ int mac::ue_rem(uint16_t rnti) } // Called after Msg3 -int mac::ue_set_crnti(uint16_t temp_crnti, uint16_t crnti, sched_interface::ue_cfg_t* cfg) +int mac::ue_set_crnti(uint16_t temp_crnti, uint16_t crnti, const sched_interface::ue_cfg_t& cfg) { srsran::rwlock_read_guard lock(rwlock); if (temp_crnti != crnti) { @@ -221,7 +223,7 @@ int mac::ue_set_crnti(uint16_t temp_crnti, uint16_t crnti, sched_interface::ue_c // Schedule ConRes Msg4 scheduler.dl_mac_buffer_state(crnti, (uint32_t)srsran::dl_sch_lcid::CON_RES_ID); } - return ue_cfg(crnti, cfg); + return ue_cfg(crnti, &cfg); } int mac::cell_cfg(const std::vector& cell_cfg_) @@ -493,19 +495,17 @@ uint16_t mac::allocate_ue(uint32_t enb_cc_idx) return rnti; } -uint16_t mac::reserve_new_crnti(const sched_interface::ue_cfg_t& ue_cfg) +uint16_t mac::reserve_new_crnti(const sched_interface::ue_cfg_t& uecfg) { - uint16_t rnti = allocate_ue(ue_cfg.supported_cc_list[0].enb_cc_idx); + uint16_t rnti = allocate_ue(uecfg.supported_cc_list[0].enb_cc_idx); if (rnti == SRSRAN_INVALID_RNTI) { return rnti; } // Add new user to the scheduler so that it can RX/TX SRB0 - if (scheduler.ue_cfg(rnti, ue_cfg) != SRSRAN_SUCCESS) { - logger.error("Registering new user rnti=0x%x to SCHED", rnti); + if (ue_cfg(rnti, &uecfg) != SRSRAN_SUCCESS) { return SRSRAN_INVALID_RNTI; } - return rnti; } @@ -534,20 +534,18 @@ void mac::rach_detected(uint32_t tti, uint32_t enb_cc_idx, uint32_t preamble_idx ++detected_rachs[enb_cc_idx]; // Add new user to the scheduler so that it can RX/TX SRB0 - sched_interface::ue_cfg_t ue_cfg = {}; - ue_cfg.supported_cc_list.emplace_back(); - ue_cfg.supported_cc_list.back().active = true; - ue_cfg.supported_cc_list.back().enb_cc_idx = enb_cc_idx; - ue_cfg.ue_bearers[0].direction = srsenb::sched_interface::ue_bearer_cfg_t::BOTH; - ue_cfg.supported_cc_list[0].dl_cfg.tm = SRSRAN_TM1; - if (scheduler.ue_cfg(rnti, ue_cfg) != SRSRAN_SUCCESS) { - logger.error("Registering new user rnti=0x%x to SCHED", rnti); - ue_rem(rnti); + sched_interface::ue_cfg_t uecfg = {}; + uecfg.supported_cc_list.emplace_back(); + uecfg.supported_cc_list.back().active = true; + uecfg.supported_cc_list.back().enb_cc_idx = enb_cc_idx; + uecfg.ue_bearers[0].direction = srsenb::sched_interface::ue_bearer_cfg_t::BOTH; + uecfg.supported_cc_list[0].dl_cfg.tm = SRSRAN_TM1; + if (ue_cfg(rnti, &uecfg) != SRSRAN_SUCCESS) { return; } // Register new user in RRC - if (rrc_h->add_user(rnti, ue_cfg) == SRSRAN_ERROR) { + if (rrc_h->add_user(rnti, uecfg) == SRSRAN_ERROR) { ue_rem(rnti); return; } @@ -924,6 +922,7 @@ int mac::get_ul_sched(uint32_t tti_tx_ul, ul_sched_list_t& ul_sched_res_list) // If the Rx soft-buffer is not given, abort reception if (phy_ul_sched_res->pusch[n].softbuffer_rx == nullptr) { + logger.warning("Failed to retrieve UL softbuffer for tti=%d, cc=%d", tti_tx_ul, enb_cc_idx); continue; } diff --git a/srsenb/src/stack/mac/ue.cc b/srsenb/src/stack/mac/ue.cc index 00e8c9287..0772a1491 100644 --- a/srsenb/src/stack/mac/ue.cc +++ b/srsenb/src/stack/mac/ue.cc @@ -220,6 +220,16 @@ void ue::start_pcap(srsran::mac_pcap* pcap_) pcap = pcap_; } +void ue::ue_cfg(const sched_interface::ue_cfg_t& ue_cfg) +{ + for (const auto& ue_cc : ue_cfg.supported_cc_list) { + // Allocate and initialize Rx/Tx softbuffers for new carriers (exclude PCell) + if (ue_cc.active and cc_buffers[ue_cc.enb_cc_idx].empty()) { + cc_buffers[ue_cc.enb_cc_idx].allocate_cc(softbuffer_pool->make()); + } + } +} + srsran_softbuffer_rx_t* ue::get_rx_softbuffer(uint32_t enb_cc_idx, uint32_t tti) { if ((size_t)enb_cc_idx >= cc_buffers.size() or cc_buffers[enb_cc_idx].empty()) { @@ -509,12 +519,6 @@ void ue::allocate_ce(srsran::sch_pdu* pdu, uint32_t lcid) } if (pdu->get()->set_scell_activation_cmd(active_scell_list)) { phy->set_activation_deactivation_scell(rnti, active_scell_list); - // Allocate and initialize Rx/Tx softbuffers for new carriers (exclude PCell) - for (size_t cc = 0; cc < cc_buffers.size(); ++cc) { - if (active_ccs[cc] >= 0 and cc_buffers[cc].empty()) { - cc_buffers[cc].allocate_cc(softbuffer_pool->make()); - } - } } else { logger.error("CE: Setting SCell Activation CE"); } diff --git a/srsenb/src/stack/rrc/mac_controller.cc b/srsenb/src/stack/rrc/mac_controller.cc index e42414597..1f36d2ef8 100644 --- a/srsenb/src/stack/rrc/mac_controller.cc +++ b/srsenb/src/stack/rrc/mac_controller.cc @@ -116,7 +116,7 @@ void mac_controller::handle_con_reject() if (not crnti_set) { crnti_set = true; // Need to schedule ConRes CE for UE to see the Reject message - mac->ue_set_crnti(rnti, rnti, ¤t_sched_ue_cfg); + mac->ue_set_crnti(rnti, rnti, current_sched_ue_cfg); } } @@ -137,7 +137,7 @@ int mac_controller::handle_crnti_ce(uint32_t temp_crnti) current_sched_ue_cfg.ue_bearers[i] = next_sched_ue_cfg.ue_bearers[i]; } - return mac->ue_set_crnti(temp_crnti, rnti, ¤t_sched_ue_cfg); + return mac->ue_set_crnti(temp_crnti, rnti, current_sched_ue_cfg); } int mac_controller::apply_basic_conn_cfg(const asn1::rrc::rr_cfg_ded_s& rr_cfg) @@ -183,7 +183,7 @@ int mac_controller::apply_basic_conn_cfg(const asn1::rrc::rr_cfg_ded_s& rr_cfg) // In case of RRC Connection Setup/Reest message (Msg4), we need to resolve the contention by sending a ConRes CE mac->phy_config_enabled(rnti, false); crnti_set = true; - return mac->ue_set_crnti(rnti, rnti, ¤t_sched_ue_cfg); + return mac->ue_set_crnti(rnti, rnti, current_sched_ue_cfg); } void mac_controller::handle_con_setup_complete() diff --git a/srsenb/test/common/dummy_classes.h b/srsenb/test/common/dummy_classes.h index 68c50baa8..9338f1484 100644 --- a/srsenb/test/common/dummy_classes.h +++ b/srsenb/test/common/dummy_classes.h @@ -28,9 +28,9 @@ class mac_dummy : public mac_interface_rrc { public: int cell_cfg(const std::vector& cell_cfg) override { return 0; } - int ue_cfg(uint16_t rnti, sched_interface::ue_cfg_t* cfg) override { return 0; } + int ue_cfg(uint16_t rnti, const sched_interface::ue_cfg_t* cfg) override { return 0; } int ue_rem(uint16_t rnti) override { return 0; } - int ue_set_crnti(uint16_t temp_crnti, uint16_t crnti, sched_interface::ue_cfg_t* cfg) override { return 0; } + int ue_set_crnti(uint16_t temp_crnti, uint16_t crnti, const sched_interface::ue_cfg_t& cfg) override { return 0; } int bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, sched_interface::ue_bearer_cfg_t* cfg) override { return 0; } int bearer_ue_rem(uint16_t rnti, uint32_t lc_id) override { return 0; } void phy_config_enabled(uint16_t rnti, bool enabled) override {} diff --git a/srsenb/test/rrc/test_helpers.h b/srsenb/test/rrc/test_helpers.h index cadd06e94..ecd0823e6 100644 --- a/srsenb/test/rrc/test_helpers.h +++ b/srsenb/test/rrc/test_helpers.h @@ -175,14 +175,14 @@ public: class mac_mobility_dummy : public mac_dummy { public: - int ue_cfg(uint16_t rnti, sched_interface::ue_cfg_t* cfg) override + int ue_cfg(uint16_t rnti, const sched_interface::ue_cfg_t* cfg) override { ue_db[rnti] = *cfg; return 0; } - int ue_set_crnti(uint16_t temp_crnti, uint16_t crnti, sched_interface::ue_cfg_t* cfg) override + int ue_set_crnti(uint16_t temp_crnti, uint16_t crnti, const sched_interface::ue_cfg_t& cfg) override { - ue_db[crnti] = *cfg; + ue_db[crnti] = cfg; return 0; } std::map ue_db; From c280ac5ad663855af0be90e55b42ba70ac1be589 Mon Sep 17 00:00:00 2001 From: Bedran Karakoc Date: Tue, 15 Jun 2021 15:09:34 +0200 Subject: [PATCH 31/31] Introducing extended NGAP functionality Remove unused logger for now in ngap::ue to pass tests --- .../srsran/interfaces/gnb_ngap_interfaces.h | 7 +- srsenb/hdr/stack/ngap/ngap.h | 103 +++- srsenb/src/stack/ngap/ngap.cc | 476 +++++++++++++++++- srsenb/test/CMakeLists.txt | 1 + srsenb/test/ngap/CMakeLists.txt | 13 + srsenb/test/ngap/ngap_test.cc | 152 ++++++ 6 files changed, 711 insertions(+), 41 deletions(-) create mode 100644 srsenb/test/ngap/CMakeLists.txt create mode 100644 srsenb/test/ngap/ngap_test.cc diff --git a/lib/include/srsran/interfaces/gnb_ngap_interfaces.h b/lib/include/srsran/interfaces/gnb_ngap_interfaces.h index ff39c7ffe..eed86ca4d 100644 --- a/lib/include/srsran/interfaces/gnb_ngap_interfaces.h +++ b/lib/include/srsran/interfaces/gnb_ngap_interfaces.h @@ -42,17 +42,14 @@ public: uint32_t gnb_cc_idx, asn1::ngap_nr::rrcestablishment_cause_e cause, srsran::unique_byte_buffer_t pdu, - uint32_t m_tmsi, - uint8_t mmec) = 0; + uint32_t m_tmsi) = 0; virtual void write_pdu(uint16_t rnti, srsran::unique_byte_buffer_t pdu) = 0; virtual bool user_exists(uint16_t rnti) = 0; virtual void user_mod(uint16_t old_rnti, uint16_t new_rnti) = 0; virtual bool user_release(uint16_t rnti, asn1::ngap_nr::cause_radio_network_e cause_radio) = 0; virtual bool is_amf_connected() = 0; - - /// TS 36.413, 8.3.1 - Initial Context Setup - virtual void ue_ctxt_setup_complete(uint16_t rnti) = 0; + virtual void ue_ctxt_setup_complete(uint16_t rnti) = 0; }; } // namespace srsenb diff --git a/srsenb/hdr/stack/ngap/ngap.h b/srsenb/hdr/stack/ngap/ngap.h index 99b7af3b8..737d6022d 100644 --- a/srsenb/hdr/stack/ngap/ngap.h +++ b/srsenb/hdr/stack/ngap/ngap.h @@ -14,6 +14,7 @@ #include "srsenb/hdr/common/common_enb.h" #include "srsran/adt/circular_map.h" +#include "srsran/adt/optional.h" #include "srsran/asn1/asn1_utils.h" #include "srsran/asn1/ngap.h" #include "srsran/common/bcd_helpers.h" @@ -27,8 +28,11 @@ #include "srsran/interfaces/gnb_ngap_interfaces.h" #include "srsran/interfaces/gnb_rrc_nr_interfaces.h" #include "srsran/srslog/srslog.h" +#include +#include namespace srsenb { + class ngap : public ngap_interface_rrc_nr { public: @@ -42,21 +46,22 @@ public: void initial_ue(uint16_t rnti, uint32_t gnb_cc_idx, asn1::ngap_nr::rrcestablishment_cause_e cause, - srsran::unique_byte_buffer_t pdu){}; + srsran::unique_byte_buffer_t pdu); void initial_ue(uint16_t rnti, uint32_t gnb_cc_idx, asn1::ngap_nr::rrcestablishment_cause_e cause, srsran::unique_byte_buffer_t pdu, - uint32_t m_tmsi, - uint8_t mmec){}; + uint32_t s_tmsi); + void write_pdu(uint16_t rnti, srsran::unique_byte_buffer_t pdu){}; bool user_exists(uint16_t rnti) { return true; }; void user_mod(uint16_t old_rnti, uint16_t new_rnti){}; bool user_release(uint16_t rnti, asn1::ngap_nr::cause_radio_network_e cause_radio) { return true; }; bool is_amf_connected(); - - /// TS 36.413, 8.3.1 - Initial Context Setup - void ue_ctxt_setup_complete(uint16_t rnti){}; + bool send_error_indication(const asn1::ngap_nr::cause_c& cause, + srsran::optional ran_ue_ngap_id = {}, + srsran::optional amf_ue_ngap_id = {}); + void ue_ctxt_setup_complete(uint16_t rnti); // Stack interface bool @@ -82,7 +87,7 @@ private: struct sockaddr_in amf_addr = {}; // AMF address bool amf_connected = false; bool running = false; - uint32_t next_enb_ue_ngap_id = 1; // Next ENB-side UE identifier + uint32_t next_gnb_ue_ngap_id = 1; // Next GNB-side UE identifier uint16_t next_ue_stream_id = 1; // Next UE SCTP stream identifier srsran::unique_timer amf_connect_timer, ngsetup_timeout; @@ -90,8 +95,82 @@ private: asn1::ngap_nr::tai_s tai; asn1::ngap_nr::nr_cgi_s nr_cgi; + // Moved into NGAP class to avoid redifinition (Introduce new namespace?) + struct ue_ctxt_t { + static const uint32_t invalid_gnb_id = std::numeric_limits::max(); + + uint16_t rnti = SRSRAN_INVALID_RNTI; + uint32_t ran_ue_ngap_id = invalid_gnb_id; + srsran::optional amf_ue_ngap_id; + uint32_t gnb_cc_idx = 0; + struct timeval init_timestamp = {}; + + // AMF identifier + uint16_t amf_set_id; + uint8_t amf_pointer; + uint8_t amf_region_id; + }; + asn1::ngap_nr::ng_setup_resp_s ngsetupresponse; + int build_tai_cgi(); + bool connect_amf(); + bool setup_ng(); + bool sctp_send_ngap_pdu(const asn1::ngap_nr::ngap_pdu_c& tx_pdu, uint32_t rnti, const char* procedure_name); + + bool handle_ngap_rx_pdu(srsran::byte_buffer_t* pdu); + bool handle_successfuloutcome(const asn1::ngap_nr::successful_outcome_s& msg); + bool handle_unsuccessfuloutcome(const asn1::ngap_nr::unsuccessful_outcome_s& msg); + bool handle_initiatingmessage(const asn1::ngap_nr::init_msg_s& msg); + + bool handle_dlnastransport(const asn1::ngap_nr::dl_nas_transport_s& msg); + bool handle_ngsetupresponse(const asn1::ngap_nr::ng_setup_resp_s& msg); + bool handle_ngsetupfailure(const asn1::ngap_nr::ng_setup_fail_s& msg); + bool handle_initialctxtsetuprequest(const asn1::ngap_nr::init_context_setup_request_s& msg); + struct ue { + explicit ue(ngap* ngap_ptr_); + bool send_initialuemessage(asn1::ngap_nr::rrcestablishment_cause_e cause, + srsran::unique_byte_buffer_t pdu, + bool has_tmsi, + uint32_t s_tmsi = 0); + bool send_ulnastransport(srsran::unique_byte_buffer_t pdu); + bool was_uectxtrelease_requested() const { return release_requested; } + void ue_ctxt_setup_complete(); + + ue_ctxt_t ctxt = {}; + uint16_t stream_id = 1; + + private: + // args + ngap* ngap_ptr; + + // state + bool release_requested = false; + }; + class user_list + { + public: + using value_type = std::unique_ptr; + using iterator = std::unordered_map::iterator; + using const_iterator = std::unordered_map::const_iterator; + using pair_type = std::unordered_map::value_type; + + ue* find_ue_rnti(uint16_t rnti); + ue* find_ue_gnbid(uint32_t gnbid); + ue* find_ue_amfid(uint32_t amfid); + ue* add_user(value_type user); + void erase(ue* ue_ptr); + iterator begin() { return users.begin(); } + iterator end() { return users.end(); } + const_iterator cbegin() const { return users.begin(); } + const_iterator cend() const { return users.end(); } + size_t size() const { return users.size(); } + + private: + std::unordered_map > users; // maps ran_ue_ngap_id to user + }; + user_list users; + // procedures class ng_setup_proc_t { @@ -114,15 +193,7 @@ private: ngap* ngap_ptr = nullptr; }; - void build_tai_cgi(); - bool connect_amf(); - bool setup_ng(); - bool sctp_send_ngap_pdu(const asn1::ngap_nr::ngap_pdu_c& tx_pdu, uint32_t rnti, const char* procedure_name); - - bool handle_ngap_rx_pdu(srsran::byte_buffer_t* pdu); - bool handle_successfuloutcome(const asn1::ngap_nr::successful_outcome_s& msg); - - bool handle_ngsetupresponse(const asn1::ngap_nr::ng_setup_resp_s& msg); + ue* handle_ngapmsg_ue_id(uint32_t gnb_id, uint32_t amf_id); srsran::proc_t ngsetup_proc; diff --git a/srsenb/src/stack/ngap/ngap.cc b/srsenb/src/stack/ngap/ngap.cc index 7f901d8e1..75fec27c6 100644 --- a/srsenb/src/stack/ngap/ngap.cc +++ b/srsenb/src/stack/ngap/ngap.cc @@ -11,6 +11,10 @@ */ #include "srsenb/hdr/stack/ngap/ngap.h" +#include "srsran/common/int_helpers.h" + +using srsran::s1ap_mccmnc_to_plmn; +using srsran::uint32_to_uint8; #define procError(fmt, ...) ngap_ptr->logger.error("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__) #define procWarning(fmt, ...) ngap_ptr->logger.warning("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__) @@ -145,20 +149,137 @@ bool ngap::is_amf_connected() } // Generate common NGAP protocol IEs from config args -void ngap::build_tai_cgi() +int ngap::build_tai_cgi() { uint32_t plmn; + uint8_t shift; // TAI srsran::s1ap_mccmnc_to_plmn(args.mcc, args.mnc, &plmn); tai.plmn_id.from_number(plmn); - tai.tac.from_number(args.tac); - // nr_cgi + // NR CGI nr_cgi.plmn_id.from_number(plmn); - // TODO Check how to build nr cell id - nr_cgi.nrcell_id.from_number((uint32_t)(args.gnb_id << 8) | args.cell_id); + + // NR CELL ID (36 bits) = gnb_id (22...32 bits) + cell_id (4...14 bits) + if (((uint8_t)log2(args.gnb_id) + (uint8_t)log2(args.cell_id) + 2) > 36) { + logger.error("gNB ID and Cell ID combination greater than 36 bits"); + return SRSRAN_ERROR; + } + // Consider moving sanity checks into the parsing function of the configs. + if (((uint8_t)log2(args.gnb_id) + 1) < 22) { + shift = 14; + } else { + shift = 36 - ((uint8_t)log2(args.gnb_id) + 1); + } + + nr_cgi.nrcell_id.from_number((uint64_t)args.gnb_id << shift | args.cell_id); + return SRSRAN_SUCCESS; +} + +/******************************************************************************* +/* RRC interface +********************************************************************************/ +void ngap::initial_ue(uint16_t rnti, + uint32_t gnb_cc_idx, + asn1::ngap_nr::rrcestablishment_cause_e cause, + srsran::unique_byte_buffer_t pdu) +{ + std::unique_ptr ue_ptr{new ue{this}}; + ue_ptr->ctxt.rnti = rnti; + ue_ptr->ctxt.gnb_cc_idx = gnb_cc_idx; + ue* u = users.add_user(std::move(ue_ptr)); + if (u == nullptr) { + logger.error("Failed to add rnti=0x%x", rnti); + return; + } + u->send_initialuemessage(cause, std::move(pdu), false); +} + +void ngap::initial_ue(uint16_t rnti, + uint32_t gnb_cc_idx, + asn1::ngap_nr::rrcestablishment_cause_e cause, + srsran::unique_byte_buffer_t pdu, + uint32_t s_tmsi) +{ + std::unique_ptr ue_ptr{new ue{this}}; + ue_ptr->ctxt.rnti = rnti; + ue_ptr->ctxt.gnb_cc_idx = gnb_cc_idx; + ue* u = users.add_user(std::move(ue_ptr)); + if (u == nullptr) { + logger.error("Failed to add rnti=0x%x", rnti); + return; + } + u->send_initialuemessage(cause, std::move(pdu), true, s_tmsi); +} + +void ngap::ue_ctxt_setup_complete(uint16_t rnti) +{ + ue* u = users.find_ue_rnti(rnti); + if (u == nullptr) { + return; + } + u->ue_ctxt_setup_complete(); +} + +/********************************************************* + * ngap::user_list class + *********************************************************/ + +ngap::ue* ngap::user_list::find_ue_rnti(uint16_t rnti) +{ + if (rnti == SRSRAN_INVALID_RNTI) { + return nullptr; + } + auto it = std::find_if( + users.begin(), users.end(), [rnti](const user_list::pair_type& v) { return v.second->ctxt.rnti == rnti; }); + return it != users.end() ? it->second.get() : nullptr; +} + +ngap::ue* ngap::user_list::find_ue_gnbid(uint32_t gnbid) +{ + auto it = users.find(gnbid); + return (it != users.end()) ? it->second.get() : nullptr; +} + +ngap::ue* ngap::user_list::find_ue_amfid(uint32_t amfid) +{ + auto it = std::find_if(users.begin(), users.end(), [amfid](const user_list::pair_type& v) { + return v.second->ctxt.amf_ue_ngap_id == amfid; + }); + return it != users.end() ? it->second.get() : nullptr; +} + +ngap::ue* ngap::user_list::add_user(std::unique_ptr user) +{ + static srslog::basic_logger& logger = srslog::fetch_basic_logger("NGAP"); + // Check for ID repetitions + if (find_ue_rnti(user->ctxt.rnti) != nullptr) { + logger.error("The user to be added with rnti=0x%x already exists", user->ctxt.rnti); + return nullptr; + } + if (find_ue_gnbid(user->ctxt.ran_ue_ngap_id) != nullptr) { + logger.error("The user to be added with ran ue ngap id=%d already exists", user->ctxt.ran_ue_ngap_id); + return nullptr; + } + if (user->ctxt.amf_ue_ngap_id.has_value() and find_ue_amfid(user->ctxt.amf_ue_ngap_id.value()) != nullptr) { + logger.error("The user to be added with amf id=%d already exists", user->ctxt.amf_ue_ngap_id.value()); + return nullptr; + } + auto p = users.insert(std::make_pair(user->ctxt.ran_ue_ngap_id, std::move(user))); + return p.second ? p.first->second.get() : nullptr; +} + +void ngap::user_list::erase(ue* ue_ptr) +{ + static srslog::basic_logger& logger = srslog::fetch_basic_logger("NGAP"); + auto it = users.find(ue_ptr->ctxt.ran_ue_ngap_id); + if (it == users.end()) { + logger.error("User to be erased does not exist"); + return; + } + users.erase(it); } /******************************************************************************* @@ -191,11 +312,11 @@ bool ngap::handle_amf_rx_msg(srsran::unique_byte_buffer_t pdu, amf_socket.close(); } - // Restart MME connection procedure if we lost connection + // Restart AMF connection procedure if we lost connection if (not amf_socket.is_open()) { amf_connected = false; if (ngsetup_proc.is_busy()) { - logger.error("Failed to initiate MME connection procedure, as it is already running."); + logger.error("Failed to initiate AMF connection procedure, as it is already running."); return false; } ngsetup_proc.launch(); @@ -208,6 +329,7 @@ bool ngap::handle_amf_rx_msg(srsran::unique_byte_buffer_t pdu, bool ngap::handle_ngap_rx_pdu(srsran::byte_buffer_t* pdu) { + // TODO: // Save message to PCAP // if (pcap != nullptr) { // pcap->write_ngap(pdu->msg, pdu->N_bytes); @@ -220,18 +342,19 @@ bool ngap::handle_ngap_rx_pdu(srsran::byte_buffer_t* pdu) logger.error(pdu->msg, pdu->N_bytes, "Failed to unpack received PDU"); cause_c cause; cause.set_protocol().value = cause_protocol_opts::transfer_syntax_error; - // send_error_indication(cause); + send_error_indication(cause); return false; } + // TODO: // log_ngap_msg(rx_pdu, srsran::make_span(*pdu), true); switch (rx_pdu.type().value) { - // case ngap_pdu_c::types_opts::init_msg: - // return handle_initiatingmessage(rx_pdu.init_msg()); + case ngap_pdu_c::types_opts::init_msg: + return handle_initiatingmessage(rx_pdu.init_msg()); case ngap_pdu_c::types_opts::successful_outcome: return handle_successfuloutcome(rx_pdu.successful_outcome()); - // case ngap_pdu_c::types_opts::unsuccessful_outcome: - // return handle_unsuccessfuloutcome(rx_pdu.unsuccessful_outcome()); + case ngap_pdu_c::types_opts::unsuccessful_outcome: + return handle_unsuccessfuloutcome(rx_pdu.unsuccessful_outcome()); default: logger.error("Unhandled PDU type %d", rx_pdu.type().value); return false; @@ -240,6 +363,19 @@ bool ngap::handle_ngap_rx_pdu(srsran::byte_buffer_t* pdu) return true; } +bool ngap::handle_initiatingmessage(const asn1::ngap_nr::init_msg_s& msg) +{ + switch (msg.value.type().value) { + case ngap_elem_procs_o::init_msg_c::types_opts::dl_nas_transport: + return handle_dlnastransport(msg.value.dl_nas_transport()); + case ngap_elem_procs_o::init_msg_c::types_opts::init_context_setup_request: + return handle_initialctxtsetuprequest(msg.value.init_context_setup_request()); + default: + logger.error("Unhandled initiating message: %s", msg.value.type().to_string()); + } + return true; +} + bool ngap::handle_successfuloutcome(const successful_outcome_s& msg) { switch (msg.value.type().value) { @@ -251,6 +387,17 @@ bool ngap::handle_successfuloutcome(const successful_outcome_s& msg) return true; } +bool ngap::handle_unsuccessfuloutcome(const asn1::ngap_nr::unsuccessful_outcome_s& msg) +{ + switch (msg.value.type().value) { + case ngap_elem_procs_o::unsuccessful_outcome_c::types_opts::ng_setup_fail: + return handle_ngsetupfailure(msg.value.ng_setup_fail()); + default: + logger.error("Unhandled unsuccessful outcome message: %s", msg.value.type().to_string()); + } + return true; +} + bool ngap::handle_ngsetupresponse(const asn1::ngap_nr::ng_setup_resp_s& msg) { ngsetupresponse = msg; @@ -258,6 +405,93 @@ bool ngap::handle_ngsetupresponse(const asn1::ngap_nr::ng_setup_resp_s& msg) ng_setup_proc_t::ngsetupresult res; res.success = true; ngsetup_proc.trigger(res); + + return true; +} + +bool ngap::handle_ngsetupfailure(const asn1::ngap_nr::ng_setup_fail_s& msg) +{ + std::string cause = get_cause(msg.protocol_ies.cause.value); + logger.error("NG Setup Failure. Cause: %s", cause.c_str()); + srsran::console("NG Setup Failure. Cause: %s\n", cause.c_str()); + return true; +} + +bool ngap::handle_dlnastransport(const asn1::ngap_nr::dl_nas_transport_s& msg) +{ + if (msg.ext) { + logger.warning("Not handling NGAP message extension"); + } + ue* u = + handle_ngapmsg_ue_id(msg.protocol_ies.ran_ue_ngap_id.value.value, msg.protocol_ies.amf_ue_ngap_id.value.value); + if (u == nullptr) { + return false; + } + + if (msg.protocol_ies.old_amf_present) { + logger.warning("Not handling OldAMF"); + } + + if (msg.protocol_ies.ran_paging_prio_present) { + logger.warning("Not handling RANPagingPriority"); + } + + if (msg.protocol_ies.mob_restrict_list_present) { + logger.warning("Not handling MobilityRestrictionList"); + } + + if (msg.protocol_ies.idx_to_rfsp_present) { + logger.warning("Not handling IndexToRFSP"); + } + + if (msg.protocol_ies.ue_aggregate_maximum_bit_rate_present) { + logger.warning("Not handling UEAggregateMaximumBitRate"); + } + + if (msg.protocol_ies.allowed_nssai_present) { + logger.warning("Not handling AllowedNSSAI"); + } + + // TODO: Pass NAS PDU once RRC interface is ready + /* srsran::unique_byte_buffer_t pdu = srsran::make_byte_buffer(); + if (pdu == nullptr) { + logger.error("Fatal Error: Couldn't allocate buffer in ngap::run_thread()."); + return false; + } + memcpy(pdu->msg, msg.protocol_ies.nas_pdu.value.data(), msg.protocol_ies.nas_pdu.value.size()); + pdu->N_bytes = msg.protocol_ies.nas_pdu.value.size(); + rrc->write_dl_info(u->ctxt.rnti, std::move(pdu)); */ + return true; +} + +bool ngap::handle_initialctxtsetuprequest(const asn1::ngap_nr::init_context_setup_request_s& msg) +{ + ue* u = + handle_ngapmsg_ue_id(msg.protocol_ies.ran_ue_ngap_id.value.value, msg.protocol_ies.amf_ue_ngap_id.value.value); + if (u == nullptr) { + return false; + } + + u->ctxt.amf_pointer = msg.protocol_ies.guami.value.amf_pointer.to_number(); + u->ctxt.amf_set_id = msg.protocol_ies.guami.value.amf_set_id.to_number(); + u->ctxt.amf_region_id = msg.protocol_ies.guami.value.amf_region_id.to_number(); + + // Setup UE ctxt in RRC once interface is ready + /* if (not rrc->setup_ue_ctxt(u->ctxt.rnti, msg)) { + return false; + } */ + + /* if (msg.protocol_ies.nas_pdu_present) { + srsran::unique_byte_buffer_t pdu = srsran::make_byte_buffer(); + if (pdu == nullptr) { + logger.error("Fatal Error: Couldn't allocate buffer in ngap::run_thread()."); + return false; + } + memcpy(pdu->msg, msg.protocol_ies.nas_pdu.value.data(), msg.protocol_ies.nas_pdu.value.size()); + pdu->N_bytes = msg.protocol_ies.nas_pdu.value.size(); + rrc->write_dl_info(u->ctxt.rnti, std::move(pdu)); + } */ + return true; } @@ -344,6 +578,134 @@ bool ngap::setup_ng() return sctp_send_ngap_pdu(pdu, 0, "ngSetupRequest"); } +/******************************************************************************* +/* NGAP message senders +********************************************************************************/ + +bool ngap::ue::send_initialuemessage(asn1::ngap_nr::rrcestablishment_cause_e cause, + srsran::unique_byte_buffer_t pdu, + bool has_tmsi, + uint32_t s_tmsi) +{ + if (not ngap_ptr->amf_connected) { + return false; + } + + ngap_pdu_c tx_pdu; + tx_pdu.set_init_msg().load_info_obj(ASN1_NGAP_NR_ID_INIT_UE_MSG); + init_ue_msg_ies_container& container = tx_pdu.init_msg().value.init_ue_msg().protocol_ies; + + // 5G-S-TMSI + if (has_tmsi) { + container.five_g_s_tmsi_present = true; + srsran::uint32_to_uint8(s_tmsi, container.five_g_s_tmsi.value.five_g_tmsi.data()); + container.five_g_s_tmsi.value.amf_set_id.from_number(ctxt.amf_set_id); + container.five_g_s_tmsi.value.amf_pointer.from_number(ctxt.amf_pointer); + } + + // RAN_UE_NGAP_ID + container.ran_ue_ngap_id.value = ctxt.ran_ue_ngap_id; + + // NAS_PDU + container.nas_pdu.value.resize(pdu->N_bytes); + memcpy(container.nas_pdu.value.data(), pdu->msg, pdu->N_bytes); + + // RRC Establishment Cause + container.rrcestablishment_cause.value = cause; + + // User Location Info + + // userLocationInformationNR + container.user_location_info.value.set_user_location_info_nr(); + container.user_location_info.value.user_location_info_nr().nr_cgi.nrcell_id = ngap_ptr->nr_cgi.nrcell_id; + container.user_location_info.value.user_location_info_nr().nr_cgi.plmn_id = ngap_ptr->nr_cgi.plmn_id; + container.user_location_info.value.user_location_info_nr().tai.plmn_id = ngap_ptr->tai.plmn_id; + container.user_location_info.value.user_location_info_nr().tai.tac = ngap_ptr->tai.tac; + + return ngap_ptr->sctp_send_ngap_pdu(tx_pdu, ctxt.rnti, "InitialUEMessage"); +} + +bool ngap::ue::send_ulnastransport(srsran::unique_byte_buffer_t pdu) +{ + if (not ngap_ptr->amf_connected) { + return false; + } + + ngap_pdu_c tx_pdu; + tx_pdu.set_init_msg().load_info_obj(ASN1_NGAP_NR_ID_UL_NAS_TRANSPORT); + asn1::ngap_nr::ul_nas_transport_ies_container& container = tx_pdu.init_msg().value.ul_nas_transport().protocol_ies; + + // AMF UE NGAP ID + container.amf_ue_ngap_id.value = ctxt.amf_ue_ngap_id.value(); + + // RAN UE NGAP ID + container.ran_ue_ngap_id.value = ctxt.ran_ue_ngap_id; + + // NAS PDU + container.nas_pdu.value.resize(pdu->N_bytes); + memcpy(container.nas_pdu.value.data(), pdu->msg, pdu->N_bytes); + + // User Location Info + // userLocationInformationNR + container.user_location_info.value.set_user_location_info_nr(); + container.user_location_info.value.user_location_info_nr().nr_cgi.nrcell_id = ngap_ptr->nr_cgi.nrcell_id; + container.user_location_info.value.user_location_info_nr().nr_cgi.plmn_id = ngap_ptr->nr_cgi.plmn_id; + container.user_location_info.value.user_location_info_nr().tai.plmn_id = ngap_ptr->tai.plmn_id; + container.user_location_info.value.user_location_info_nr().tai.tac = ngap_ptr->tai.tac; + + return ngap_ptr->sctp_send_ngap_pdu(tx_pdu, ctxt.rnti, "UplinkNASTransport"); +} + +void ngap::ue::ue_ctxt_setup_complete() +{ + ngap_pdu_c tx_pdu; + // Handle PDU Session List once RRC interface is ready + tx_pdu.set_successful_outcome().load_info_obj(ASN1_NGAP_NR_ID_INIT_CONTEXT_SETUP); + auto& container = tx_pdu.successful_outcome().value.init_context_setup_resp().protocol_ies; +} + +bool ngap::send_error_indication(const asn1::ngap_nr::cause_c& cause, + srsran::optional ran_ue_ngap_id, + srsran::optional amf_ue_ngap_id) +{ + if (not amf_connected) { + return false; + } + + ngap_pdu_c tx_pdu; + tx_pdu.set_init_msg().load_info_obj(ASN1_NGAP_NR_ID_ERROR_IND); + auto& container = tx_pdu.init_msg().value.error_ind().protocol_ies; + + uint16_t rnti = SRSRAN_INVALID_RNTI; + container.ran_ue_ngap_id_present = ran_ue_ngap_id.has_value(); + if (ran_ue_ngap_id.has_value()) { + container.ran_ue_ngap_id.value = ran_ue_ngap_id.value(); + ue* user_ptr = users.find_ue_gnbid(ran_ue_ngap_id.value()); + rnti = user_ptr != nullptr ? user_ptr->ctxt.rnti : SRSRAN_INVALID_RNTI; + } + container.amf_ue_ngap_id_present = amf_ue_ngap_id.has_value(); + if (amf_ue_ngap_id.has_value()) { + container.amf_ue_ngap_id.value = amf_ue_ngap_id.value(); + } + + container.cause_present = true; + container.cause.value = cause; + + return sctp_send_ngap_pdu(tx_pdu, rnti, "Error Indication"); +} + +/******************************************************************************* +/* ngap::ue Class +********************************************************************************/ + +ngap::ue::ue(ngap* ngap_ptr_) : ngap_ptr(ngap_ptr_) +{ + ctxt.ran_ue_ngap_id = ngap_ptr->next_gnb_ue_ngap_id++; + gettimeofday(&ctxt.init_timestamp, nullptr); + + stream_id = ngap_ptr->next_ue_stream_id; +} + /******************************************************************************* /* General helpers ********************************************************************************/ @@ -374,14 +736,14 @@ bool ngap::sctp_send_ngap_pdu(const asn1::ngap_nr::ngap_pdu_c& tx_pdu, uint32_t // } if (rnti != SRSRAN_INVALID_RNTI) { - logger.info(buf->msg, buf->N_bytes, "Tx S1AP SDU, %s, rnti=0x%x", procedure_name, rnti); + logger.info(buf->msg, buf->N_bytes, "Tx NGAP SDU, %s, rnti=0x%x", procedure_name, rnti); } else { - logger.info(buf->msg, buf->N_bytes, "Tx S1AP SDU, %s", procedure_name); + logger.info(buf->msg, buf->N_bytes, "Tx NGAP SDU, %s", procedure_name); } - // TODO: when user list is ready - // uint16_t streamid = rnti == SRSRAN_INVALID_RNTI ? NONUE_STREAM_ID : users.find_ue_rnti(rnti)->stream_id; - uint16_t streamid = 0; - ssize_t n_sent = sctp_sendmsg(amf_socket.fd(), + + uint16_t streamid = rnti == SRSRAN_INVALID_RNTI ? NONUE_STREAM_ID : users.find_ue_rnti(rnti)->stream_id; + + ssize_t n_sent = sctp_sendmsg(amf_socket.fd(), buf->msg, buf->N_bytes, (struct sockaddr*)&amf_addr, @@ -393,13 +755,87 @@ bool ngap::sctp_send_ngap_pdu(const asn1::ngap_nr::ngap_pdu_c& tx_pdu, uint32_t 0); if (n_sent == -1) { if (rnti != SRSRAN_INVALID_RNTI) { - logger.error("Error: Failure at Tx S1AP SDU, %s, rnti=0x%x", procedure_name, rnti); + logger.error("Error: Failure at Tx NGAP SDU, %s, rnti=0x%x", procedure_name, rnti); } else { - logger.error("Error: Failure at Tx S1AP SDU, %s", procedure_name); + logger.error("Error: Failure at Tx NGAP SDU, %s", procedure_name); } return false; } return true; } +/** + * Helper method to find user based on the ran_ue_ngap_id stored in an S1AP Msg, and update amf_ue_ngap_id + * @param gnb_id ran_ue_ngap_id value stored in NGAP message + * @param amf_id amf_ue_ngap_id value stored in NGAP message + * @return pointer to user if it has been found + */ +ngap::ue* ngap::handle_ngapmsg_ue_id(uint32_t gnb_id, uint32_t amf_id) +{ + ue* user_ptr = users.find_ue_gnbid(gnb_id); + ue* user_amf_ptr = nullptr; + cause_c cause; + // TODO: Introduce proper error handling for faulty ids + if (user_ptr != nullptr) { + if (user_ptr->ctxt.amf_ue_ngap_id == amf_id) { + return user_ptr; + } + + user_amf_ptr = users.find_ue_amfid(amf_id); + if (not user_ptr->ctxt.amf_ue_ngap_id.has_value() and user_amf_ptr == nullptr) { + user_ptr->ctxt.amf_ue_ngap_id = amf_id; + return user_ptr; + } + + logger.warning("AMF UE NGAP ID=%d not found - discarding message", amf_id); + if (user_amf_ptr != nullptr) { + cause.set_radio_network().value = cause_radio_network_opts::unknown_target_id; + } + + } else { + user_amf_ptr = users.find_ue_amfid(amf_id); + logger.warning("RAN UE NGAP ID=%d not found - discarding message", gnb_id); + if (user_amf_ptr != nullptr) { + cause.set_radio_network().value = cause_radio_network_opts::unknown_local_ue_ngap_id; + } + } + + send_error_indication(cause, gnb_id, amf_id); + + if (user_ptr != nullptr) { + // rrc->release_ue(user_ptr->ctxt.rnti); + } + if (user_amf_ptr != nullptr and user_amf_ptr != user_ptr) { + // rrc->release_ue(user_mme_ptr->ctxt.rnti); + } + return nullptr; +} + +std::string ngap::get_cause(const cause_c& c) +{ + std::string cause = c.type().to_string(); + cause += " - "; + switch (c.type().value) { + case cause_c::types_opts::radio_network: + cause += c.radio_network().to_string(); + break; + case cause_c::types_opts::transport: + cause += c.transport().to_string(); + break; + case cause_c::types_opts::nas: + cause += c.nas().to_string(); + break; + case cause_c::types_opts::protocol: + cause += c.protocol().to_string(); + break; + case cause_c::types_opts::misc: + cause += c.misc().to_string(); + break; + default: + cause += "unknown"; + break; + } + return cause; +} + } // namespace srsenb diff --git a/srsenb/test/CMakeLists.txt b/srsenb/test/CMakeLists.txt index b648a8e05..a7d93ea1f 100644 --- a/srsenb/test/CMakeLists.txt +++ b/srsenb/test/CMakeLists.txt @@ -11,6 +11,7 @@ add_subdirectory(phy) add_subdirectory(upper) add_subdirectory(rrc) add_subdirectory(s1ap) +add_subdirectory(ngap) add_executable(enb_metrics_test enb_metrics_test.cc ../src/metrics_stdout.cc ../src/metrics_csv.cc) target_link_libraries(enb_metrics_test srsran_phy srsran_common) diff --git a/srsenb/test/ngap/CMakeLists.txt b/srsenb/test/ngap/CMakeLists.txt new file mode 100644 index 000000000..0824d8aac --- /dev/null +++ b/srsenb/test/ngap/CMakeLists.txt @@ -0,0 +1,13 @@ +# +# Copyright 2013-2021 Software Radio Systems Limited +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the distribution. +# + +add_executable(ngap_test ngap_test.cc) +target_link_libraries(ngap_test srsran_common ngap_nr_asn1 srsenb_upper srsran_upper ngap_nr_asn1 srsgnb_upper srsgnb_ngap ${SCTP_LIBRARIES}) + +add_test(ngap_test ngap_test) + diff --git a/srsenb/test/ngap/ngap_test.cc b/srsenb/test/ngap/ngap_test.cc new file mode 100644 index 000000000..d21bf7223 --- /dev/null +++ b/srsenb/test/ngap/ngap_test.cc @@ -0,0 +1,152 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "srsenb/hdr/stack/ngap/ngap.h" +#include "srsran/common/network_utils.h" +#include "srsran/common/test_common.h" + +using namespace srsenb; + +struct amf_dummy { + amf_dummy(const char* addr_str_, int port_) : addr_str(addr_str_), port(port_) + { + srsran::net_utils::set_sockaddr(&amf_sockaddr, addr_str, port); + { + using namespace srsran::net_utils; + fd = open_socket(addr_family::ipv4, socket_type::seqpacket, protocol_type::SCTP); + TESTASSERT(fd > 0); + TESTASSERT(bind_addr(fd, amf_sockaddr)); + } + + int success = listen(fd, SOMAXCONN); + srsran_assert(success == 0, "Failed to listen to incoming SCTP connections"); + } + + ~amf_dummy() + { + if (fd > 0) { + close(fd); + } + } + + srsran::unique_byte_buffer_t read_msg(sockaddr_in* sockfrom = nullptr) + { + srsran::unique_byte_buffer_t pdu = srsran::make_byte_buffer(); + sockaddr_in from = {}; + socklen_t fromlen = sizeof(from); + sctp_sndrcvinfo sri = {}; + int flags = 0; + ssize_t n_recv = sctp_recvmsg(fd, pdu->msg, pdu->get_tailroom(), (struct sockaddr*)&from, &fromlen, &sri, &flags); + if (n_recv > 0) { + if (sockfrom != nullptr) { + *sockfrom = from; + } + pdu->N_bytes = n_recv; + } + return pdu; + } + + const char* addr_str; + int port; + struct sockaddr_in amf_sockaddr = {}; + int fd; + srsran::unique_byte_buffer_t last_sdu; +}; + +struct dummy_socket_manager : public srsran::socket_manager_itf { + dummy_socket_manager() : srsran::socket_manager_itf(srslog::fetch_basic_logger("TEST")) {} + + /// Register (fd, callback). callback is called within socket thread when fd has data. + bool add_socket_handler(int fd, recv_callback_t handler) final + { + if (s1u_fd > 0) { + return false; + } + s1u_fd = fd; + callback = std::move(handler); + return true; + } + + /// remove registered socket fd + bool remove_socket(int fd) final + { + if (s1u_fd < 0) { + return false; + } + s1u_fd = -1; + return true; + } + + int s1u_fd; + recv_callback_t callback; +}; + +void run_ng_setup(ngap& ngap_obj, amf_dummy& amf) +{ + asn1::ngap_nr::ngap_pdu_c ngap_pdu; + + // gNB -> AMF: NG Setup Request + srsran::unique_byte_buffer_t sdu = amf.read_msg(); + TESTASSERT(sdu->N_bytes > 0); + asn1::cbit_ref cbref(sdu->msg, sdu->N_bytes); + TESTASSERT(ngap_pdu.unpack(cbref) == asn1::SRSASN_SUCCESS); + TESTASSERT(ngap_pdu.type().value == asn1::ngap_nr::ngap_pdu_c::types_opts::init_msg); + TESTASSERT(ngap_pdu.init_msg().proc_code == ASN1_NGAP_NR_ID_NG_SETUP); + + // AMF -> gNB: ng Setup Response + sockaddr_in amf_addr = {}; + sctp_sndrcvinfo rcvinfo = {}; + int flags = 0; + + uint8_t ng_setup_resp[] = {0x20, 0x15, 0x00, 0x55, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x31, 0x17, 0x00, 0x61, 0x6d, + 0x61, 0x72, 0x69, 0x73, 0x6f, 0x66, 0x74, 0x2e, 0x61, 0x6d, 0x66, 0x2e, 0x35, 0x67, 0x63, + 0x2e, 0x6d, 0x6e, 0x63, 0x30, 0x30, 0x31, 0x2e, 0x6d, 0x63, 0x63, 0x30, 0x30, 0x31, 0x2e, + 0x33, 0x67, 0x70, 0x70, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x6f, 0x72, 0x67, + 0x00, 0x60, 0x00, 0x08, 0x00, 0x00, 0x00, 0xf1, 0x10, 0x80, 0x01, 0x01, 0x00, 0x56, 0x40, + 0x01, 0x32, 0x00, 0x50, 0x00, 0x08, 0x00, 0x00, 0xf1, 0x10, 0x00, 0x00, 0x00, 0x08}; + memcpy(sdu->msg, ng_setup_resp, sizeof(ng_setup_resp)); + sdu->N_bytes = sizeof(ng_setup_resp); + TESTASSERT(ngap_obj.handle_amf_rx_msg(std::move(sdu), amf_addr, rcvinfo, flags)); +} + +int main(int argc, char** argv) +{ + // Setup logging. + auto& logger = srslog::fetch_basic_logger("NGAP"); + logger.set_level(srslog::basic_levels::debug); + logger.set_hex_dump_max_size(-1); + + srsran::task_scheduler task_sched; + dummy_socket_manager rx_sockets; + ngap ngap_obj(&task_sched, logger, &rx_sockets); + + const char* amf_addr_str = "127.0.0.1"; + const uint32_t AMF_PORT = 38412; + amf_dummy amf(amf_addr_str, AMF_PORT); + + ngap_args_t args = {}; + args.cell_id = 0x01; + args.gnb_id = 0x19B; + args.mcc = 907; + args.mnc = 70; + args.ngc_bind_addr = "127.0.0.100"; + args.tac = 7; + args.gtp_bind_addr = "127.0.0.100"; + args.amf_addr = amf_addr_str; + args.gnb_name = "srsgnb01"; + rrc_interface_ngap_nr rrc; + ngap_obj.init(args, &rrc); + + // Start the log backend. + srsran::test_init(argc, argv); + run_ng_setup(ngap_obj, amf); +} \ No newline at end of file