diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 3124d496d4..f29110e012 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -335,6 +335,11 @@ else (CUDA_FOUND) ) endif () +if (SANITIZE_ADDRESS) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") +endif () + add_definitions("-DASN_DISABLE_OER_SUPPORT") ######################### diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index dba6d7da6d..8748e8d807 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -68,6 +68,7 @@ USRP_REC_PLAY="False" BUILD_ECLIPSE=0 NR="False" ITTI_SIM="False" +SANITIZE_ADDRESS="False" OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope msc" trap handle_ctrl_c INT @@ -424,6 +425,9 @@ function main() { CMAKE_CMD="$CMAKE_CMD -GNinja" MAKE_CMD=ninja shift;; + --sanitize-address | -fsanitize=address) + SANITIZE_ADDRESS=True + shift;; --ittiSIM) ittiSIM=1 ITTI_SIM="True" @@ -612,6 +616,7 @@ function main() { echo "set ( USRP_REC_PLAY $USRP_REC_PLAY )" >> $cmake_file echo "set ( SKIP_SHARED_LIB_FLAG $SKIP_SHARED_LIB_FLAG )" >> $cmake_file echo "set ( ITTI_SIM $ITTI_SIM )" >> $cmake_file + echo "set ( SANITIZE_ADDRESS $SANITIZE_ADDRESS )" >> $cmake_file echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file cd $DIR/$build_dir/build eval $CMAKE_CMD diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c index 1d4efc1e26..000c764e8f 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c @@ -650,7 +650,7 @@ control: control_decoder = decoder; control_e1 = e1; while (control_e1) { - nr_rlc_pdu_decoder_get_bits(&control_decoder, entity->sn_field_length); R(control_decoder); /* NACK_SN */ + nack_sn = nr_rlc_pdu_decoder_get_bits(&control_decoder, entity->sn_field_length); R(control_decoder); control_e1 = nr_rlc_pdu_decoder_get_bits(&control_decoder, 1); R(control_decoder); control_e2 = nr_rlc_pdu_decoder_get_bits(&control_decoder, 1); R(control_decoder); control_e3 = nr_rlc_pdu_decoder_get_bits(&control_decoder, 1); R(control_decoder); @@ -660,17 +660,36 @@ control: } else { nr_rlc_pdu_decoder_get_bits(&control_decoder, 1); R(control_decoder); } + /* check range and so_start/so_end consistency */ if (control_e2) { - nr_rlc_pdu_decoder_get_bits(&control_decoder, 16); R(control_decoder); /* SOstart */ - nr_rlc_pdu_decoder_get_bits(&control_decoder, 16); R(control_decoder); /* SOend */ + so_start = nr_rlc_pdu_decoder_get_bits(&control_decoder, 16); R(control_decoder); + so_end = nr_rlc_pdu_decoder_get_bits(&control_decoder, 16); R(control_decoder); + } else { + so_start = 0; + so_end = 0xffff; } if (control_e3) { - nr_rlc_pdu_decoder_get_bits(&control_decoder, 8); R(control_decoder); /* NACK range */ + range = nr_rlc_pdu_decoder_get_bits(&control_decoder, 8); R(control_decoder); + } else { + range = 1; + } + if (range < 1) { + LOG_E(RLC, "%s:%d:%s: error, bad 'range' in RLC NACK (sn %d)\n", + __FILE__, __LINE__, __FUNCTION__, nack_sn); + goto err; + } + /* so_start can be > so_end if more than one range; they don't refer + * to the same PDU then + */ + if (range == 1 && so_end < so_start) { + LOG_E(RLC, "%s:%d:%s: error, bad so start/end (sn %d)\n", + __FILE__, __LINE__, __FUNCTION__, nack_sn); + goto err; } } /* 38.322 5.3.3.3 says to stop t_poll_retransmit if a ACK or NACK is - * received for the SN 'poll_sn' + * received for the SN 'poll_sn' - check ACK case (NACK done below) */ if (sn_compare_tx(entity, entity->poll_sn, ack_sn) < 0) entity->t_poll_retransmit_start = 0; @@ -697,28 +716,22 @@ control: if (e2) { so_start = nr_rlc_pdu_decoder_get_bits(&decoder, 16); R(decoder); so_end = nr_rlc_pdu_decoder_get_bits(&decoder, 16); R(decoder); - if (so_end < so_start) { - LOG_W(RLC, "%s:%d:%s: warning, bad so start/end, NACK the whole PDU (sn %d)\n", - __FILE__, __LINE__, __FUNCTION__, nack_sn); - so_start = 0; - so_end = -1; - } - /* special value 0xffff indicates 'all bytes to the end' */ - if (so_end == 0xffff) - so_end = -1; } else { so_start = 0; - so_end = -1; + so_end = 0xffff; } if (e3) { range = nr_rlc_pdu_decoder_get_bits(&decoder, 8); R(decoder); } else { range = 1; } + /* special value 0xffff indicates 'all bytes to the end' */ + if (so_end == 0xffff) + so_end = -1; process_received_nack(entity, nack_sn, so_start, so_end, range, sn_set); /* 38.322 5.3.3.3 says to stop t_poll_retransmit if a ACK or NACK is - * received for the SN 'poll_sn' + * received for the SN 'poll_sn' - check NACK case (ACK done above) */ if (sn_compare_tx(entity, nack_sn, entity->poll_sn) <= 0 && sn_compare_tx(entity, entity->poll_sn, (nack_sn + range) % entity->sn_modulus) < 0) diff --git a/openair2/LAYER2/nr_rlc/tests/run_tests.sh b/openair2/LAYER2/nr_rlc/tests/run_tests.sh index bf1b343d7e..a98f6b5d0f 100755 --- a/openair2/LAYER2/nr_rlc/tests/run_tests.sh +++ b/openair2/LAYER2/nr_rlc/tests/run_tests.sh @@ -1,6 +1,6 @@ #!/bin/sh -test_count=14 +test_count=15 for i in `seq $test_count` do diff --git a/openair2/LAYER2/nr_rlc/tests/test15.h b/openair2/LAYER2/nr_rlc/tests/test15.h new file mode 100644 index 0000000000..8ce9f97896 --- /dev/null +++ b/openair2/LAYER2/nr_rlc/tests/test15.h @@ -0,0 +1,19 @@ +/* + * am test (SN field size 18): + * test "range" in NACK, generate a case where so_start > so_end + * (so so_start and so_end are not from the same PDU) + */ + +TIME, 1, + GNB_AM, 100000, 100000, 45, 35, 0, -1, -1, 8, 18, + UE_AM, 100000, 100000, 45, 35, 0, -1, -1, 8, 18, + GNB_PDU_SIZE, 40, + UE_PDU_SIZE, 80, + GNB_SDU, 0, 50, + GNB_SDU, 1, 50, + GNB_SDU, 2, 50, +TIME, 2, + UE_RECV_FAILS, 1, +TIME, 4, + UE_RECV_FAILS, 0, +TIME, -1 diff --git a/openair2/LAYER2/nr_rlc/tests/test15.txt.gz b/openair2/LAYER2/nr_rlc/tests/test15.txt.gz new file mode 100644 index 0000000000..e615a59a5f Binary files /dev/null and b/openair2/LAYER2/nr_rlc/tests/test15.txt.gz differ diff --git a/openair2/RRC/LTE/rrc_defs.h b/openair2/RRC/LTE/rrc_defs.h index c19335910b..6615541662 100644 --- a/openair2/RRC/LTE/rrc_defs.h +++ b/openair2/RRC/LTE/rrc_defs.h @@ -67,6 +67,8 @@ #define MAX_NUM_NEIGH_CELLs 6 /* maximum neighbouring cells number */ +#define MAX_NUM_GNB_CELLs 1 /* maximum gNB cells number */ + #define UE_STATE_NOTIFICATION_INTERVAL 50 #define IPV4_ADDR "%u.%u.%u.%u" @@ -804,8 +806,13 @@ typedef struct eNB_RRC_INST_s { int num_neigh_cells_cc[MAX_NUM_CCs]; uint32_t neigh_cells_id[MAX_NUM_NEIGH_CELLs][MAX_NUM_CCs]; + // gNB cells connected to this eNB + int num_gnb_cells; + int num_gnb_cells_cc[MAX_NUM_GNB_CELLs]; + uint32_t gnb_cells_id[MAX_NUM_GNB_CELLs][MAX_NUM_CCs]; + // Nr scc freq band and SSB absolute frequency - uint32_t nr_neigh_freq_band[MAX_NUM_NEIGH_CELLs][MAX_NUM_CCs]; + uint32_t nr_gnb_freq_band[MAX_NUM_GNB_CELLs][MAX_NUM_CCs]; int nr_scg_ssb_freq; // other RAN parameters diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index b30422ce2f..c3e67b86b3 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -1283,7 +1283,7 @@ rrc_eNB_generate_UECapabilityEnquiry( T(T_ENB_RRC_UE_CAPABILITY_ENQUIRY, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); int16_t eutra_band = RC.rrc[ctxt_pP->module_id]->configuration.eutra_band[0]; - uint32_t nr_band = RC.rrc[ctxt_pP->module_id]->nr_neigh_freq_band[0][0]; + uint32_t nr_band = RC.rrc[ctxt_pP->module_id]->nr_gnb_freq_band[0][0]; size = do_UECapabilityEnquiry( ctxt_pP, buffer, @@ -1333,7 +1333,7 @@ rrc_eNB_generate_NR_UECapabilityEnquiry( T(T_ENB_RRC_UE_CAPABILITY_ENQUIRY, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); int16_t eutra_band = RC.rrc[ctxt_pP->module_id]->configuration.eutra_band[0]; - uint32_t nr_band = RC.rrc[ctxt_pP->module_id]->nr_neigh_freq_band[0][0]; + uint32_t nr_band = RC.rrc[ctxt_pP->module_id]->nr_gnb_freq_band[0][0]; size = do_NR_UECapabilityEnquiry( ctxt_pP, buffer, @@ -7587,8 +7587,8 @@ is_en_dc_supported( ) //----------------------------------------------------------------------------- { - /* to be refined - check that the eNB is connected to a gNB, check that - * the bands supported by the UE include the band of the gNB + /* to be refined - check that the bands supported by the UE include + * the band of the gNB */ #define NCE nonCriticalExtension return c != NULL @@ -8288,8 +8288,13 @@ rrc_eNB_decode_dcch( ue_context_p->ue_context.UE_Capability = 0; } - if (dec_rval.code == RC_OK) - ue_context_p->ue_context.does_nr = is_en_dc_supported(ue_context_p->ue_context.UE_Capability); + if (dec_rval.code == RC_OK) { + /* do NR only if at least one gNB connected */ + if (RC.rrc[ctxt_pP->module_id]->num_gnb_cells != 0) + ue_context_p->ue_context.does_nr = is_en_dc_supported(ue_context_p->ue_context.UE_Capability); + else + ue_context_p->ue_context.does_nr = 0; + } if (EPC_MODE_ENABLED) { rrc_eNB_send_S1AP_UE_CAPABILITIES_IND(ctxt_pP, @@ -9028,22 +9033,22 @@ void rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id) { } void rrc_eNB_process_ENDC_x2_setup_request(int mod_id, x2ap_ENDC_setup_req_t *m) { - if (RC.rrc[mod_id]->num_neigh_cells > MAX_NUM_NEIGH_CELLs) { - LOG_E(RRC, "Error: number of neighbouring cells is exceeded \n"); + if (RC.rrc[mod_id]->num_gnb_cells >= MAX_NUM_GNB_CELLs) { + LOG_E(RRC, "Error: number of gNB cells is exceeded\n"); return; } if (m->num_cc > MAX_NUM_CCs) { - LOG_E(RRC, "Error: number of neighbouring cells carriers is exceeded \n"); + LOG_E(RRC, "Error: number of gNB cells carriers is exceeded \n"); return; } - RC.rrc[mod_id]->num_neigh_cells++; - RC.rrc[mod_id]->num_neigh_cells_cc[RC.rrc[mod_id]->num_neigh_cells-1] = m->num_cc; + RC.rrc[mod_id]->num_gnb_cells++; + RC.rrc[mod_id]->num_gnb_cells_cc[RC.rrc[mod_id]->num_gnb_cells-1] = m->num_cc; for (int i=0; inum_cc; i++) { - RC.rrc[mod_id]->neigh_cells_id[RC.rrc[mod_id]->num_neigh_cells-1][i] = m->Nid_cell[i]; - RC.rrc[mod_id]->nr_neigh_freq_band[RC.rrc[mod_id]->num_neigh_cells-1][i] = m->servedNrCell_band[i]; + RC.rrc[mod_id]->gnb_cells_id[RC.rrc[mod_id]->num_gnb_cells-1][i] = m->Nid_cell[i]; + RC.rrc[mod_id]->nr_gnb_freq_band[RC.rrc[mod_id]->num_gnb_cells-1][i] = m->servedNrCell_band[i]; } } diff --git a/openair2/X2AP/x2ap_eNB.c b/openair2/X2AP/x2ap_eNB.c index 58535646fd..321190015d 100644 --- a/openair2/X2AP/x2ap_eNB.c +++ b/openair2/X2AP/x2ap_eNB.c @@ -116,9 +116,7 @@ void x2ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa /* some sanity check - to be refined at some point */ if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) { X2AP_ERROR("x2ap_enb_data_p not NULL and sctp state not SCTP_STATE_ESTABLISHED, what to do?\n"); - // Allow for a gracious exit when we kill first the gNB, then the eNB - //abort(); - return; + exit(1); } x2ap_enb_data_p->in_streams = sctp_new_association_resp->in_streams; diff --git a/openair2/X2AP/x2ap_eNB_handler.c b/openair2/X2AP/x2ap_eNB_handler.c index 1fb28ea05b..d60f7654ad 100644 --- a/openair2/X2AP/x2ap_eNB_handler.c +++ b/openair2/X2AP/x2ap_eNB_handler.c @@ -690,9 +690,11 @@ int x2ap_eNB_handle_x2_setup_failure(instance_t instance, // need a FSM to handle all cases if ((ie->value.choice.Cause.present == X2AP_Cause_PR_misc) && (ie->value.choice.Cause.choice.misc == X2AP_CauseMisc_unspecified)) { - X2AP_WARN("Received X2 setup failure for eNB ... eNB is not ready\n"); + X2AP_ERROR("Received X2 setup failure for eNB ... eNB is not ready\n"); + exit(1); } else { X2AP_ERROR("Received x2 setup failure for eNB... please check your parameters\n"); + exit(1); } x2ap_eNB_data->state = X2AP_ENB_STATE_WAITING;