Integration 2021 wk14 a
MR !1111 : fix x2 without gnb -fix x2 without gnb (that is: the eNB is running without gNB, then we must not switch the UE to NR) -exit gNB if eNB crashes (and exit eNB if gNB crashes) MR !1102 : nr rlc: bugfix: fix NACK with range We do some sanity checks for incoming rlc control packets. One of them is to check that so_start is not > so_end when present. But when 'range' is present and bigger than 1 it means that so_start refers to one PDU and so_end to another one. So we may well have so_start > so_end. This MR fixes that and reorganizes a bit the code to do the check before processing and rejecting the PDU if the values are not correct. (Before this commit we were NACKing the whole PDUs if so_start > so_end.) MR !1096 : build_oai: Add --sanitize-address option -pass the -fsanitize=address option to the compiler which enables run-time checks for some kinds of memory mismanagement
This commit is contained in:
@@ -333,6 +333,11 @@ else (CUDA_FOUND)
|
|||||||
)
|
)
|
||||||
endif ()
|
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")
|
add_definitions("-DASN_DISABLE_OER_SUPPORT")
|
||||||
|
|
||||||
#########################
|
#########################
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ USRP_REC_PLAY="False"
|
|||||||
BUILD_ECLIPSE=0
|
BUILD_ECLIPSE=0
|
||||||
NR="False"
|
NR="False"
|
||||||
ITTI_SIM="False"
|
ITTI_SIM="False"
|
||||||
|
SANITIZE_ADDRESS="False"
|
||||||
OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope msc"
|
OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope msc"
|
||||||
trap handle_ctrl_c INT
|
trap handle_ctrl_c INT
|
||||||
|
|
||||||
@@ -424,6 +425,9 @@ function main() {
|
|||||||
CMAKE_CMD="$CMAKE_CMD -GNinja"
|
CMAKE_CMD="$CMAKE_CMD -GNinja"
|
||||||
MAKE_CMD=ninja
|
MAKE_CMD=ninja
|
||||||
shift;;
|
shift;;
|
||||||
|
--sanitize-address | -fsanitize=address)
|
||||||
|
SANITIZE_ADDRESS=True
|
||||||
|
shift;;
|
||||||
--ittiSIM)
|
--ittiSIM)
|
||||||
ittiSIM=1
|
ittiSIM=1
|
||||||
ITTI_SIM="True"
|
ITTI_SIM="True"
|
||||||
@@ -612,6 +616,7 @@ function main() {
|
|||||||
echo "set ( USRP_REC_PLAY $USRP_REC_PLAY )" >> $cmake_file
|
echo "set ( USRP_REC_PLAY $USRP_REC_PLAY )" >> $cmake_file
|
||||||
echo "set ( SKIP_SHARED_LIB_FLAG $SKIP_SHARED_LIB_FLAG )" >> $cmake_file
|
echo "set ( SKIP_SHARED_LIB_FLAG $SKIP_SHARED_LIB_FLAG )" >> $cmake_file
|
||||||
echo "set ( ITTI_SIM $ITTI_SIM )" >> $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
|
echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file
|
||||||
cd $DIR/$build_dir/build
|
cd $DIR/$build_dir/build
|
||||||
eval $CMAKE_CMD
|
eval $CMAKE_CMD
|
||||||
|
|||||||
@@ -650,7 +650,7 @@ control:
|
|||||||
control_decoder = decoder;
|
control_decoder = decoder;
|
||||||
control_e1 = e1;
|
control_e1 = e1;
|
||||||
while (control_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_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_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);
|
control_e3 = nr_rlc_pdu_decoder_get_bits(&control_decoder, 1); R(control_decoder);
|
||||||
@@ -660,17 +660,36 @@ control:
|
|||||||
} else {
|
} else {
|
||||||
nr_rlc_pdu_decoder_get_bits(&control_decoder, 1); R(control_decoder);
|
nr_rlc_pdu_decoder_get_bits(&control_decoder, 1); R(control_decoder);
|
||||||
}
|
}
|
||||||
|
/* check range and so_start/so_end consistency */
|
||||||
if (control_e2) {
|
if (control_e2) {
|
||||||
nr_rlc_pdu_decoder_get_bits(&control_decoder, 16); R(control_decoder); /* SOstart */
|
so_start = nr_rlc_pdu_decoder_get_bits(&control_decoder, 16); R(control_decoder);
|
||||||
nr_rlc_pdu_decoder_get_bits(&control_decoder, 16); R(control_decoder); /* SOend */
|
so_end = nr_rlc_pdu_decoder_get_bits(&control_decoder, 16); R(control_decoder);
|
||||||
|
} else {
|
||||||
|
so_start = 0;
|
||||||
|
so_end = 0xffff;
|
||||||
}
|
}
|
||||||
if (control_e3) {
|
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
|
/* 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)
|
if (sn_compare_tx(entity, entity->poll_sn, ack_sn) < 0)
|
||||||
entity->t_poll_retransmit_start = 0;
|
entity->t_poll_retransmit_start = 0;
|
||||||
@@ -697,28 +716,22 @@ control:
|
|||||||
if (e2) {
|
if (e2) {
|
||||||
so_start = nr_rlc_pdu_decoder_get_bits(&decoder, 16); R(decoder);
|
so_start = nr_rlc_pdu_decoder_get_bits(&decoder, 16); R(decoder);
|
||||||
so_end = 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 {
|
} else {
|
||||||
so_start = 0;
|
so_start = 0;
|
||||||
so_end = -1;
|
so_end = 0xffff;
|
||||||
}
|
}
|
||||||
if (e3) {
|
if (e3) {
|
||||||
range = nr_rlc_pdu_decoder_get_bits(&decoder, 8); R(decoder);
|
range = nr_rlc_pdu_decoder_get_bits(&decoder, 8); R(decoder);
|
||||||
} else {
|
} else {
|
||||||
range = 1;
|
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);
|
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
|
/* 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 &&
|
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)
|
sn_compare_tx(entity, entity->poll_sn, (nack_sn + range) % entity->sn_modulus) < 0)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
test_count=14
|
test_count=15
|
||||||
|
|
||||||
for i in `seq $test_count`
|
for i in `seq $test_count`
|
||||||
do
|
do
|
||||||
|
|||||||
@@ -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
|
||||||
Binary file not shown.
@@ -67,6 +67,8 @@
|
|||||||
|
|
||||||
#define MAX_NUM_NEIGH_CELLs 6 /* maximum neighbouring cells number */
|
#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 UE_STATE_NOTIFICATION_INTERVAL 50
|
||||||
|
|
||||||
#define IPV4_ADDR "%u.%u.%u.%u"
|
#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];
|
int num_neigh_cells_cc[MAX_NUM_CCs];
|
||||||
uint32_t neigh_cells_id[MAX_NUM_NEIGH_CELLs][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
|
// 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;
|
int nr_scg_ssb_freq;
|
||||||
|
|
||||||
// other RAN parameters
|
// other RAN parameters
|
||||||
|
|||||||
+18
-13
@@ -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(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));
|
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||||
int16_t eutra_band = RC.rrc[ctxt_pP->module_id]->configuration.eutra_band[0];
|
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(
|
size = do_UECapabilityEnquiry(
|
||||||
ctxt_pP,
|
ctxt_pP,
|
||||||
buffer,
|
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(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));
|
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||||
int16_t eutra_band = RC.rrc[ctxt_pP->module_id]->configuration.eutra_band[0];
|
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(
|
size = do_NR_UECapabilityEnquiry(
|
||||||
ctxt_pP,
|
ctxt_pP,
|
||||||
buffer,
|
buffer,
|
||||||
@@ -7588,8 +7588,8 @@ is_en_dc_supported(
|
|||||||
)
|
)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
{
|
{
|
||||||
/* to be refined - check that the eNB is connected to a gNB, check that
|
/* to be refined - check that the bands supported by the UE include
|
||||||
* the bands supported by the UE include the band of the gNB
|
* the band of the gNB
|
||||||
*/
|
*/
|
||||||
#define NCE nonCriticalExtension
|
#define NCE nonCriticalExtension
|
||||||
return c != NULL
|
return c != NULL
|
||||||
@@ -8289,8 +8289,13 @@ rrc_eNB_decode_dcch(
|
|||||||
ue_context_p->ue_context.UE_Capability = 0;
|
ue_context_p->ue_context.UE_Capability = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dec_rval.code == RC_OK)
|
if (dec_rval.code == RC_OK) {
|
||||||
ue_context_p->ue_context.does_nr = is_en_dc_supported(ue_context_p->ue_context.UE_Capability);
|
/* 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) {
|
if (EPC_MODE_ENABLED) {
|
||||||
rrc_eNB_send_S1AP_UE_CAPABILITIES_IND(ctxt_pP,
|
rrc_eNB_send_S1AP_UE_CAPABILITIES_IND(ctxt_pP,
|
||||||
@@ -9029,22 +9034,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) {
|
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) {
|
if (RC.rrc[mod_id]->num_gnb_cells >= MAX_NUM_GNB_CELLs) {
|
||||||
LOG_E(RRC, "Error: number of neighbouring cells is exceeded \n");
|
LOG_E(RRC, "Error: number of gNB cells is exceeded\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m->num_cc > MAX_NUM_CCs) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RC.rrc[mod_id]->num_neigh_cells++;
|
RC.rrc[mod_id]->num_gnb_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_cc[RC.rrc[mod_id]->num_gnb_cells-1] = m->num_cc;
|
||||||
|
|
||||||
for (int i=0; i<m->num_cc; i++) {
|
for (int i=0; i<m->num_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]->gnb_cells_id[RC.rrc[mod_id]->num_gnb_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]->nr_gnb_freq_band[RC.rrc[mod_id]->num_gnb_cells-1][i] = m->servedNrCell_band[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 */
|
/* some sanity check - to be refined at some point */
|
||||||
if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
|
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");
|
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
|
exit(1);
|
||||||
//abort();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
x2ap_enb_data_p->in_streams = sctp_new_association_resp->in_streams;
|
x2ap_enb_data_p->in_streams = sctp_new_association_resp->in_streams;
|
||||||
|
|||||||
@@ -690,9 +690,11 @@ int x2ap_eNB_handle_x2_setup_failure(instance_t instance,
|
|||||||
// need a FSM to handle all cases
|
// need a FSM to handle all cases
|
||||||
if ((ie->value.choice.Cause.present == X2AP_Cause_PR_misc) &&
|
if ((ie->value.choice.Cause.present == X2AP_Cause_PR_misc) &&
|
||||||
(ie->value.choice.Cause.choice.misc == X2AP_CauseMisc_unspecified)) {
|
(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 {
|
} else {
|
||||||
X2AP_ERROR("Received x2 setup failure for eNB... please check your parameters\n");
|
X2AP_ERROR("Received x2 setup failure for eNB... please check your parameters\n");
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
x2ap_eNB_data->state = X2AP_ENB_STATE_WAITING;
|
x2ap_eNB_data->state = X2AP_ENB_STATE_WAITING;
|
||||||
|
|||||||
Reference in New Issue
Block a user