Commit 34adf865 authored by Sakthivel Velumani's avatar Sakthivel Velumani

Removed RRC thread from CUUP

parent 53674191
......@@ -314,20 +314,23 @@ int create_gNB_tasks(void) {
RC.nrrrc = (gNB_RRC_INST **)malloc(RC.nb_nr_inst*sizeof(gNB_RRC_INST *));
LOG_I(PHY, "%s() RC.nb_nr_inst:%d RC.nrrrc:%p\n", __FUNCTION__, RC.nb_nr_inst, RC.nrrrc);
ngran_node_t node_type = get_node_type();
if (node_type != ngran_gNB_CUUP) {
for (int gnb_id = gnb_id_start; (gnb_id < gnb_id_end) ; gnb_id++) {
RC.nrrrc[gnb_id] = (gNB_RRC_INST*)calloc(1,sizeof(gNB_RRC_INST));
LOG_I(PHY, "%s() Creating RRC instance RC.nrrrc[%d]:%p (%d of %d)\n", __FUNCTION__, gnb_id, RC.nrrrc[gnb_id], gnb_id+1, gnb_id_end);
configure_nr_rrc(gnb_id);
}
}
if (RC.nb_nr_inst > 0 &&
!get_softmodem_params()->nsa &&
!(RC.nrrrc[0]->node_type == ngran_gNB_DU)) {
!(node_type == ngran_gNB_DU)) {
// we start pdcp in both cuup (for drb) and cucp (for srb)
init_pdcp();
}
if (is_x2ap_enabled() ) { //&& !NODE_IS_DU(RC.rrc[0]->node_type)
if (is_x2ap_enabled() ) { //&& !NODE_IS_DU(node_type)
LOG_I(X2AP, "X2AP enabled \n");
__attribute__((unused)) uint32_t x2_register_gnb_pending = gNB_app_register_x2 (gnb_id_start, gnb_id_end);
}
......@@ -335,8 +338,8 @@ int create_gNB_tasks(void) {
/* For the CU case the gNB registration with the AMF might have to take place after the F1 setup, as the PLMN info
* can originate from the DU. Add check on whether x2ap is enabled to account for ENDC NSA scenario.*/
if ((get_softmodem_params()->sa || is_x2ap_enabled()) &&
!NODE_IS_DU(RC.nrrrc[0]->node_type) &&
RC.nrrrc[gnb_id_start]->node_type != ngran_gNB_CUUP) {
!NODE_IS_DU(node_type) &&
node_type != ngran_gNB_CUUP) {
/* Try to register each gNB */
//registered_gnb = 0;
__attribute__((unused)) uint32_t register_gnb_pending = gNB_app_register (gnb_id_start, gnb_id_end);
......@@ -364,8 +367,8 @@ int create_gNB_tasks(void) {
}
if (get_softmodem_params()->sa &&
!NODE_IS_DU(RC.nrrrc[0]->node_type) &&
RC.nrrrc[gnb_id_start]->node_type != ngran_gNB_CUUP ) {
!NODE_IS_DU(node_type) &&
node_type != ngran_gNB_CUUP ) {
char* gnb_ipv4_address_for_NGU = NULL;
uint32_t gnb_port_for_NGU = 0;
......@@ -401,19 +404,21 @@ int create_gNB_tasks(void) {
LOG_I(NR_RRC,"Creating NR RRC gNB Task\n");
if (node_type != ngran_gNB_CUUP) {
if (itti_create_task (TASK_RRC_GNB, rrc_gnb_task, NULL) < 0) {
LOG_E(NR_RRC, "Create task for NR RRC gNB failed\n");
return -1;
}
}
// If CU
if ((RC.nrrrc[gnb_id_start]->node_type == ngran_gNB_CU) ||
(RC.nrrrc[gnb_id_start]->node_type == ngran_gNB)) {
if ((node_type == ngran_gNB_CU) ||
(node_type == ngran_gNB)) {
RC.nrrrc[gnb_id_start]->gtpInstN3 = RCconfig_nr_gtpu();
}
//Use check on x2ap to consider the NSA scenario
if((is_x2ap_enabled() || get_softmodem_params()->sa) && (RC.nrrrc[0]->node_type != ngran_gNB_CUCP) ) {
if((is_x2ap_enabled() || get_softmodem_params()->sa) && (node_type != ngran_gNB_CUCP) ) {
if (itti_create_task (TASK_GTPV1_U, &gtpv1uTask, NULL) < 0) {
LOG_E(GTPU, "Create task for GTPV1U failed\n");
return -1;
......@@ -643,7 +648,7 @@ void init_pdcp(void) {
LINK_ENB_PDCP_TO_GTPV1U_BIT;
if (!get_softmodem_params()->nsa) {
if (!NODE_IS_DU(RC.nrrrc[0]->node_type)) {
if (!NODE_IS_DU(get_node_type())) {
pdcp_layer_init();
nr_pdcp_module_init(pdcp_initmask, 0);
}
......
......@@ -67,6 +67,7 @@ typedef struct e1ap_setup_req_s {
long cn_support;
int port_cuup;
int port_cucp;
int remoteDUPort;
in_addr_t IPv4AddressN3;
int portN3;
} e1ap_setup_req_t;
......
add_subdirectory(MESSAGES)
add_library(E1AP e1ap.c e1ap_common.c)
add_library(E1AP e1ap.c e1ap_common.c e1ap_api.c)
target_link_libraries(E1AP
PUBLIC ASN1_E1AP_LIB
PRIVATE UTIL)
......
......@@ -23,6 +23,7 @@
#include "e1ap.h"
#include "e1ap_common.h"
#include "e1ap_api.h"
#include "gnb_config.h"
#include "openair2/SDAP/nr_sdap/nr_sdap_entity.h"
......@@ -773,6 +774,7 @@ int e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(instance_t instance,
}
}
e1ap_encode_send(UPtype, instance, &pdu, 0, __func__);
free(resp);
return 0;
}
......@@ -802,9 +804,7 @@ int e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST(instance_t instance,
E1AP_BearerContextSetupRequest_t *in = &pdu->choice.initiatingMessage->value.choice.BearerContextSetupRequest;
E1AP_BearerContextSetupRequestIEs_t *ie;
MessageDef *msg = itti_alloc_new_message(TASK_CUUP_E1, 0, E1AP_BEARER_CONTEXT_SETUP_REQ);
e1ap_bearer_setup_req_t *bearerCxt = &E1AP_BEARER_CONTEXT_SETUP_REQ(msg);
e1ap_bearer_setup_req_t *bearerCxt = calloc(1, sizeof(e1ap_bearer_setup_req_t));
LOG_I(E1AP, "Bearer context setup number of IEs %d\n", in->protocolIEs.list.count);
for (int i=0; i < in->protocolIEs.list.count; i++) {
......@@ -975,9 +975,8 @@ int e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST(instance_t instance,
}
}
itti_send_msg_to_task(TASK_RRC_GNB, instance, msg);
CUUP_process_e1_bearer_context_setup_req(bearerCxt, instance);
return 0;
}
int e1apCUCP_handle_BEARER_CONTEXT_SETUP_RESPONSE(instance_t instance,
......@@ -1210,9 +1209,7 @@ int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(instance_t instance,
E1AP_BearerContextModificationRequest_t *in = &pdu->choice.initiatingMessage->value.choice.BearerContextModificationRequest;
E1AP_BearerContextModificationRequestIEs_t *ie;
MessageDef *msg = itti_alloc_new_message(TASK_CUUP_E1, 0, E1AP_BEARER_CONTEXT_MODIFICATION_REQ);
e1ap_bearer_setup_req_t *bearerCxt = &E1AP_BEARER_CONTEXT_SETUP_REQ(msg);
e1ap_bearer_setup_req_t *bearerCxt = calloc(1, sizeof(e1ap_bearer_setup_req_t));
LOG_I(E1AP, "Bearer context setup number of IEs %d\n", in->protocolIEs.list.count);
for (int i=0; i < in->protocolIEs.list.count; i++) {
......@@ -1297,7 +1294,7 @@ int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(instance_t instance,
}
}
itti_send_msg_to_task(TASK_RRC_GNB, instance, msg);
CUUP_process_bearer_context_mod_req(bearerCxt, instance);
return 0;
}
......@@ -1631,11 +1628,6 @@ void *E1AP_CUUP_task(void *arg) {
cuxp_task_handle_sctp_data_ind(myInstance, &msg->ittiMsg.sctp_data_ind);
break;
case E1AP_BEARER_CONTEXT_SETUP_RESP:
LOG_I(E1AP, "CUUP Task Received E1AP_BEARER_CONTEXT_SETUP_RESP %ld\n", myInstance);
e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(myInstance, &E1AP_BEARER_CONTEXT_SETUP_RESP(msg));
break;
default:
LOG_E(E1AP, "Unknown message received in TASK_CUUP_E1\n");
break;
......
......@@ -56,6 +56,9 @@ int e1apCUCP_handle_BEARER_CONTEXT_SETUP_FAILURE(instance_t instance,
int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(instance_t instance,
E1AP_E1AP_PDU_t *pdu);
int e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(instance_t instance,
e1ap_bearer_setup_resp_t *resp);
void *E1AP_CUUP_task(void *arg);
void *E1AP_CUCP_task(void *arg);
/*
* 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
*
* Author and copyright: Laurent Thomas, open-cells.com
*
* 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
*/
#include "e1ap_api.h"
#include "UTIL/OSA/osa_defs.h"
#include "nr_pdcp/nr_pdcp_entity.h"
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h"
#include "openair3/ocp-gtpu/gtp_itf.h"
static void fill_DRB_configList(NR_DRB_ToAddModList_t *DRB_configList, pdu_session_to_setup_t *pdu) {
for (int i=0; i < pdu->numDRB2Setup; i++) {
DRB_nGRAN_to_setup_t *drb = pdu->DRBnGRanList + i;
asn1cSequenceAdd(DRB_configList->list, NR_DRB_ToAddMod_t, ie);
ie->drb_Identity = drb->id;
ie->cnAssociation = CALLOC(1, sizeof(*ie->cnAssociation));
ie->cnAssociation->present = NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config;
// sdap_Config
NR_SDAP_Config_t *sdap_config = CALLOC(1, sizeof(*sdap_config));
memset(sdap_config, 0, sizeof(*sdap_config));
ie->cnAssociation->choice.sdap_Config = sdap_config;
sdap_config->pdu_Session = pdu->sessionId;
sdap_config->sdap_HeaderDL = drb->sDAP_Header_DL;
sdap_config->sdap_HeaderUL = drb->sDAP_Header_UL;
sdap_config->defaultDRB = drb->defaultDRB;
sdap_config->mappedQoS_FlowsToAdd = calloc(1, sizeof(struct NR_SDAP_Config__mappedQoS_FlowsToAdd));
for (int j=0; j < drb->numQosFlow2Setup; j++) {
NR_QFI_t *qfi = calloc(1, sizeof(NR_QFI_t));
*qfi = drb->qosFlows[j].fiveQI;
ASN_SEQUENCE_ADD(&sdap_config->mappedQoS_FlowsToAdd->list, qfi);
}
sdap_config->mappedQoS_FlowsToRelease = NULL;
// pdcp_Config
ie->reestablishPDCP = NULL;
ie->recoverPDCP = NULL;
NR_PDCP_Config_t *pdcp_config = calloc(1, sizeof(*pdcp_config));
memset(pdcp_config, 0, sizeof(*pdcp_config));
ie->pdcp_Config = pdcp_config;
pdcp_config->drb = calloc(1,sizeof(*pdcp_config->drb));
pdcp_config->drb->discardTimer = calloc(1, sizeof(*pdcp_config->drb->discardTimer));
*pdcp_config->drb->discardTimer = drb->discardTimer;
pdcp_config->drb->pdcp_SN_SizeUL = calloc(1, sizeof(*pdcp_config->drb->pdcp_SN_SizeUL));
*pdcp_config->drb->pdcp_SN_SizeUL = drb->pDCP_SN_Size_UL;
pdcp_config->drb->pdcp_SN_SizeDL = calloc(1, sizeof(*pdcp_config->drb->pdcp_SN_SizeDL));
*pdcp_config->drb->pdcp_SN_SizeDL = drb->pDCP_SN_Size_DL;
pdcp_config->drb->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed;
pdcp_config->drb->headerCompression.choice.notUsed = 0;
pdcp_config->drb->integrityProtection = NULL;
pdcp_config->drb->statusReportRequired = NULL;
pdcp_config->drb->outOfOrderDelivery = NULL;
pdcp_config->moreThanOneRLC = NULL;
pdcp_config->t_Reordering = calloc(1, sizeof(*pdcp_config->t_Reordering));
*pdcp_config->t_Reordering = drb->reorderingTimer;
pdcp_config->ext1 = NULL;
if (pdu->integrityProtectionIndication == 0 || // Required
pdu->integrityProtectionIndication == 1) { // Preferred
pdcp_config->drb->integrityProtection = calloc(1, sizeof(*pdcp_config->drb->integrityProtection));
*pdcp_config->drb->integrityProtection = NR_PDCP_Config__drb__integrityProtection_enabled;
}
if (pdu->confidentialityProtectionIndication == 0 || // Required
pdu->confidentialityProtectionIndication == 1) { // Preferred
pdcp_config->ext1 = calloc(1, sizeof(*pdcp_config->ext1));
pdcp_config->ext1->cipheringDisabled = calloc(1, sizeof(*pdcp_config->ext1->cipheringDisabled));
*pdcp_config->ext1->cipheringDisabled = NR_PDCP_Config__ext1__cipheringDisabled_true;
}
}
}
static int drb_config_N3gtpu_create(e1ap_bearer_setup_req_t *req,
gtpv1u_gnb_create_tunnel_resp_t *create_tunnel_resp,
instance_t instance) {
gtpv1u_gnb_create_tunnel_req_t create_tunnel_req={0};
NR_DRB_ToAddModList_t DRB_configList = {0};
for (int i=0; i < req->numPDUSessions; i++) {
pdu_session_to_setup_t *pdu = &req->pduSession[i];
create_tunnel_req.pdusession_id[i] = pdu->sessionId;
create_tunnel_req.incoming_rb_id[i] = pdu->DRBnGRanList[0].id; // taking only the first DRB. TODO:change this
memcpy(&create_tunnel_req.dst_addr[i].buffer,
&pdu->tlAddress,
sizeof(uint8_t)*4);
create_tunnel_req.dst_addr[i].length = 32; // 8bits * 4bytes
create_tunnel_req.outgoing_teid[i] = pdu->teId;
fill_DRB_configList(&DRB_configList, pdu);
}
create_tunnel_req.num_tunnels = req->numPDUSessions;
create_tunnel_req.ue_id = (req->gNB_cu_cp_ue_id & 0xFFFF);
// Create N3 tunnel
int ret = gtpv1u_create_ngu_tunnel(instance,
&create_tunnel_req,
create_tunnel_resp);
if (ret != 0) {
LOG_E(NR_RRC,"rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ : gtpv1u_create_ngu_tunnel failed,start to release UE id %ld\n",
create_tunnel_req.ue_id);
return ret;
}
// Configure DRBs
uint8_t *kUPenc = NULL;
uint8_t *kUPint = NULL;
nr_derive_key_up_enc(req->cipheringAlgorithm,
(uint8_t *)req->encryptionKey,
&kUPenc);
nr_derive_key_up_int(req->integrityProtectionAlgorithm,
(uint8_t *)req->integrityProtectionKey,
&kUPint);
nr_pdcp_e1_add_drbs(true, // set this to notify PDCP that his not UE
create_tunnel_req.ue_id,
&DRB_configList,
(req->integrityProtectionAlgorithm << 4) | req->cipheringAlgorithm,
kUPenc,
kUPint);
return ret;
}
void gNB_CU_create_up_ul_tunnel(e1ap_bearer_setup_resp_t *resp,
e1ap_bearer_setup_req_t *req,
instance_t gtpInst,
ue_id_t ue_id,
int remote_port,
in_addr_t my_addr) {
resp->numPDUSessions = req->numPDUSessions;
transport_layer_addr_t dummy_address = {0};
dummy_address.length = 32; // IPv4
for (int i=0; i < req->numPDUSessions; i++) {
resp->pduSession[i].numDRBSetup = req->pduSession[i].numDRB2Setup;
for (int j=0; j < req->pduSession[i].numDRB2Setup; j++) {
DRB_nGRAN_to_setup_t *drb2Setup = req->pduSession[i].DRBnGRanList + j;
DRB_nGRAN_setup_t *drbSetup = resp->pduSession[i].DRBnGRanList + j;
drbSetup->numUpParam = 1;
drbSetup->UpParamList[0].tlAddress = my_addr;
drbSetup->UpParamList[0].teId = newGtpuCreateTunnel(gtpInst,
(ue_id & 0xFFFF),
drb2Setup->id,
drb2Setup->id,
0xFFFF, // We will set the right value from DU answer
-1, // no qfi
dummy_address, // We will set the right value from DU answer
remote_port,
cu_f1u_data_req,
NULL);
drbSetup->id = drb2Setup->id;
drbSetup->numQosFlowSetup = drb2Setup->numQosFlow2Setup;
for (int k=0; k < drbSetup->numQosFlowSetup; k++) {
drbSetup->qosFlows[k].id = drb2Setup->qosFlows[k].id;
}
}
}
}
void CUUP_process_e1_bearer_context_setup_req(e1ap_bearer_setup_req_t *req, instance_t instance) {
gtpv1u_gnb_create_tunnel_resp_t create_tunnel_resp_N3={0};
// GTP tunnel for UL
instance_t gtpInst = getCxtE1(UPtype, instance)->gtpInstN3;
drb_config_N3gtpu_create(req, &create_tunnel_resp_N3, gtpInst);
e1ap_bearer_setup_resp_t *resp = calloc(1, sizeof(e1ap_bearer_setup_resp_t));
int remote_port = getCxtE1(UPtype, instance)->setupReq.remoteDUPort;
in_addr_t my_addr;
inet_pton(AF_INET,
getCxtE1(UPtype, instance)->setupReq.CUUP_e1_ip_address.ipv4_address,
&my_addr);
gtpInst = getCxtE1(UPtype, instance)->gtpInstF1U;
gNB_CU_create_up_ul_tunnel(resp, req, gtpInst, req->gNB_cu_cp_ue_id, remote_port, my_addr);
resp->gNB_cu_cp_ue_id = req->gNB_cu_cp_ue_id;
resp->numPDUSessions = req->numPDUSessions;
for (int i=0; i < req->numPDUSessions; i++) {
pdu_session_setup_t *pduSetup = resp->pduSession + i;
pdu_session_to_setup_t *pdu2Setup = req->pduSession + i;
pduSetup->id = pdu2Setup->sessionId;
memcpy(&pduSetup->tlAddress,
&getCxtE1(UPtype, instance)->setupReq.IPv4AddressN3,
sizeof(in_addr_t));
pduSetup->teId = create_tunnel_resp_N3.gnb_NGu_teid[i];
pduSetup->numDRBSetup = pdu2Setup->numDRB2Setup;
// At this point we don't have a way to know the DRBs that failed to setup
// We assume all DRBs to setup have are setup successfully so we always send successful outcome in response
// TODO: Modify nr_pdcp_add_drbs() to return DRB list that failed to setup to support E1AP
pduSetup->numDRBFailed = 0;
}
e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(instance, resp);
free(req);
}
void update_UL_UP_tunnel_info(e1ap_bearer_setup_req_t *req, instance_t instance, ue_id_t ue_id) {
for (int i=0; i < req->numPDUSessionsMod; i++) {
for (int j=0; j < req->pduSessionMod[i].numDRB2Modify; j++) {
DRB_nGRAN_to_setup_t *drb_p = req->pduSessionMod[i].DRBnGRanModList + j;
transport_layer_addr_t newRemoteAddr;
newRemoteAddr.length = 32; // IPv4
memcpy(newRemoteAddr.buffer,
&drb_p->DlUpParamList[0].tlAddress,
sizeof(in_addr_t));
GtpuUpdateTunnelOutgoingPair(instance,
(ue_id & 0xFFFF),
(ebi_t)drb_p->id,
drb_p->DlUpParamList[0].teId,
newRemoteAddr);
}
}
}
void CUUP_process_bearer_context_mod_req(e1ap_bearer_setup_req_t *req, instance_t instance) {
instance_t gtpInst = getCxtE1(UPtype, instance)->gtpInstF1U;
update_UL_UP_tunnel_info(req, gtpInst, req->gNB_cu_cp_ue_id);
free(req);
// TODO: send bearer cxt mod response
}
/*
* 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
*
* Author and copyright: Laurent Thomas, open-cells.com
*
* 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
*/
#include "e1ap.h"
#include "e1ap_common.h"
#include "NR_DRB-ToAddModList.h"
void gNB_CU_create_up_ul_tunnel(e1ap_bearer_setup_resp_t *resp,
e1ap_bearer_setup_req_t *req,
instance_t gtpInst,
ue_id_t ue_id,
int remote_port,
in_addr_t my_addr);
void update_UL_UP_tunnel_info(e1ap_bearer_setup_req_t *req, instance_t instance, ue_id_t ue_id);
void CUUP_process_e1_bearer_context_setup_req(e1ap_bearer_setup_req_t *req, instance_t instance);
void CUUP_process_bearer_context_mod_req(e1ap_bearer_setup_req_t *req, instance_t instance);
......@@ -147,12 +147,13 @@ void *gNB_app_task(void *args_p)
int cell_to_activate = 0;
itti_mark_task_ready (TASK_GNB_APP);
ngran_node_t node_type = get_node_type();
if (RC.nb_nr_inst > 0) {
if (RC.nrrrc[0]->node_type == ngran_gNB_CUCP ||
RC.nrrrc[0]->node_type == ngran_gNB_CU ||
RC.nrrrc[0]->node_type == ngran_eNB_CU ||
RC.nrrrc[0]->node_type == ngran_ng_eNB_CU) {
if (node_type == ngran_gNB_CUCP ||
node_type == ngran_gNB_CU ||
node_type == ngran_eNB_CU ||
node_type == ngran_ng_eNB_CU) {
if (itti_create_task(TASK_CU_F1, F1AP_CU_task, NULL) < 0) {
LOG_E(F1AP, "Create task for F1AP CU failed\n");
......@@ -160,7 +161,7 @@ void *gNB_app_task(void *args_p)
}
}
if (RC.nrrrc[0]->node_type == ngran_gNB_CUCP) {
if (node_type == ngran_gNB_CUCP) {
if (itti_create_task(TASK_CUCP_E1, E1AP_CUCP_task, NULL) < 0) {
LOG_E(E1AP, "Create task for E1AP CP failed\n");
......@@ -174,7 +175,7 @@ void *gNB_app_task(void *args_p)
}
if (RC.nrrrc[0]->node_type == ngran_gNB_CUUP) {
if (node_type == ngran_gNB_CUUP) {
if (itti_create_task(TASK_CUUP_E1, E1AP_CUUP_task, NULL) < 0) {
LOG_E(E1AP, "Create task for E1AP UP failed\n");
AssertFatal(1==0, "exiting");
......@@ -187,7 +188,7 @@ void *gNB_app_task(void *args_p)
itti_send_msg_to_task(TASK_CUUP_E1, GNB_MODULE_ID_TO_INSTANCE(0), msg_p);
}
if (NODE_IS_DU(RC.nrrrc[0]->node_type)) {
if (NODE_IS_DU(node_type)) {
if (itti_create_task(TASK_DU_F1, F1AP_DU_task, NULL) < 0) {
LOG_E(F1AP, "Create task for F1AP DU failed\n");
......@@ -263,7 +264,7 @@ void *gNB_app_task(void *args_p)
break;
case F1AP_SETUP_RESP:
AssertFatal(NODE_IS_DU(RC.nrrrc[0]->node_type), "Should not have received F1AP_SETUP_RESP in CU/gNB\n");
AssertFatal(NODE_IS_DU(node_type), "Should not have received F1AP_SETUP_RESP in CU/gNB\n");
LOG_I(GNB_APP, "Received %s: associated ngran_gNB_CU %s with %d cells to activate\n", ITTI_MSG_NAME (msg_p),
F1AP_SETUP_RESP(msg_p).gNB_CU_name,F1AP_SETUP_RESP(msg_p).num_cells_to_activate);
......@@ -273,7 +274,7 @@ void *gNB_app_task(void *args_p)
break;
case F1AP_GNB_CU_CONFIGURATION_UPDATE:
AssertFatal(NODE_IS_DU(RC.nrrrc[0]->node_type), "Should not have received F1AP_GNB_CU_CONFIGURATION_UPDATE in CU/gNB\n");
AssertFatal(NODE_IS_DU(node_type), "Should not have received F1AP_GNB_CU_CONFIGURATION_UPDATE in CU/gNB\n");
LOG_I(GNB_APP, "Received %s: associated ngran_gNB_CU %s with %d cells to activate\n", ITTI_MSG_NAME (msg_p),
F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p).gNB_CU_name,F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p).num_cells_to_activate);
......
......@@ -87,7 +87,7 @@
extern uint16_t sf_ahead;
int macrlc_has_f1 = 0;
static ngran_node_t get_node_type(void);
ngran_node_t get_node_type(void);
extern int config_check_band_frequencies(int ind, int16_t band, uint64_t downlink_frequency,
int32_t uplink_frequency_offset, uint32_t frame_type);
......@@ -1848,6 +1848,7 @@ int RCconfig_NR_CU_E1(MessageDef *msg_p, uint32_t i) {
strcpy(e1Setup->CUUP_e1_ip_address.ipv4_address, *(GNBE1ParamList.paramarray[0][GNB_CONFIG_E1_IPV4_ADDRESS_CUUP].strptr));
e1Setup->CUUP_e1_ip_address.ipv4 = 1;
e1Setup->port_cuup = *GNBE1ParamList.paramarray[0][GNB_CONFIG_E1_PORT_CUUP].uptr;
e1Setup->remoteDUPort = e1Setup->port_cuup; // set same as local port for now TODO: get from F1 config
char N3Addr[64];
int N3Port;
if (!get_NGU_S1U_addr(N3Addr, &N3Port)) {;
......@@ -2289,7 +2290,7 @@ int gNB_app_handle_f1ap_gnb_cu_configuration_update(f1ap_gnb_cu_configuration_up
return(ret);
}
static ngran_node_t get_node_type(void)
ngran_node_t get_node_type(void)
{
paramdef_t MacRLC_Params[] = MACRLCPARAMS_DESC;
paramlist_def_t MacRLC_ParamList = {CONFIG_STRING_MACRLC_LIST,NULL,0};
......
......@@ -109,6 +109,7 @@ int gNB_app_handle_f1ap_setup_resp(f1ap_setup_resp_t *resp);
int gNB_app_handle_f1ap_gnb_cu_configuration_update(f1ap_gnb_cu_configuration_update_t *gnb_cu_cfg_update);
void nr_read_config_and_init(void);
int RCconfig_NR_CU_E1(MessageDef *msg_p, uint32_t i);
ngran_node_t get_node_type(void);
#endif /* GNB_CONFIG_H_ */
/** @} */
......@@ -38,6 +38,7 @@
#include <openair3/ocp-gtpu/gtp_itf.h>
#include "openair2/SDAP/nr_sdap/nr_sdap.h"
#include "nr_pdcp_e1_api.h"
#include "gnb_config.h"
#define TODO do { \
printf("%s:%d:%s: todo\n", __FILE__, __LINE__, __FUNCTION__); \
......@@ -58,6 +59,8 @@ static uint64_t pdcp_optmask;
uint8_t first_dcch = 0;
uint8_t proto_agent_flag = 0;
static ngran_node_t node_type;
/****************************************************************************/
/* rlc_data_req queue - begin */
/****************************************************************************/
......@@ -528,6 +531,10 @@ int pdcp_fifo_flush_sdus(const protocol_ctxt_t *const ctxt_pP)
return 0;
}
static void set_node_type() {
node_type = get_node_type();
}
void pdcp_layer_init(void)
{
/* hack: be sure to initialize only once */
......@@ -543,7 +550,9 @@ void pdcp_layer_init(void)
nr_pdcp_ue_manager = new_nr_pdcp_ue_manager(1);
if ((RC.nrrrc == NULL) || (!NODE_IS_CU(RC.nrrrc[0]->node_type))) {
set_node_type();
if ((RC.nrrrc == NULL) || (!NODE_IS_CU(node_type))) {
init_nr_rlc_data_req_queue();
}
......@@ -687,7 +696,7 @@ rb_found:
ctxt.brOption = 0;
ctxt.rnti = ue->ue_id;
if (RC.nrrrc != NULL && NODE_IS_CU(RC.nrrrc[0]->node_type)) {
if (RC.nrrrc != NULL && NODE_IS_CU(node_type)) {
MessageDef *message_p = itti_alloc_new_message_sized(TASK_PDCP_ENB, 0,
GTPV1U_TUNNEL_DATA_REQ,
sizeof(gtpv1u_tunnel_data_req_t)
......@@ -788,7 +797,7 @@ srb_found:
LOG_D(PDCP, "%s(): (srb %d) calling rlc_data_req size %d\n", __func__, srb_id, size);
//for (i = 0; i < size; i++) printf(" %2.2x", (unsigned char)memblock->data[i]);
//printf("\n");
if ((RC.nrrrc == NULL) || (!NODE_IS_CU(RC.nrrrc[0]->node_type))) {
if ((RC.nrrrc == NULL) || (!NODE_IS_CU(node_type))) {
ctxt.module_id = 0;
ctxt.enb_flag = 1;
ctxt.instance = 0;
......
......@@ -104,6 +104,7 @@
#include "openair2/F1AP/f1ap_common.h"
#include "openair2/E1AP/e1ap_common.h"
#include "openair2/SDAP/nr_sdap/nr_sdap_entity.h"
#include "openair2/E1AP/e1ap_api.h"
#include "BIT_STRING.h"
#include "assertions.h"
......@@ -208,9 +209,6 @@ static void rrc_gNB_mac_rrc_init(gNB_RRC_INST *rrc)
rrc->mac_rrc.nr_e1_bearer_cxt_msg_transfer = bearer_context_setup_e1ap;
rrc->mac_rrc.nr_e1_ue_cxt_mod_msg_transfer = ue_cxt_mod_send_e1ap;
break;
case ngran_gNB_CUUP:
// CUUP should not have a RRC instance but we let it for now
break;
case ngran_gNB_CU:
mac_rrc_dl_f1ap_init(&rrc->mac_rrc);
rrc->mac_rrc.nr_e1_bearer_cxt_msg_transfer = bearer_context_setup_direct;
......@@ -3609,32 +3607,6 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, const ch
}
static void update_UL_UP_tunnel_info(e1ap_bearer_setup_req_t *req, instance_t instance, ue_id_t ue_id) {
for (int i=0; i < req->numPDUSessionsMod; i++) {
for (int j=0; j < req->pduSessionMod[i].numDRB2Modify; j++) {
DRB_nGRAN_to_setup_t *drb_p = req->pduSessionMod[i].DRBnGRanModList + j;
transport_layer_addr_t newRemoteAddr;
newRemoteAddr.length = 32; // IPv4
memcpy(newRemoteAddr.buffer,
&drb_p->DlUpParamList[0].tlAddress,
sizeof(in_addr_t));
GtpuUpdateTunnelOutgoingPair(instance,
(ue_id & 0xFFFF),
(ebi_t)drb_p->id,
drb_p->DlUpParamList[0].teId,
newRemoteAddr);
}
}
}
void rrc_CUUP_process_bearer_context_mod_req(e1ap_bearer_setup_req_t *req, instance_t instance) {
instance_t gtpInst = getCxtE1(UPtype, instance)->gtpInstF1U;
update_UL_UP_tunnel_info(req, gtpInst, req->gNB_cu_cp_ue_id);
// TODO: send bearer cxt mod response
}
void ue_cxt_mod_send_e1ap(MessageDef *msg, instance_t instance) {
int module_id = 0;
itti_send_msg_to_task(TASK_CUCP_E1, module_id, msg);
......@@ -4017,209 +3989,6 @@ int rrc_gNB_process_e1_setup_req(e1ap_setup_req_t *req, instance_t instance) {
return 0;
}
void fill_DRB_configList_e1(NR_DRB_ToAddModList_t *DRB_configList, pdu_session_to_setup_t *pdu) {
for (int i=0; i < pdu->numDRB2Setup; i++) {
DRB_nGRAN_to_setup_t *drb = pdu->DRBnGRanList + i;
asn1cSequenceAdd(DRB_configList->list, NR_DRB_ToAddMod_t, ie);
ie->drb_Identity = drb->id;
ie->cnAssociation = CALLOC(1, sizeof(*ie->cnAssociation));
ie->cnAssociation->present = NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config;
// sdap_Config
NR_SDAP_Config_t *sdap_config = CALLOC(1, sizeof(*sdap_config));
memset(sdap_config, 0, sizeof(*sdap_config));
ie->cnAssociation->choice.sdap_Config = sdap_config;
sdap_config->pdu_Session = pdu->sessionId;
sdap_config->sdap_HeaderDL = drb->sDAP_Header_DL;
sdap_config->sdap_HeaderUL = drb->sDAP_Header_UL;
sdap_config->defaultDRB = drb->defaultDRB;
sdap_config->mappedQoS_FlowsToAdd = calloc(1, sizeof(struct NR_SDAP_Config__mappedQoS_FlowsToAdd));
// LTSFIXME
for (int j=0; j < drb->numQosFlow2Setup; j++) {
NR_QFI_t *qfi = calloc(1, sizeof(NR_QFI_t));
*qfi = drb->qosFlows[j].fiveQI;
ASN_SEQUENCE_ADD(&sdap_config->mappedQoS_FlowsToAdd->list, qfi);
}
sdap_config->mappedQoS_FlowsToRelease = NULL;
// pdcp_Config
ie->reestablishPDCP = NULL;
ie->recoverPDCP = NULL;
NR_PDCP_Config_t *pdcp_config = calloc(1, sizeof(*pdcp_config));
memset(pdcp_config, 0, sizeof(*pdcp_config));
ie->pdcp_Config = pdcp_config;
pdcp_config->drb = calloc(1,sizeof(*pdcp_config->drb));
pdcp_config->drb->discardTimer = calloc(1, sizeof(*pdcp_config->drb->discardTimer));
*pdcp_config->drb->discardTimer = drb->discardTimer;
pdcp_config->drb->pdcp_SN_SizeUL = calloc(1, sizeof(*pdcp_config->drb->pdcp_SN_SizeUL));
*pdcp_config->drb->pdcp_SN_SizeUL = drb->pDCP_SN_Size_UL;
pdcp_config->drb->pdcp_SN_SizeDL = calloc(1, sizeof(*pdcp_config->drb->pdcp_SN_SizeDL));
*pdcp_config->drb->pdcp_SN_SizeDL = drb->pDCP_SN_Size_DL;
pdcp_config->drb->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed;
pdcp_config->drb->headerCompression.choice.notUsed = 0;
pdcp_config->drb->integrityProtection = NULL;
pdcp_config->drb->statusReportRequired = NULL;
pdcp_config->drb->outOfOrderDelivery = NULL;
pdcp_config->moreThanOneRLC = NULL;
pdcp_config->t_Reordering = calloc(1, sizeof(*pdcp_config->t_Reordering));
*pdcp_config->t_Reordering = drb->reorderingTimer;
pdcp_config->ext1 = NULL;
if (pdu->integrityProtectionIndication == 0 || // Required
pdu->integrityProtectionIndication == 1) { // Preferred
pdcp_config->drb->integrityProtection = calloc(1, sizeof(*pdcp_config->drb->integrityProtection));
*pdcp_config->drb->integrityProtection = NR_PDCP_Config__drb__integrityProtection_enabled;
}
if (pdu->confidentialityProtectionIndication == 0 || // Required
pdu->confidentialityProtectionIndication == 1) { // Preferred
pdcp_config->ext1 = calloc(1, sizeof(*pdcp_config->ext1));
pdcp_config->ext1->cipheringDisabled = calloc(1, sizeof(*pdcp_config->ext1->cipheringDisabled));
*pdcp_config->ext1->cipheringDisabled = NR_PDCP_Config__ext1__cipheringDisabled_true;
}
}
}
int drb_config_N3gtpu_create_e1(e1ap_bearer_setup_req_t *req,
gtpv1u_gnb_create_tunnel_resp_t *create_tunnel_resp,
instance_t instance) {
gtpv1u_gnb_create_tunnel_req_t create_tunnel_req={0};
NR_DRB_ToAddModList_t DRB_configList = {0};
for (int i=0; i < req->numPDUSessions; i++) {
pdu_session_to_setup_t *pdu = &req->pduSession[i];
create_tunnel_req.pdusession_id[i] = pdu->sessionId;
create_tunnel_req.incoming_rb_id[i] = pdu->DRBnGRanList[0].id; // taking only the first DRB. TODO:change this
memcpy(&create_tunnel_req.dst_addr[i].buffer,
&pdu->tlAddress,
sizeof(uint8_t)*4);
create_tunnel_req.dst_addr[i].length = 32; // 8bits * 4bytes
create_tunnel_req.outgoing_teid[i] = pdu->teId;
fill_DRB_configList_e1(&DRB_configList, pdu);
}
create_tunnel_req.num_tunnels = req->numPDUSessions;
create_tunnel_req.ue_id = (req->gNB_cu_cp_ue_id & 0xFFFF);
// Create N3 tunnel
int ret = gtpv1u_create_ngu_tunnel(
instance,
&create_tunnel_req,
create_tunnel_resp);
if (ret != 0) {
LOG_E(NR_RRC,"rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ : gtpv1u_create_ngu_tunnel failed,start to release UE id %ld\n",
create_tunnel_req.ue_id);
return ret;
}
// Configure DRBs
uint8_t *kUPenc = NULL;
uint8_t *kUPint = NULL;
nr_derive_key_up_enc(req->cipheringAlgorithm,
(uint8_t *)req->encryptionKey,
&kUPenc);
nr_derive_key_up_int(req->integrityProtectionAlgorithm,
(uint8_t *)req->integrityProtectionKey,
&kUPint);
nr_pdcp_e1_add_drbs(true, // set this to notify PDCP that his not UE
create_tunnel_req.ue_id,
&DRB_configList,
(req->integrityProtectionAlgorithm << 4) | req->cipheringAlgorithm,
kUPenc,
kUPint);
return ret;
}
void gNB_CU_create_up_ul_tunnel(e1ap_bearer_setup_resp_t *resp,
e1ap_bearer_setup_req_t *req,
instance_t gtpInst,
ue_id_t ue_id,
int remote_port,
in_addr_t my_addr) {
resp->numPDUSessions = req->numPDUSessions;
transport_layer_addr_t dummy_address = {0};
dummy_address.length = 32; // IPv4
for (int i=0; i < req->numPDUSessions; i++) {
resp->pduSession[i].numDRBSetup = req->pduSession[i].numDRB2Setup;
for (int j=0; j < req->pduSession[i].numDRB2Setup; j++) {
DRB_nGRAN_to_setup_t *drb2Setup = req->pduSession[i].DRBnGRanList + j;
DRB_nGRAN_setup_t *drbSetup = resp->pduSession[i].DRBnGRanList + j;
drbSetup->numUpParam = 1;
drbSetup->UpParamList[0].tlAddress = my_addr;
drbSetup->UpParamList[0].teId = newGtpuCreateTunnel(gtpInst,
(ue_id & 0xFFFF),
drb2Setup->id,
drb2Setup->id,
0xFFFF, // We will set the right value from DU answer
-1, // no qfi
dummy_address, // We will set the right value from DU answer
remote_port,
cu_f1u_data_req,
NULL);
drbSetup->id = drb2Setup->id;
drbSetup->numQosFlowSetup = drb2Setup->numQosFlow2Setup;
for (int k=0; k < drbSetup->numQosFlowSetup; k++) {
drbSetup->qosFlows[k].id = drb2Setup->qosFlows[k].id;
}
}
}
}
void rrc_gNB_process_e1_bearer_context_setup_req(e1ap_bearer_setup_req_t *req, instance_t instance) {
protocol_ctxt_t ctxt={0};
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, req->gNB_cu_cp_ue_id, 0, 0, 0);
gtpv1u_gnb_create_tunnel_resp_t create_tunnel_resp_N3={0};
// GTP tunnel for UL
instance_t gtpInst = getCxtE1(UPtype, instance)->gtpInstN3;
drb_config_N3gtpu_create_e1(req, &create_tunnel_resp_N3, gtpInst);
MessageDef *message_p;
message_p = itti_alloc_new_message (TASK_RRC_GNB, instance, E1AP_BEARER_CONTEXT_SETUP_RESP);
e1ap_bearer_setup_resp_t *resp = &E1AP_BEARER_CONTEXT_SETUP_RESP(message_p);
int remote_port = RC.nrrrc[ctxt.module_id]->eth_params_s.remote_portd;
in_addr_t my_addr;
inet_pton(AF_INET,
getCxtE1(UPtype, instance)->setupReq.CUUP_e1_ip_address.ipv4_address,
&my_addr);
gtpInst = getCxtE1(UPtype, instance)->gtpInstF1U;
gNB_CU_create_up_ul_tunnel(resp, req, gtpInst, req->gNB_cu_cp_ue_id, remote_port, my_addr);
resp->gNB_cu_cp_ue_id = req->gNB_cu_cp_ue_id;
resp->numPDUSessions = req->numPDUSessions;
for (int i=0; i < req->numPDUSessions; i++) {
pdu_session_setup_t *pduSetup = resp->pduSession + i;
pdu_session_to_setup_t *pdu2Setup = req->pduSession + i;
pduSetup->id = pdu2Setup->sessionId;
memcpy(&pduSetup->tlAddress,
&getCxtE1(UPtype, instance)->setupReq.IPv4AddressN3,
sizeof(in_addr_t));
pduSetup->teId = create_tunnel_resp_N3.gnb_NGu_teid[i];
pduSetup->numDRBSetup = pdu2Setup->numDRB2Setup;
// At this point we don't have a way to know the DRBs that failed to setup
// We assume all DRBs to setup have are setup successfully so we always send successful outcome in response
// TODO: Modify nr_pdcp_add_drbs() to return DRB list that failed to setup to support E1AP
pduSetup->numDRBFailed = 0;
}
itti_send_msg_to_task(TASK_CUUP_E1, instance, message_p);
}
void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_context_p,
e1ap_bearer_setup_resp_t *e1ap_resp) {
......@@ -4502,21 +4271,11 @@ void *rrc_gnb_task(void *args_p) {
rrc_gNB_process_e1_setup_req(&E1AP_SETUP_REQ(msg_p), instance);
break;
case E1AP_BEARER_CONTEXT_SETUP_REQ:
LOG_I(NR_RRC, "Received E1AP_BEARER_CONTEXT_SETUP_REQ for instance %d\n", (int)instance);
rrc_gNB_process_e1_bearer_context_setup_req(&E1AP_BEARER_CONTEXT_SETUP_REQ(msg_p), instance);
break;
case E1AP_BEARER_CONTEXT_SETUP_RESP:
LOG_I(NR_RRC, "Received E1AP_BEARER_CONTEXT_SETUP_RESP for instance %d\n", (int)instance);
rrc_gNB_process_e1_bearer_context_setup_resp(&E1AP_BEARER_CONTEXT_SETUP_RESP(msg_p), instance);
break;
case E1AP_BEARER_CONTEXT_MODIFICATION_REQ:
LOG_I(NR_RRC, "Received E1AP_BEARER_CONTEXT_MODIFICATION_REQ for instance %d\n", (int)instance);
rrc_CUUP_process_bearer_context_mod_req(&E1AP_BEARER_CONTEXT_SETUP_REQ(msg_p), instance);
break;
default:
LOG_E(NR_RRC, "[gNB %ld] Received unexpected message %s\n", instance, msg_name_p);
break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment