diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index c8459e96b..8f7445d2e 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -1,35 +1,44 @@ name: C/C++ CI on: push jobs: - x86_ubuntu18_build: - name: Build and test on x86 Ubuntu 18.04 - strategy: - matrix: - compiler: [gcc, clang] - runs-on: ubuntu-18.04 - steps: - - uses: actions/checkout@v1 - - name: Build srsRAN on x86 Ubuntu 18.04 - run: | - sudo apt update - sudo apt install -y build-essential cmake libfftw3-dev libmbedtls-dev libpcsclite-dev libboost-program-options-dev libconfig++-dev libsctp-dev colordiff ninja-build valgrind - mkdir build && cd build && cmake -DRF_FOUND=True -GNinja .. && ninja && ctest - - aarch64_ubuntu18_build: - runs-on: ubuntu-18.04 - name: Build on aarch64 + x86_ubuntu_build: + name: Build on x86 + runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: + os: [ubuntu-20.04, ubuntu-18.04] compiler: [gcc, clang] steps: - - uses: actions/checkout@v1 - - name: Build srsRAN on aarch64 + - uses: actions/checkout@v3 + - name: Build srsRAN on x86 ${{ matrix.os }} + run: | + sudo apt update + sudo apt install -y build-essential cmake libfftw3-dev libmbedtls-dev libpcsclite-dev libboost-program-options-dev libconfig++-dev libsctp-dev colordiff ninja-build valgrind + mkdir build && cd build && cmake -DRF_FOUND=True -GNinja .. && ninja && ctest + + aarch64_ubuntu_build: + name: Build on aarch64 + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-20.04, ubuntu-18.04] + compiler: [gcc, clang] + include: + - os: ubuntu-20.04 + distro: ubuntu20.04 + - os: ubuntu-18.04 + distro: ubuntu18.04 + steps: + - uses: actions/checkout@v3 + - name: Build srsRAN on aarch64 ${{ matrix.os }} uses: uraimo/run-on-arch-action@master with: - architecture: aarch64 - distribution: ubuntu18.04 + arch: aarch64 + distro: ${{ matrix.distro }} run: | export CTEST_PARALLEL_LEVEL=$(nproc --all) apt update apt install -y build-essential cmake libfftw3-dev libmbedtls-dev libpcsclite-dev libboost-program-options-dev libconfig++-dev libsctp-dev ninja-build - ls -l && pwd && mkdir build && cd build && cmake -DRF_FOUND=True -GNinja .. && ninja \ No newline at end of file + ls -l && pwd && mkdir build && cd build && cmake -DRF_FOUND=True -GNinja .. && ninja diff --git a/lib/include/srsran/rlc/rlc_am_lte.h b/lib/include/srsran/rlc/rlc_am_lte.h index 841d5c1ed..ca60af86c 100644 --- a/lib/include/srsran/rlc/rlc_am_lte.h +++ b/lib/include/srsran/rlc/rlc_am_lte.h @@ -95,6 +95,7 @@ private: void retransmit_pdu(uint32_t sn); // Helpers + bool window_full(); bool poll_required(); bool do_status(); void check_sn_reached_max_retx(uint32_t sn); diff --git a/lib/src/asn1/liblte_mme.cc b/lib/src/asn1/liblte_mme.cc index 2d32f310e..e3d1cff84 100644 --- a/lib/src/asn1/liblte_mme.cc +++ b/lib/src/asn1/liblte_mme.cc @@ -319,6 +319,7 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_mobile_id_ie(uint8** ie_ptr, LIBLTE_MME_MOBI { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; uint8* id; + uint32* id32; uint32 length; uint32 i; bool odd = false; @@ -338,22 +339,35 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_mobile_id_ie(uint8** ie_ptr, LIBLTE_MME_MOBI } else if (LIBLTE_MME_MOBILE_ID_TYPE_IMEISV == mobile_id->type_of_id) { id = mobile_id->imeisv; odd = false; + } else if (LIBLTE_MME_MOBILE_ID_TYPE_TMSI == mobile_id->type_of_id) { + id32 = &mobile_id->tmsi; + odd = false; } else { // TODO: Not handling these IDs return (err); } - id[0] = **ie_ptr >> 4; - *ie_ptr += 1; - for (i = 0; i < 7; i++) { - id[i * 2 + 1] = (*ie_ptr)[i] & 0x0F; - id[i * 2 + 2] = (*ie_ptr)[i] >> 4; - } - if (odd) { - *ie_ptr += 7; + if (mobile_id->type_of_id != LIBLTE_MME_MOBILE_ID_TYPE_TMSI) { + id[0] = **ie_ptr >> 4; + *ie_ptr += 1; + for (i = 0; i < 7; i++) { + id[i * 2 + 1] = (*ie_ptr)[i] & 0x0F; + id[i * 2 + 2] = (*ie_ptr)[i] >> 4; + } + if (odd) { + *ie_ptr += 7; + } else { + id[i * 2 + 1] = (*ie_ptr)[i] & 0xF; + *ie_ptr += 8; + } } else { - id[i * 2 + 1] = (*ie_ptr)[i] & 0xF; - *ie_ptr += 8; + *ie_ptr += 1; + uint32 tmsi = 0; + for (i = 0; i < 4; i++) { + tmsi += ((*ie_ptr)[i] & 0xFF) << ((3 - i) * 8); + } + *id32 = tmsi; + *ie_ptr += 4; } err = LIBLTE_SUCCESS; @@ -1380,12 +1394,13 @@ liblte_mme_unpack_eps_network_feature_support_ie(uint8** ie_ptr, LIBLTE_MME_EPS_ LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; if (ie_ptr != NULL && eps_nfs != NULL) { + int ie_len = *ie_ptr[0]; eps_nfs->esrps = ((*ie_ptr)[1] >> 5) & 0x01; eps_nfs->cs_lcs = (LIBLTE_MME_CS_LCS_ENUM)(((*ie_ptr)[1] >> 3) & 0x03); eps_nfs->epc_lcs = ((*ie_ptr)[1] >> 2) & 0x01; eps_nfs->emc_bs = ((*ie_ptr)[1] >> 1) & 0x01; eps_nfs->ims_vops = (*ie_ptr)[1] & 0x01; - *ie_ptr += 2; + *ie_ptr += (ie_len + 1); err = LIBLTE_SUCCESS; } diff --git a/lib/src/phy/fec/convolutional/test/CMakeLists.txt b/lib/src/phy/fec/convolutional/test/CMakeLists.txt index e27666179..3759bce24 100644 --- a/lib/src/phy/fec/convolutional/test/CMakeLists.txt +++ b/lib/src/phy/fec/convolutional/test/CMakeLists.txt @@ -30,7 +30,11 @@ add_test(viterbi_40_2 viterbi_test -n 1000 -s 1 -l 40 -t -e 2.0) add_test(viterbi_40_3 viterbi_test -n 1000 -s 1 -l 40 -t -e 3.0) add_test(viterbi_40_4 viterbi_test -n 1000 -s 1 -l 40 -t -e 4.5) -add_test(viterbi_1000_0 viterbi_test -n 100 -s 1 -l 1000 -t -e 0.0) +if (HAVE_AVX2) + # The accuracy of the 8-bit implementation of the Viterbi decoder used on + # non-AVX2 machines falls below the theoretical accuracy at 0dB. + add_test(viterbi_1000_0 viterbi_test -n 100 -s 1 -l 1000 -t -e 0.0) +endif() add_test(viterbi_1000_2 viterbi_test -n 100 -s 1 -l 1000 -t -e 2.0) add_test(viterbi_1000_3 viterbi_test -n 100 -s 1 -l 1000 -t -e 3.0) add_test(viterbi_1000_4 viterbi_test -n 100 -s 1 -l 1000 -t -e 4.5) diff --git a/lib/src/phy/phch/test/CMakeLists.txt b/lib/src/phy/phch/test/CMakeLists.txt index 91f6dda24..141cc9e63 100644 --- a/lib/src/phy/phch/test/CMakeLists.txt +++ b/lib/src/phy/phch/test/CMakeLists.txt @@ -211,8 +211,9 @@ 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)) + # Currently, the ARM and SSE platforms srsRAN has been tested are not capable of running 100PRB. So, skip 100 PRB in + # ARM and SSE. + if ((HAVE_NEON OR NOT HAVE_AVX2) AND (${nof_prb} EQUAL 100)) continue() endif () foreach (nof_ports 1 2) diff --git a/lib/src/rlc/rlc_am_lte.cc b/lib/src/rlc/rlc_am_lte.cc index 9ac1ce24a..383fe3b30 100644 --- a/lib/src/rlc/rlc_am_lte.cc +++ b/lib/src/rlc/rlc_am_lte.cc @@ -251,7 +251,7 @@ void rlc_am_lte_tx::get_buffer_state_nolock(uint32_t& n_bytes_newtx, uint32_t& n } // Bytes needed for tx SDUs - if (tx_window.size() < 1024) { + if (not window_full()) { n_sdus = tx_sdu_queue.get_n_sdus(); n_bytes_newtx += tx_sdu_queue.size_bytes(); if (tx_sdu != NULL) { @@ -299,7 +299,7 @@ uint32_t rlc_am_lte_tx::read_pdu(uint8_t* payload, uint32_t nof_bytes) } // Section 5.2.2.3 in TS 36.311, if tx_window is full and retx_queue empty, retransmit PDU - if (tx_window.size() >= RLC_AM_WINDOW_SIZE && retx_queue.empty()) { + if (window_full() && retx_queue.empty()) { retransmit_pdu(vt_a); } @@ -323,7 +323,7 @@ void rlc_am_lte_tx::timer_expired(uint32_t timeout_id) // Section 5.2.2.3 in TS 36.322, schedule PDU for retransmission if // (a) both tx and retx buffer are empty (excluding tx'ed PDU waiting for ack), or // (b) no new data PDU can be transmitted (tx window is full) - if ((retx_queue.empty() && tx_sdu_queue.size() == 0) || tx_window.size() >= RLC_AM_WINDOW_SIZE) { + if ((retx_queue.empty() && tx_sdu_queue.size() == 0) || window_full()) { retransmit_pdu(vt_a); // TODO: TS says to send vt_s - 1 here } } else if (status_prohibit_timer.is_valid() && status_prohibit_timer.id() == timeout_id) { @@ -368,6 +368,11 @@ void rlc_am_lte_tx::retransmit_pdu(uint32_t sn) * Helper functions ***************************************************************************/ +bool rlc_am_lte_tx::window_full() +{ + return TX_MOD_BASE(vt_s) >= RLC_AM_WINDOW_SIZE; +}; + /** * Called when building a RLC PDU for checking whether the poll bit needs * to be set. @@ -394,7 +399,7 @@ bool rlc_am_lte_tx::poll_required() return true; } - if (tx_window.size() >= RLC_AM_WINDOW_SIZE) { + if (window_full()) { RlcDebug("Poll required. Cause: TX window full."); return true; } @@ -699,7 +704,7 @@ int rlc_am_lte_tx::build_data_pdu(uint8_t* payload, uint32_t nof_bytes) } // do not build any more PDU if window is already full - if (tx_window.size() >= RLC_AM_WINDOW_SIZE) { + if (window_full()) { RlcInfo("Cannot build data PDU - Tx window full."); return 0; } @@ -1165,7 +1170,8 @@ rlc_am_lte_rx::rlc_am_lte_rx(rlc_am* parent_) : pool(byte_buffer_pool::get_instance()), reordering_timer(parent_->timers->get_unique_timer()), rlc_am_base_rx(parent_, parent_->logger) -{} +{ +} bool rlc_am_lte_rx::configure(const rlc_config_t& cfg_) { diff --git a/lib/test/rlc/rlc_am_lte_test.cc b/lib/test/rlc/rlc_am_lte_test.cc index 50ecc5d8a..090165c52 100644 --- a/lib/test/rlc/rlc_am_lte_test.cc +++ b/lib/test/rlc/rlc_am_lte_test.cc @@ -3766,6 +3766,322 @@ bool poll_retx_expiry_test() return SRSRAN_SUCCESS; } +bool full_window_check_test() +{ + rlc_config_t config = rlc_config_t::default_rlc_am_config(); + // [I] SRB1 configured: t_poll_retx=65, poll_pdu=-1, poll_byte=-1, max_retx_thresh=6, t_reordering=55, + // t_status_prohibit=0 + config.am.t_poll_retx = 65; + config.am.poll_pdu = -1; + config.am.poll_byte = -1; + config.am.max_retx_thresh = 6; + config.am.t_reordering = 55; + config.am.t_status_prohibit = 55; + +#if HAVE_PCAP + rlc_pcap pcap; + pcap.open("rlc_am_poll_rext_expiry_test.pcap", config); + rlc_am_tester tester(true, &pcap); +#else + rlc_am_tester tester(true, NULL); +#endif + + srsran::timer_handler timers(8); + + rlc_am rlc1(srsran_rat_t::lte, srslog::fetch_basic_logger("RLC_AM_1"), 1, &tester, &tester, &timers); + rlc_am rlc2(srsran_rat_t::lte, srslog::fetch_basic_logger("RLC_AM_2"), 1, &tester, &tester, &timers); + + srslog::fetch_basic_logger("RLC_AM_1").set_hex_dump_max_size(100); + srslog::fetch_basic_logger("RLC_AM_2").set_hex_dump_max_size(100); + srslog::fetch_basic_logger("RLC").set_hex_dump_max_size(100); + + if (not rlc1.configure(config)) { + return -1; + } + + if (not rlc2.configure(config)) { + return -1; + } + + { + // Initial Tx + uint32_t num_tx_pdus = 512; + for (uint32_t i = 0; i < num_tx_pdus; ++i) { + // Write SDU + unique_byte_buffer_t sdu = srsran::make_byte_buffer(); + TESTASSERT(sdu != nullptr); + sdu->N_bytes = 1; + sdu->msg[0] = i; + sdu->md.pdcp_sn = i; + rlc1.write_sdu(std::move(sdu)); + + unique_byte_buffer_t pdu = srsran::make_byte_buffer(); + TESTASSERT(pdu != nullptr); + pdu->N_bytes = 1; + pdu->msg[0] = i; + pdu->md.pdcp_sn = i; + pdu->N_bytes = rlc1.read_pdu(pdu->msg, 3); + TESTASSERT(pdu->N_bytes == 3); + } + } + { + // Tx one more to check the window is full + unique_byte_buffer_t sdu = srsran::make_byte_buffer(); + TESTASSERT(sdu != nullptr); + sdu->N_bytes = 1; + sdu->msg[0] = 0; + sdu->md.pdcp_sn = 512; + rlc1.write_sdu(std::move(sdu)); + + unique_byte_buffer_t pdu = srsran::make_byte_buffer(); + TESTASSERT(pdu != nullptr); + pdu->N_bytes = rlc1.read_pdu(pdu->msg, 3); + TESTASSERT(pdu->N_bytes == 3); + + // If the TX window is full, we should RETX SN=0 + rlc_amd_pdu_header_t header = {}; + rlc_am_read_data_pdu_header(&pdu->msg, &pdu->N_bytes, &header); + TESTASSERT_EQ(header.sn, 0); + TESTASSERT_EQ(header.N_li, 0); + TESTASSERT_EQ(header.fi, 0); + } + + // Ack one SN in the middle of the TX window. + // This is done to make sure the full window check is correct + // even if PDUs in the middle of the window are ACKed. + // ACK_SN=3, NACK_SN=0 + { + rlc_status_pdu_t status = {}; + status.ack_sn = 3; + status.N_nack = 1; + status.nacks[0].nack_sn = 0; + + unique_byte_buffer_t status_buf = srsran::make_byte_buffer(); + TESTASSERT(status_buf != nullptr); + rlc_am_write_status_pdu(&status, status_buf.get()); + rlc1.write_pdu(status_buf->msg, status_buf->N_bytes); + + // Read RETX for SN=0 from NACK + unique_byte_buffer_t pdu = srsran::make_byte_buffer(); + TESTASSERT(pdu != nullptr); + pdu->N_bytes = rlc1.read_pdu(pdu->msg, 3); + TESTASSERT(pdu->N_bytes == 3); + + // Check RETX SN=0 + rlc_amd_pdu_header_t header = {}; + rlc_am_read_data_pdu_header(&pdu->msg, &pdu->N_bytes, &header); + TESTASSERT_EQ(header.sn, 0); + TESTASSERT_EQ(header.N_li, 0); + TESTASSERT_EQ(header.fi, 0); + TESTASSERT_EQ(0, rlc1.get_buffer_state()); + } + { + // Tx more PDUs to check the window is still full + uint32_t num_tx_pdus = 2; + for (uint32_t i = 0; i < num_tx_pdus; ++i) { + // Write SDU + unique_byte_buffer_t sdu = srsran::make_byte_buffer(); + TESTASSERT(sdu != nullptr); + sdu->N_bytes = 1; + sdu->msg[0] = i; + sdu->md.pdcp_sn = i; + rlc1.write_sdu(std::move(sdu)); + + unique_byte_buffer_t pdu = srsran::make_byte_buffer(); + TESTASSERT(pdu != nullptr); + pdu->N_bytes = 1; + pdu->msg[0] = i; + pdu->md.pdcp_sn = i; + pdu->N_bytes = rlc1.read_pdu(pdu->msg, 3); + TESTASSERT(pdu->N_bytes == 3); + + // If the TX window is full, we should RETX SN=0 + rlc_amd_pdu_header_t header = {}; + rlc_am_read_data_pdu_header(&pdu->msg, &pdu->N_bytes, &header); + TESTASSERT_EQ(header.sn, 0); + TESTASSERT_EQ(header.N_li, 0); + TESTASSERT_EQ(header.fi, 0); + } + } + // ACK more PDUs and advance VT(A). + // New PDUs should be available to read now. + { + rlc_status_pdu_t status = {}; + status.ack_sn = 5; + status.N_nack = 0; + + unique_byte_buffer_t status_buf = srsran::make_byte_buffer(); + TESTASSERT(status_buf != nullptr); + rlc_am_write_status_pdu(&status, status_buf.get()); + rlc1.write_pdu(status_buf->msg, status_buf->N_bytes); + + // Read new PDU + unique_byte_buffer_t pdu = srsran::make_byte_buffer(); + TESTASSERT(pdu != nullptr); + pdu->N_bytes = rlc1.read_pdu(pdu->msg, 3); + TESTASSERT(pdu->N_bytes == 3); + + // If the TX window is no longer full, we should TX a new SN (SN=512) + rlc_amd_pdu_header_t header = {}; + rlc_am_read_data_pdu_header(&pdu->msg, &pdu->N_bytes, &header); + TESTASSERT_EQ(header.sn, 512); + TESTASSERT_EQ(header.N_li, 0); + TESTASSERT_EQ(header.fi, 0); + } + +#if HAVE_PCAP + pcap.close(); +#endif + + return SRSRAN_SUCCESS; +} + +bool full_window_check_wraparound_test() +{ + rlc_config_t config = rlc_config_t::default_rlc_am_config(); + // [I] SRB1 configured: t_poll_retx=65, poll_pdu=-1, poll_byte=-1, max_retx_thresh=6, t_reordering=55, + // t_status_prohibit=0 + config.am.t_poll_retx = 65; + config.am.poll_pdu = -1; + config.am.poll_byte = -1; + config.am.max_retx_thresh = 6; + config.am.t_reordering = 55; + config.am.t_status_prohibit = 55; + +#if HAVE_PCAP + rlc_pcap pcap; + pcap.open("rlc_am_poll_rext_expiry_test.pcap", config); + rlc_am_tester tester(true, &pcap); +#else + rlc_am_tester tester(true, NULL); +#endif + + uint32_t pdcp_count = 0; + + srsran::timer_handler timers(8); + + rlc_am rlc1(srsran_rat_t::lte, srslog::fetch_basic_logger("RLC_AM_1"), 1, &tester, &tester, &timers); + rlc_am rlc2(srsran_rat_t::lte, srslog::fetch_basic_logger("RLC_AM_2"), 1, &tester, &tester, &timers); + + srslog::fetch_basic_logger("RLC_AM_1").set_hex_dump_max_size(100); + srslog::fetch_basic_logger("RLC_AM_2").set_hex_dump_max_size(100); + srslog::fetch_basic_logger("RLC").set_hex_dump_max_size(100); + + if (not rlc1.configure(config)) { + return -1; + } + + if (not rlc2.configure(config)) { + return -1; + } + + // Advance vt_a to 512 and vt_s to 512 as well. + { + // Initial Tx + uint32_t num_tx_pdus = 512; + for (uint32_t i = 0; i < num_tx_pdus; ++i) { + // Write SDU + unique_byte_buffer_t sdu = srsran::make_byte_buffer(); + TESTASSERT(sdu != nullptr); + sdu->N_bytes = 1; + sdu->msg[0] = i; + sdu->md.pdcp_sn = pdcp_count++; + rlc1.write_sdu(std::move(sdu)); + + unique_byte_buffer_t pdu = srsran::make_byte_buffer(); + TESTASSERT(pdu != nullptr); + pdu->N_bytes = rlc1.read_pdu(pdu->msg, 3); + TESTASSERT(pdu->N_bytes == 3); + } + + // ACK all SNs to advance the TX window. + rlc_status_pdu_t status = {}; + status.ack_sn = num_tx_pdus; + status.N_nack = 0; + + unique_byte_buffer_t status_buf = srsran::make_byte_buffer(); + TESTASSERT(status_buf != nullptr); + rlc_am_write_status_pdu(&status, status_buf.get()); + rlc1.write_pdu(status_buf->msg, status_buf->N_bytes); + } + + // Advance vt_a and vt_s to 1023 + { + // Initial Tx + uint32_t num_tx_pdus = 511; + for (uint32_t i = 0; i < num_tx_pdus; ++i) { + // Write SDU + unique_byte_buffer_t sdu = srsran::make_byte_buffer(); + TESTASSERT(sdu != nullptr); + sdu->N_bytes = 1; + sdu->msg[0] = i; + sdu->md.pdcp_sn = pdcp_count++; + rlc1.write_sdu(std::move(sdu)); + + unique_byte_buffer_t pdu = srsran::make_byte_buffer(); + TESTASSERT(pdu != nullptr); + pdu->N_bytes = rlc1.read_pdu(pdu->msg, 3); + TESTASSERT(pdu->N_bytes == 3); + } + + // ACK all SNs to advance the TX window. + rlc_status_pdu_t status = {}; + status.ack_sn = 512 + num_tx_pdus; + status.N_nack = 0; + + unique_byte_buffer_t status_buf = srsran::make_byte_buffer(); + TESTASSERT(status_buf != nullptr); + rlc_am_write_status_pdu(&status, status_buf.get()); + rlc1.write_pdu(status_buf->msg, status_buf->N_bytes); + } + + // Now, fill up the window + { + // Initial Tx + uint32_t num_tx_pdus = 512; + for (uint32_t i = 0; i < num_tx_pdus; ++i) { + // Write SDU + unique_byte_buffer_t sdu = srsran::make_byte_buffer(); + TESTASSERT(sdu != nullptr); + sdu->N_bytes = 1; + sdu->msg[0] = i; + sdu->md.pdcp_sn = pdcp_count++; + rlc1.write_sdu(std::move(sdu)); + + unique_byte_buffer_t pdu = srsran::make_byte_buffer(); + TESTASSERT(pdu != nullptr); + pdu->N_bytes = rlc1.read_pdu(pdu->msg, 3); + TESTASSERT(pdu->N_bytes == 3); + } + } + { + // Tx one more to check the window is full + unique_byte_buffer_t sdu = srsran::make_byte_buffer(); + TESTASSERT(sdu != nullptr); + sdu->N_bytes = 1; + sdu->msg[0] = 0; + sdu->md.pdcp_sn = pdcp_count++; + rlc1.write_sdu(std::move(sdu)); + + unique_byte_buffer_t pdu = srsran::make_byte_buffer(); + TESTASSERT(pdu != nullptr); + pdu->N_bytes = rlc1.read_pdu(pdu->msg, 3); + TESTASSERT(pdu->N_bytes == 3); + + // If the TX window is full, we should RETX SN=1023 + rlc_amd_pdu_header_t header = {}; + rlc_am_read_data_pdu_header(&pdu->msg, &pdu->N_bytes, &header); + TESTASSERT_EQ(header.sn, 1023); + TESTASSERT_EQ(header.N_li, 0); + TESTASSERT_EQ(header.fi, 0); + } + +#if HAVE_PCAP + pcap.close(); +#endif + + return SRSRAN_SUCCESS; +} int main(int argc, char** argv) { // Setup the log message spy to intercept error and warning log entries from RLC @@ -3975,5 +4291,15 @@ int main(int argc, char** argv) printf("poll_retx_expiry_test failed\n"); exit(-1); }; + + if (full_window_check_test()) { + printf("full_window_check_test failed\n"); + exit(-1); + }; + + if (full_window_check_wraparound_test()) { + printf("full_window_check_wraparound_test failed\n"); + exit(-1); + }; return SRSRAN_SUCCESS; } diff --git a/srsenb/sib.conf.example b/srsenb/sib.conf.example index 0d4e60aa4..69bc9c077 100644 --- a/srsenb/sib.conf.example +++ b/srsenb/sib.conf.example @@ -137,12 +137,65 @@ sib3 = } }; +##################################################################### +# sib6 configuration options (See TS 36.331) +# Contains UTRA neighbor information for inter-rat handover. +# Must be added to sib1::sched_info::si_mapping_info array parameter to be transmitted +# +# t_resel_utra: Cell reselection timer (seconds) +# t_resel_utra_sf: Optional speed dependent ScalingFactor for t_resel_utra. +# sf_medium: Scaling factor if the UE is in Medium Mobility state, one of "0.25", "0.5", "0.75" or "1.0". +# sf_high: Scaling factor if the UE is in High Mobility state, one of "0.25", "0.5", "0.75" or "1.0". +# carrier_freq_list_utra_fdd / carrier_freq_list_utra_tdd: A list of carrier frequencies of UTRA FDD / TDD. +# carrier_freq: The UARFCN for the UTRA carrier frequency. +# cell_resel_prio: Optional absolute priority of the carrier frequency group. +# thresh_x_high: Srclev threshold (dB) to select to a higher-priority RAT/Frequency. +# thresh_x_low: Srclev threshold (dB) to select to a lower-priority RAT/Frequency. +# q_rx_lev_min: Minimum receive level in UTRA cell, ([field_val] * 2) + 1 = [level in dBm]. +# p_max_utra: The maximum allowed transmission power on the (uplink) carrier frequency. +# q_qual_min: Minimum required quality leve in UTRA cell, applicable only for FDD cells. +# +##################################################################### +sib6 = +{ + t_resel_utra = 1; + t_resel_utra_sf = { + sf_medium = "0.25"; + sf_high = "1.0"; + } + carrier_freq_list_utra_fdd = + ( + { + carrier_freq = 9613; + cell_resel_prio = 6; + thresh_x_high = 3; + thresh_x_low = 2; + q_rx_lev_min = -50; + p_max_utra = 4; + q_qual_min = -10; + } + ); + carrier_freq_list_utra_tdd = + ( + { + carrier_freq = 9505; + thresh_x_high = 1; + thresh_x_low = 2; + q_rx_lev_min = -50; + p_max_utra = -3; + } + ); +}; + ##################################################################### # sib7 configuration options (See TS 36.331) # Contains GERAN neighbor information for CSFB and inter-rat handover. # Must be added to sib1::sched_info::si_mapping_info array parameter to be transmitted # # t_resel_geran: Cell reselection timer (seconds) +# t_resel_geran_sf: Optional speed dependent ScalingFactor for t_resel_geran. +# sf_medium: Scaling factor if the UE is in Medium Mobility state, one of "0.25", "0.5", "0.75" or "1.0". +# sf_high: Scaling factor if the UE is in High Mobility state, one of "0.25", "0.5", "0.75" or "1.0". # carrier_freqs_info_list: A list of carrier frequency groups. # cell_resel_prio: Absolute priority of the carrier frequency group # ncc_permitted: 8-bit bitmap of NCC carriers permitted for monitoring diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index 1769d96cd..c9b642192 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -133,7 +133,7 @@ int field_intra_neigh_cell_list::parse(libconfig::Setting& root) int field_intra_black_cell_list::parse(libconfig::Setting& root) { data->intra_freq_black_cell_list.resize((uint32_t)root.getLength()); - data->intra_freq_black_cell_list_present = data->intra_freq_neigh_cell_list.size() > 0; + data->intra_freq_black_cell_list_present = data->intra_freq_black_cell_list.size() > 0; for (uint32_t i = 0; i < data->intra_freq_black_cell_list.size() && i < ASN1_RRC_MAX_CELL_BLACK; i++) { if (not parse_enum_by_number(data->intra_freq_black_cell_list[i].range, "range", root[i])) { fprintf(stderr, "Missing field range in black_cell=%d\n", i); @@ -151,6 +151,111 @@ int field_intra_black_cell_list::parse(libconfig::Setting& root) return 0; } +int field_carrier_freq_list_utra_fdd::parse(libconfig::Setting& root) +{ + data->carrier_freq_list_utra_fdd.resize((uint32_t)root.getLength()); + data->carrier_freq_list_utra_fdd_present = data->carrier_freq_list_utra_fdd.size() > 0; + for (uint32_t i = 0; i < data->carrier_freq_list_utra_fdd.size() && i < ASN1_RRC_MAX_UTRA_FDD_CARRIER; i++) { + unsigned int carrier_freq = 0; + if (!root[i].lookupValue("carrier_freq", carrier_freq)) { + fprintf(stderr, "Missing field `carrier_freq` in carrier_freq_list_utra_fdd=%d\n", i); + return SRSRAN_ERROR; + } + data->carrier_freq_list_utra_fdd[i].carrier_freq = carrier_freq; + + unsigned int cell_resel_prio = 0; + if (root[i].lookupValue("cell_resel_prio", cell_resel_prio)) { + data->carrier_freq_list_utra_fdd[i].cell_resel_prio_present = true; + data->carrier_freq_list_utra_fdd[i].cell_resel_prio = cell_resel_prio; + } + + unsigned int thresh_x_high = 0; + if (!root[i].lookupValue("thresh_x_high", thresh_x_high)) { + ERROR("Missing field `thresh_x_high` in carrier_freq_list_utra_fdd=%d", i); + return SRSRAN_ERROR; + } + data->carrier_freq_list_utra_fdd[i].thresh_x_high = thresh_x_high; + + unsigned int thresh_x_low = 0; + if (!root[i].lookupValue("thresh_x_low", thresh_x_low)) { + ERROR("Missing field `thresh_x_low` in carrier_freq_list_utra_fdd=%d", i); + return SRSRAN_ERROR; + } + data->carrier_freq_list_utra_fdd[i].thresh_x_low = thresh_x_low; + + int q_rx_lev_min = 0; + if (!root[i].lookupValue("q_rx_lev_min", q_rx_lev_min)) { + ERROR("Missing field `q_rx_lev_min` in carrier_freq_list_utra_fdd=%d", i); + return SRSRAN_ERROR; + } + data->carrier_freq_list_utra_fdd[i].q_rx_lev_min = q_rx_lev_min; + + int p_max_utra = 0; + if (!root[i].lookupValue("p_max_utra", p_max_utra)) { + ERROR("Missing field `p_max_utra` in carrier_freq_list_utra_fdd=%d", i); + return SRSRAN_ERROR; + } + data->carrier_freq_list_utra_fdd[i].p_max_utra = p_max_utra; + + int q_qual_min = 0; + if (!root[i].lookupValue("q_qual_min", q_qual_min)) { + ERROR("Missing field `q_qual_min` in carrier_freq_list_utra_fdd=%d", i); + return SRSRAN_ERROR; + } + data->carrier_freq_list_utra_fdd[i].q_qual_min = q_qual_min; + } + return 0; +} + +int field_carrier_freq_list_utra_tdd::parse(libconfig::Setting& root) +{ + data->carrier_freq_list_utra_tdd.resize((uint32_t)root.getLength()); + data->carrier_freq_list_utra_tdd_present = data->carrier_freq_list_utra_tdd.size() > 0; + for (uint32_t i = 0; i < data->carrier_freq_list_utra_tdd.size() && i < ASN1_RRC_MAX_UTRA_TDD_CARRIER; i++) { + unsigned int carrier_freq = 0; + if (!root[i].lookupValue("carrier_freq", carrier_freq)) { + fprintf(stderr, "Missing field `carrier_freq` in carrier_freq_list_utra_tdd=%d\n", i); + return SRSRAN_ERROR; + } + data->carrier_freq_list_utra_tdd[i].carrier_freq = carrier_freq; + + unsigned int cell_resel_prio = 0; + if (root[i].lookupValue("cell_resel_prio", cell_resel_prio)) { + data->carrier_freq_list_utra_tdd[i].cell_resel_prio_present = true; + data->carrier_freq_list_utra_tdd[i].cell_resel_prio = cell_resel_prio; + } + + unsigned int thresh_x_high = 0; + if (!root[i].lookupValue("thresh_x_high", thresh_x_high)) { + ERROR("Missing field `thresh_x_high` in carrier_freq_list_utra_tdd=%d", i); + return SRSRAN_ERROR; + } + data->carrier_freq_list_utra_tdd[i].thresh_x_high = thresh_x_high; + + unsigned int thresh_x_low = 0; + if (!root[i].lookupValue("thresh_x_low", thresh_x_low)) { + ERROR("Missing field `thresh_x_low` in carrier_freq_list_utra_tdd=%d", i); + return SRSRAN_ERROR; + } + data->carrier_freq_list_utra_tdd[i].thresh_x_low = thresh_x_low; + + int q_rx_lev_min = 0; + if (!root[i].lookupValue("q_rx_lev_min", q_rx_lev_min)) { + ERROR("Missing field `q_rx_lev_min` in carrier_freq_list_utra_tdd=%d", i); + return SRSRAN_ERROR; + } + data->carrier_freq_list_utra_tdd[i].q_rx_lev_min = q_rx_lev_min; + + int p_max_utra = 0; + if (!root[i].lookupValue("p_max_utra", p_max_utra)) { + ERROR("Missing field `p_max_utra` in carrier_freq_list_utra_tdd=%d", i); + return SRSRAN_ERROR; + } + data->carrier_freq_list_utra_tdd[i].p_max_utra = p_max_utra; + } + return 0; +} + int field_carrier_freqs_info_list::parse(libconfig::Setting& root) { data->carrier_freqs_info_list.resize((uint32_t)root.getLength()); @@ -175,7 +280,7 @@ int field_carrier_freqs_info_list::parse(libconfig::Setting& root) field_asn1_bitstring_number, uint8_t> ncc_permitted( "ncc_permitted", &data->carrier_freqs_info_list[i].common_info.ncc_permitted); if (ncc_permitted.parse(root[i])) { - ERROR("Error parsing `ncc_permitted` in carrier_freqs_info_lsit=%d", i); + ERROR("Error parsing `ncc_permitted` in carrier_freqs_info_list=%d", i); return SRSRAN_ERROR; } @@ -2003,7 +2108,7 @@ int parse_sib2(std::string filename, sib_type2_s* data) acbarring_data.add_field( make_asn1_enum_number_str_parser("factor", &data->ac_barr_info.ac_barr_for_mo_data.ac_barr_factor)); - acbarring_data.add_field(make_asn1_enum_number_parser("fime", &data->ac_barr_info.ac_barr_for_mo_data.ac_barr_time)); + acbarring_data.add_field(make_asn1_enum_number_parser("time", &data->ac_barr_info.ac_barr_for_mo_data.ac_barr_time)); acbarring_data.add_field(make_asn1_bitstring_number_parser( "for_special_ac", &data->ac_barr_info.ac_barr_for_mo_data.ac_barr_for_special_ac)); @@ -2240,12 +2345,48 @@ int parse_sib4(std::string filename, sib_type4_s* data) return parser::parse_section(std::move(filename), &sib4); } +int parse_sib6(std::string filename, sib_type6_s* data) +{ + parser::section sib6("sib6"); + + // t-ReselectionUTRA + sib6.add_field(new parser::field("t_resel_utra", &data->t_resel_utra)); + + // t-ReselectionUTRA-SF + parser::section t_resel_utra_sf("t_resel_utra_sf"); + sib6.add_subsection(&t_resel_utra_sf); + t_resel_utra_sf.set_optional(&data->t_resel_utra_sf_present); + t_resel_utra_sf.add_field(make_asn1_enum_number_str_parser("sf_medium", &data->t_resel_utra_sf.sf_medium)); + t_resel_utra_sf.add_field(make_asn1_enum_number_str_parser("sf_high", &data->t_resel_utra_sf.sf_high)); + + // carrierFreqListUTRA-FDD + parser::section carrier_freq_list_utra_fdd("carrier_freq_list_utra_fdd"); + sib6.add_subsection(&carrier_freq_list_utra_fdd); + bool dummy_bool = false; + carrier_freq_list_utra_fdd.set_optional(&dummy_bool); + carrier_freq_list_utra_fdd.add_field(new field_carrier_freq_list_utra_fdd(data)); + + // carrierFreqListUTRA-TDD + parser::section carrier_freq_list_utra_tdd("carrier_freq_list_utra_tdd"); + sib6.add_subsection(&carrier_freq_list_utra_tdd); + carrier_freq_list_utra_tdd.set_optional(&dummy_bool); + carrier_freq_list_utra_tdd.add_field(new field_carrier_freq_list_utra_tdd(data)); + + return parser::parse_section(std::move(filename), &sib6); +} + int parse_sib7(std::string filename, sib_type7_s* data) { parser::section sib7("sib7"); sib7.add_field(new parser::field("t_resel_geran", &data->t_resel_geran)); - // TODO: t_resel_geran_sf + + parser::section t_resel_geran_sf("t_resel_geran_sf"); + sib7.add_subsection(&t_resel_geran_sf); + t_resel_geran_sf.set_optional(&data->t_resel_geran_sf_present); + + t_resel_geran_sf.add_field(make_asn1_enum_number_str_parser("sf_medium", &data->t_resel_geran_sf.sf_medium)); + t_resel_geran_sf.add_field(make_asn1_enum_number_str_parser("sf_high", &data->t_resel_geran_sf.sf_high)); data->carrier_freqs_info_list_present = true; parser::section geran_neigh("carrier_freqs_info_list"); @@ -2317,6 +2458,7 @@ int parse_sibs(all_args_t* args_, rrc_cfg_t* rrc_cfg_, srsenb::phy_cfg_t* phy_co sib_type2_s* sib2 = &rrc_cfg_->sibs[1].set_sib2(); sib_type3_s* sib3 = &rrc_cfg_->sibs[2].set_sib3(); sib_type4_s* sib4 = &rrc_cfg_->sibs[3].set_sib4(); + sib_type6_s* sib6 = &rrc_cfg_->sibs[5].set_sib6(); sib_type7_s* sib7 = &rrc_cfg_->sibs[6].set_sib7(); sib_type9_s* sib9 = &rrc_cfg_->sibs[8].set_sib9(); sib_type13_r9_s* sib13 = &rrc_cfg_->sibs[12].set_sib13_v920(); @@ -2386,6 +2528,13 @@ int parse_sibs(all_args_t* args_, rrc_cfg_t* rrc_cfg_, srsenb::phy_cfg_t* phy_co } } + // Generate SIB6 if defined in mapping info + if (sib_is_present(sib1->sched_info_list, sib_type_e::sib_type6)) { + if (sib_sections::parse_sib6(args_->enb_files.sib_config, sib6) != SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + } + // Generate SIB7 if defined in mapping info if (sib_is_present(sib1->sched_info_list, sib_type_e::sib_type7)) { if (sib_sections::parse_sib7(args_->enb_files.sib_config, sib7) != SRSRAN_SUCCESS) { diff --git a/srsenb/src/enb_cfg_parser.h b/srsenb/src/enb_cfg_parser.h index c3755bcfb..0e5d1eefd 100644 --- a/srsenb/src/enb_cfg_parser.h +++ b/srsenb/src/enb_cfg_parser.h @@ -63,6 +63,7 @@ int parse_sib1(std::string filename, asn1::rrc::sib_type1_s* data); int parse_sib2(std::string filename, asn1::rrc::sib_type2_s* data); int parse_sib3(std::string filename, asn1::rrc::sib_type3_s* data); int parse_sib4(std::string filename, asn1::rrc::sib_type4_s* data); +int parse_sib6(std::string filename, asn1::rrc::sib_type6_s* data); int parse_sib7(std::string filename, asn1::rrc::sib_type7_s* data); int parse_sib9(std::string filename, asn1::rrc::sib_type9_s* data); int parse_sib13(std::string filename, asn1::rrc::sib_type13_r9_s* data); @@ -149,6 +150,28 @@ private: asn1::rrc::sib_type4_s* data; }; +class field_carrier_freq_list_utra_fdd final : public parser::field_itf +{ +public: + explicit field_carrier_freq_list_utra_fdd(asn1::rrc::sib_type6_s* data_) { data = data_; } + int parse(Setting& root) override; + const char* get_name() override { return "carrier_freq_list_utra_fdd"; } + +private: + asn1::rrc::sib_type6_s* data; +}; + +class field_carrier_freq_list_utra_tdd final : public parser::field_itf +{ +public: + explicit field_carrier_freq_list_utra_tdd(asn1::rrc::sib_type6_s* data_) { data = data_; } + int parse(Setting& root) override; + const char* get_name() override { return "carrier_freq_list_utra_tdd"; } + +private: + asn1::rrc::sib_type6_s* data; +}; + class field_carrier_freqs_info_list final : public parser::field_itf { public: diff --git a/srsenb/src/phy/phy.cc b/srsenb/src/phy/phy.cc index ad5aea3ce..cc52b78ef 100644 --- a/srsenb/src/phy/phy.cc +++ b/srsenb/src/phy/phy.cc @@ -358,7 +358,9 @@ void phy::configure_mbsfn(srsran::sib2_mbms_t* sib2, srsran::sib13_t* sib13, con // Start GUI void phy::start_plot() { - lte_workers[0]->start_plot(); + if (lte_workers.get_nof_workers() > 0) { + lte_workers[0]->start_plot(); + } } int phy::init_nr(const phy_args_t& args, const phy_cfg_t& cfg, stack_interface_phy_nr& stack) diff --git a/srsepc/epc.conf.example b/srsepc/epc.conf.example index 73183a63f..e0aa15393 100644 --- a/srsepc/epc.conf.example +++ b/srsepc/epc.conf.example @@ -21,6 +21,7 @@ # (supported: EIA0 (rejected by most UEs), EIA1 (default), EIA2, EIA3 # paging_timer: Value of paging timer in seconds (T3413) # request_imeisv: Request UE's IMEI-SV in security mode command +# lac: 16-bit Location Area Code. # ##################################################################### [mme] @@ -36,6 +37,7 @@ encryption_algo = EEA0 integrity_algo = EIA1 paging_timer = 2 request_imeisv = false +lac = 0x0006 ##################################################################### # HSS configuration diff --git a/srsepc/hdr/mme/nas.h b/srsepc/hdr/mme/nas.h index 9b0727561..79f137bb8 100644 --- a/srsepc/hdr/mme/nas.h +++ b/srsepc/hdr/mme/nas.h @@ -142,6 +142,7 @@ typedef struct { srsran::CIPHERING_ALGORITHM_ID_ENUM cipher_algo; srsran::INTEGRITY_ALGORITHM_ID_ENUM integ_algo; bool request_imeisv; + uint16_t lac; } nas_init_t; typedef struct { @@ -280,6 +281,7 @@ private: std::string m_full_net_name; std::string m_short_net_name; bool m_request_imeisv = false; + uint16_t m_lac = 0; // Timers timeout values uint16_t m_t3413 = 0; diff --git a/srsepc/hdr/mme/s1ap_common.h b/srsepc/hdr/mme/s1ap_common.h index e2161f5c5..9fa8c736f 100644 --- a/srsepc/hdr/mme/s1ap_common.h +++ b/srsepc/hdr/mme/s1ap_common.h @@ -52,6 +52,7 @@ typedef struct { srsran::CIPHERING_ALGORITHM_ID_ENUM encryption_algo; srsran::INTEGRITY_ALGORITHM_ID_ENUM integrity_algo; bool request_imeisv; + uint16_t lac; } s1ap_args_t; typedef struct { diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index 95c61db2f..88bac0665 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -97,6 +97,7 @@ void parse_args(all_args_t* args, int argc, char* argv[]) string hss_db_file; string hss_auth_algo; string log_filename; + string lac; // Command line only options bpo::options_description general("General options"); @@ -124,6 +125,7 @@ void parse_args(all_args_t* args, int argc, char* argv[]) ("mme.integrity_algo", bpo::value(&integrity_algo)->default_value("EIA1"), "Set preferred integrity protection algorithm for NAS") ("mme.paging_timer", bpo::value(&paging_timer)->default_value(2), "Set paging timer value in seconds (T3413)") ("mme.request_imeisv", bpo::value(&request_imeisv)->default_value(false), "Enable IMEISV request in Security mode command") + ("mme.lac", bpo::value(&lac)->default_value("0x01"), "Location Area Code") ("hss.db_file", bpo::value(&hss_db_file)->default_value("ue_db.csv"), ".csv file that stores UE's keys") ("spgw.gtpu_bind_addr", bpo::value(&spgw_bind_addr)->default_value("127.0.0.1"), "IP address of SP-GW for the S1-U connection") ("spgw.sgi_if_addr", bpo::value(&sgi_if_addr)->default_value("176.16.0.1"), "IP address of TUN interface for the SGi connection") @@ -227,6 +229,11 @@ void parse_args(all_args_t* args, int argc, char* argv[]) sstr << std::hex << vm["mme.tac"].as(); sstr >> args->mme_args.s1ap_args.tac; } + { + std::stringstream sstr; + sstr << std::hex << vm["mme.lac"].as(); + sstr >> args->mme_args.s1ap_args.lac; + } // Convert MCC/MNC strings if (!srsran::string_to_mcc(mcc, &args->mme_args.s1ap_args.mcc)) { diff --git a/srsepc/src/mme/nas.cc b/srsepc/src/mme/nas.cc index 6c8206398..1b01060e2 100644 --- a/srsepc/src/mme/nas.cc +++ b/srsepc/src/mme/nas.cc @@ -46,7 +46,8 @@ nas::nas(const nas_init_t& args, const nas_if_t& itf) : m_full_net_name(args.full_net_name), m_short_net_name(args.short_net_name), m_t3413(args.paging_timer), - m_request_imeisv(args.request_imeisv) + m_request_imeisv(args.request_imeisv), + m_lac(args.lac) { m_sec_ctx.integ_algo = args.integ_algo; m_sec_ctx.cipher_algo = args.cipher_algo; @@ -1550,7 +1551,7 @@ bool nas::pack_attach_accept(srsran::byte_buffer_t* nas_buffer) attach_accept.lai_present = true; attach_accept.lai.mcc = mcc; attach_accept.lai.mnc = mnc; - attach_accept.lai.lac = 001; + attach_accept.lai.lac = m_lac; attach_accept.ms_id_present = true; attach_accept.ms_id.type_of_id = LIBLTE_MME_MOBILE_ID_TYPE_TMSI; diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index e17ea9942..63e1824f1 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -81,6 +81,7 @@ void s1ap_nas_transport::init() m_nas_init.integ_algo = m_s1ap->m_s1ap_args.integrity_algo; m_nas_init.cipher_algo = m_s1ap->m_s1ap_args.encryption_algo; m_nas_init.request_imeisv = m_s1ap->m_s1ap_args.request_imeisv; + m_nas_init.lac = m_s1ap->m_s1ap_args.lac; // Init NAS interface m_nas_if.s1ap = s1ap::get_instance(); diff --git a/srsepc/srsepc_if_masq.sh b/srsepc/srsepc_if_masq.sh index 1f71f6966..00c609d25 100755 --- a/srsepc/srsepc_if_masq.sh +++ b/srsepc/srsepc_if_masq.sh @@ -26,7 +26,7 @@ sudo -v || exit #Check if outbound interface was specified if [ ! $# -eq 1 ] then - echo "Usage :'sudo ./if_masq.sh ' " + echo "Usage :'sudo ./srsepc_if_masq.sh ' " exit fi diff --git a/srsue/hdr/stack/ue_stack_lte.h b/srsue/hdr/stack/ue_stack_lte.h index 4c754dd59..553583d56 100644 --- a/srsue/hdr/stack/ue_stack_lte.h +++ b/srsue/hdr/stack/ue_stack_lte.h @@ -224,6 +224,7 @@ private: srslog::basic_logger& rrc_logger; srslog::basic_logger& usim_logger; srslog::basic_logger& nas_logger; + srslog::basic_logger& nas5g_logger; // UE NR stack logging srslog::basic_logger& mac_nr_logger; diff --git a/srsue/src/stack/ue_stack_lte.cc b/srsue/src/stack/ue_stack_lte.cc index 54cd2a58a..db2415b82 100644 --- a/srsue/src/stack/ue_stack_lte.cc +++ b/srsue/src/stack/ue_stack_lte.cc @@ -42,6 +42,7 @@ ue_stack_lte::ue_stack_lte() : rrc_logger(srslog::fetch_basic_logger("RRC", false)), usim_logger(srslog::fetch_basic_logger("USIM", false)), nas_logger(srslog::fetch_basic_logger("NAS", false)), + nas5g_logger(srslog::fetch_basic_logger("NAS5G", false)), mac_nr_logger(srslog::fetch_basic_logger("MAC-NR")), rrc_nr_logger(srslog::fetch_basic_logger("RRC-NR", false)), rlc_nr_logger(srslog::fetch_basic_logger("RLC-NR", false)), @@ -128,6 +129,8 @@ int ue_stack_lte::init(const stack_args_t& args_) nas_logger.set_level(srslog::str_to_basic_level(args.log.nas_level)); nas_logger.set_hex_dump_max_size(args.log.nas_hex_limit); + nas5g_logger.set_level(srslog::str_to_basic_level(args.log.nas_level)); + nas5g_logger.set_hex_dump_max_size(args.log.nas_hex_limit); mac_nr_logger.set_level(srslog::str_to_basic_level(args.log.mac_level)); mac_nr_logger.set_hex_dump_max_size(args.log.mac_hex_limit); rrc_nr_logger.set_level(srslog::str_to_basic_level(args.log.rrc_level)); @@ -201,6 +204,7 @@ int ue_stack_lte::init(const stack_args_t& args_) if (args.pkt_trace.nas_pcap.enable) { if (nas_pcap.open(args.pkt_trace.nas_pcap.filename.c_str()) == SRSRAN_SUCCESS) { nas.start_pcap(&nas_pcap); + nas_5g.start_pcap(&nas_pcap); stack_logger.info("Open nas pcap file %s", args.pkt_trace.nas_pcap.filename.c_str()); } else { stack_logger.error("Can not open pcap file %s", args.pkt_trace.nas_pcap.filename.c_str());