Newer
Older
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file rrc_gNB.c
* \brief rrc procedures for gNB
* \author Navid Nikaein and Raymond Knopp , WEI-TAI CHEN
* \date 2011 - 2014 , 2018
* \version 1.0
* \company Eurecom
* \email: navid.nikaein@eurecom.fr and raymond.knopp@eurecom.fr
*/
#include "nr_rrc_defs.h"
#include "nr_rrc_extern.h"
#include "assertions.h"
#include "common/ran_context.h"
#include "asn1_conversions.h"
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
#include "LAYER2/RLC/rlc.h"
#include "LAYER2/NR_MAC_gNB/mac_proto.h"
#include "UTIL/LOG/log.h"
#include "COMMON/mac_rrc_primitives.h"
#include "RRC/NR/MESSAGES/asn1_msg.h"
#include "NR_BCCH-BCH-Message.h"
#include "NR_UL-DCCH-Message.h"
#include "NR_DL-DCCH-Message.h"
#include "NR_MeasResults.h"
#include "rlc.h"
#include "rrc_eNB_UE_context.h"
#include "platform_types.h"
#include "msc.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
//#if defined(Rel10) || defined(Rel14)
#include "MeasResults.h"
//#endif
#include "RRC/NAS/nas_config.h"
#include "RRC/NAS/rb_config.h"
#include "OCG.h"
#include "OCG_extern.h"
#if defined(ENABLE_SECURITY)
# include "UTIL/OSA/osa_defs.h"
#endif
#if defined(ENABLE_USE_MME)
# include "rrc_eNB_S1AP.h"
# include "rrc_eNB_GTPV1U.h"
# if defined(ENABLE_ITTI)
# else
# include "../../S1AP/s1ap_eNB.h"
# endif
#endif
#include "gtpv1u_eNB_task.h"
#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
#endif
#include "SIMULATION/TOOLS/sim.h" // for taus
extern RAN_CONTEXT_t RC;
#ifdef PHY_EMUL
extern EMULATION_VARS *Emul_vars;
#endif
//extern eNB_MAC_INST *eNB_mac_inst;
//extern UE_MAC_INST *UE_mac_inst;
#ifdef BIGPHYSAREA
extern void* bigphys_malloc(int);
#endif
extern uint16_t two_tier_hexagonal_cellIds[7];
///---------------------------------------------------------------------------------------------------------------///
///---------------------------------------------------------------------------------------------------------------///
const protocol_ctxt_t* const ctxt_pP
)
//-----------------------------------------------------------------------------
{
int CC_id;
LOG_I(NR_RRC, PROTOCOL_NR_RRC_CTXT_FMT" gNB:OPENAIR NR RRC IN....\n",
PROTOCOL_NR_RRC_CTXT_ARGS(ctxt_pP));
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
rrc_config_nr_buffer (&RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id].SI, BCCH, 1);
RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id].SI.Active = 1;
rrc_config_nr_buffer (&RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id].Srb0, CCCH, 1);
RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Active = 1;
///---------------------------------------------------------------------------------------------------------------///
///---------------------------------------------------------------------------------------------------------------///
static void
init_NR_SI(
const int CC_id
#if defined(ENABLE_ITTI)
,
gNB_RrcConfigurationReq * configuration
#endif
)
//-----------------------------------------------------------------------------
{
RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id].physCellId = configuration->Nid_cell[CC_id];
RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id].p_gNB = configuration->nb_antenna_ports[CC_id];
RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id].Ncp = configuration->DL_prefix_type[CC_id];
RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id].Ncp_UL = configuration->UL_prefix_type[CC_id];
RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id].dl_CarrierFreq = configuration->downlink_frequency[CC_id];
RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id].ul_CarrierFreq = configuration->downlink_frequency[CC_id]+ configuration->uplink_frequency_offset[CC_id];
RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id].sizeof_MIB = 0;
RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id].MIB = (uint8_t*) malloc16(4);
RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id].sizeof_MIB = do_MIB_NR(&RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id],0,
configuration->MIB_ssb_SubcarrierOffset[CC_id],
configuration->MIB_subCarrierSpacingCommon[CC_id],
configuration->MIB_dmrs_TypeA_Position[CC_id]
do_SERVINGCELLCONFIGCOMMON(ctxt_pP->module_id,
CC_id
#if defined(ENABLE_ITTI)
,configuration
#endif
);
rrc_mac_config_req_gNB(ctxt_pP->module_id,
CC_id,
RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id].p_gNB,
configuration->eutra_band[CC_id],
RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id].dl_CarrierFreq,
configuration->N_RB_DL[CC_id],
(NR_BCCH_BCH_Message_t *)&RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id].mib,
(NR_ServingCellConfigCommon_t *)&RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id].servingcellconfigcommon
);
char openair_rrc_gNB_configuration(const module_id_t gnb_mod_idP, gNB_RrcConfigurationReq* configuration){
protocol_ctxt_t ctxt;
int CC_id;
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, gnb_mod_idP, GNB_FLAG_YES, NOT_A_RNTI, 0, 0,gnb_mod_idP);
LOG_I(NR_RRC,
PROTOCOL_NR_RRC_CTXT_FMT" Init...\n",
PROTOCOL_NR_RRC_CTXT_ARGS(&ctxt));
while ( RC.nrrrc[gnb_mod_idP] == NULL ) {
LOG_E(NR_RRC, "RC.nrrrc not yet initialized, waiting 1 second\n");
AssertFatal(RC.nrrrc[gnb_mod_idP] != NULL, "RC.nrrrc not initialized!");
AssertFatal(NUMBER_OF_UE_MAX < (module_id_t)0xFFFFFFFFFFFFFFFF, " variable overflow");
#ifdef ENABLE_ITTI
AssertFatal(configuration!=NULL,"configuration input is null\n");
#endif
RC.nrrrc[ctxt.module_id]->Nb_ue = 0;
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
RC.nrrrc[ctxt.module_id]->carrier[CC_id].Srb0.Active = 0;
uid_linear_allocator_init(&RC.nrrrc[ctxt.module_id]->uid_allocator);
RB_INIT(&RC.nrrrc[ctxt.module_id]->rrc_ue_head);
RC.nrrrc[ctxt.module_id]->initial_id2_s1ap_ids = hashtable_create (NUMBER_OF_UE_MAX * 2, NULL, NULL);
RC.nrrrc[ctxt.module_id]->s1ap_id2_s1ap_ids = hashtable_create (NUMBER_OF_UE_MAX * 2, NULL, NULL);
memcpy(&RC.nrrrc[ctxt.module_id]->configuration,configuration,sizeof(gNB_RrcConfigurationReq));
LOG_I(NR_RRC, PROTOCOL_NR_RRC_CTXT_FMT" Checking release \n",PROTOCOL_NR_RRC_CTXT_ARGS(&ctxt));
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
for (j = 0; j < NUM_MAX_CBA_GROUP; j++) {
RC.nrrrc[ctxt.module_id]->carrier[CC_id].cba_rnti[j] = CBA_OFFSET + j;
if (RC.nrrrc[ctxt.module_id]->carrier[CC_id].num_active_cba_groups > NUM_MAX_CBA_GROUP) {
RC.nrrrc[ctxt.module_id]->carrier[CC_id].num_active_cba_groups = NUM_MAX_CBA_GROUP;
PROTOCOL_NR_RRC_CTXT_FMT" Initialization of 4 cba_RNTI values (%x %x %x %x) num active groups %d\n",
PROTOCOL_NR_RRC_CTXT_ARGS(&ctxt),
gnb_mod_idP, RC.nrrrc[ctxt.module_id]->carrier[CC_id].cba_rnti[0],
RC.nrrrc[ctxt.module_id]->carrier[CC_id].cba_rnti[1],
RC.nrrrc[ctxt.module_id]->carrier[CC_id].cba_rnti[2],
RC.nrrrc[ctxt.module_id]->carrier[CC_id].cba_rnti[3],
RC.nrrrc[ctxt.module_id]->carrier[CC_id].num_active_cba_groups);
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
init_NR_SI(&ctxt,
CC_id
#if defined(ENABLE_ITTI)
,configuration
#endif
);
}//END for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++)
openair_nr_rrc_on(&ctxt);
}//END openair_rrc_gNB_configuration
///---------------------------------------------------------------------------------------------------------------///
///---------------------------------------------------------------------------------------------------------------///
//SRB_INFO *srb_info_p;
//int CC_id;
//protocol_ctxt_t ctxt;
itti_mark_task_ready(TASK_RRC_GNB);
LOG_I(NR_RRC,"Entering main loop of NR_RRC message task\n");
// Wait for a message
itti_receive_msg(TASK_RRC_GNB, &msg_p);
msg_name_p = ITTI_MSG_NAME(msg_p);
instance = ITTI_MSG_INSTANCE(msg_p);
switch (ITTI_MSG_ID(msg_p)) {
case TERMINATE_MESSAGE:
LOG_I(RRC, "[gNB %d] Received %s\n", instance, msg_name_p);
break;
/* Messages from MAC */
/* Messages from PDCP */
// Messages from S1AP
rrc_eNB_process_S1AP_DOWNLINK_NAS(msg_p, msg_name_p, instance, &rrc_gNB_mui);
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
break;
case S1AP_INITIAL_CONTEXT_SETUP_REQ:
rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(msg_p, msg_name_p, instance);
break;
case S1AP_UE_CTXT_MODIFICATION_REQ:
rrc_eNB_process_S1AP_UE_CTXT_MODIFICATION_REQ(msg_p, msg_name_p, instance);
break;
case S1AP_PAGING_IND:
LOG_D(RRC, "[eNB %d] Received Paging message from S1AP: %s\n", instance, msg_name_p);
rrc_eNB_process_PAGING_IND(msg_p, msg_name_p, instance);
break;
case S1AP_E_RAB_SETUP_REQ:
rrc_eNB_process_S1AP_E_RAB_SETUP_REQ(msg_p, msg_name_p, instance);
LOG_D(RRC, "[eNB %d] Received the message %s\n", instance, msg_name_p);
break;
case S1AP_E_RAB_MODIFY_REQ:
rrc_eNB_process_S1AP_E_RAB_MODIFY_REQ(msg_p, msg_name_p, instance);
break;
case S1AP_E_RAB_RELEASE_COMMAND:
rrc_eNB_process_S1AP_E_RAB_RELEASE_COMMAND(msg_p, msg_name_p, instance);
break;
case S1AP_UE_CONTEXT_RELEASE_REQ:
rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_REQ(msg_p, msg_name_p, instance);
break;
case S1AP_UE_CONTEXT_RELEASE_COMMAND:
rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_COMMAND(msg_p, msg_name_p, instance);
break;
case GTPV1U_ENB_DELETE_TUNNEL_RESP:
///Nothing to do. Apparently everything is done in S1AP processing
//LOG_I(RRC, "[eNB %d] Received message %s, not processed because procedure not synched\n",
//instance, msg_name_p);
if (rrc_eNB_get_ue_context(RC.nrrrc[instance], GTPV1U_ENB_DELETE_TUNNEL_RESP(msg_p).rnti)
&& rrc_eNB_get_ue_context(RC.nrrrc[instance], GTPV1U_ENB_DELETE_TUNNEL_RESP(msg_p).rnti)->ue_context.ue_release_timer_rrc > 0) {
rrc_eNB_get_ue_context(RC.nrrrc[instance], GTPV1U_ENB_DELETE_TUNNEL_RESP(msg_p).rnti)->ue_context.ue_release_timer_rrc =
rrc_eNB_get_ue_context(RC.nrrrc[instance], GTPV1U_ENB_DELETE_TUNNEL_RESP(msg_p).rnti)->ue_context.ue_release_timer_thres_rrc;
/* Messages from gNB app */
case NRRRC_CONFIGURATION_REQ:
LOG_I(NR_RRC, "[gNB %d] Received %s : %p\n", instance, msg_name_p,&NRRRC_CONFIGURATION_REQ(msg_p));
openair_rrc_gNB_configuration(GNB_INSTANCE_TO_MODULE_ID(instance), &NRRRC_CONFIGURATION_REQ(msg_p));
LOG_E(NR_RRC, "[gNB %d] Received unexpected message %s\n", instance, msg_name_p);
break;
}
result = itti_free(ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
msg_p = NULL;
}
}