From a645e10ff56b2f956c3f3f54b2231e82131783a0 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 14 Feb 2024 10:46:50 +0100 Subject: [PATCH] F1AP: message encoders should no trigger GTP The F1AP message encoders and decoders should do only that, encoding and decoding messages. For the actual logic handling, including set up and teardown of bearers, we should use the handlers. In this commit, delete GTP tunnel handling from encoders/decoders. For the CU, this happens already in the CU-UP/E1 handlers in cucp_cuup_handler.c. For the DU, add it in the handlers in mac_rrc_dl_handler.c. --- openair2/F1AP/f1ap_cu_ue_context_management.c | 29 +----- openair2/F1AP/f1ap_du_ue_context_management.c | 57 +++--------- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 88 ++++++++++++++++++- 3 files changed, 99 insertions(+), 75 deletions(-) diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index cc29a92ebb..bed69ae455 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -38,8 +38,6 @@ #include "rrc_extern.h" #include "openair2/RRC/NR/rrc_gNB_NGAP.h" -#include -#include "LAYER2/nr_pdcp/nr_pdcp_oai_api.h" static void setQos(F1AP_NonDynamic5QIDescriptor_t **toFill) { @@ -503,19 +501,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setu /* 12.1.3 uLUPTNLInformation_ToBeSetup_List */ for (int j = 0; j < f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_ul_tnl_length; j++) { - /*Use a dummy teid for the outgoing GTP-U tunnel (DU) which will be updated once we get the UE context setup response from the DU*/ - /* Use a dummy address and teid for the outgoing GTP-U tunnel (DU) which will be updated once we get the UE context setup response from the DU */ - transport_layer_addr_t addr = { .length= 32, .buffer= { 0 } }; - f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_ul_tnl[j].teid = newGtpuCreateTunnel(getCxt(0)->gtpInst, - f1ap_ue_context_setup_req->gNB_CU_ue_id, - f1ap_ue_context_setup_req->drbs_to_be_setup[i].drb_id, - f1ap_ue_context_setup_req->drbs_to_be_setup[i].drb_id, - 0xFFFF, // We will set the right value from DU answer - -1, // no qfi - addr, // We will set the right value from DU answer - f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_dl_tnl[0].port, - cu_f1u_data_req, - NULL); + DevAssert(f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_ul_tnl[j].teid > 0); /* 12.3.1 ULTunnels_ToBeSetup_Item */ asn1cSequenceAdd(drbs_toBeSetup_item->uLUPTNLInformation_ToBeSetup_List.list, F1AP_ULUPTNLInformation_ToBeSetup_Item_t, uLUPTNLInformation_ToBeSetup_Item); @@ -688,11 +674,6 @@ int CU_handle_UE_CONTEXT_SETUP_RESPONSE(instance_t instance, sctp_assoc_t assoc_ F1AP_GTPTunnel_t *dl_up_tnl0 = dl_up_tnl_info_p->dLUPTNLInformation.choice.gTPTunnel; BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&dl_up_tnl0->transportLayerAddress, drb_p->up_dl_tnl[0].tl_address); OCTET_STRING_TO_UINT32(&dl_up_tnl0->gTP_TEID, drb_p->up_dl_tnl[0].teid); - GtpuUpdateTunnelOutgoingAddressAndTeid(getCxt(instance)->gtpInst, - f1ap_ue_context_setup_resp->gNB_DU_ue_id, - (ebi_t)drbs_setup_item_p->dRBID, - drb_p->up_dl_tnl[0].tl_address, - drb_p->up_dl_tnl[0].teid); } } @@ -1569,9 +1550,6 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_conte &drbs_toBeReleased_item_ies->value.choice.DRBs_ToBeReleased_Item; /* dRBID */ drbs_toBeReleased_item->dRBID = f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id; - newGtpuDeleteOneTunnel(getCxt(0)->gtpInst, - f1ap_ue_context_modification_req->gNB_CU_ue_id, - f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id); } } @@ -1644,11 +1622,6 @@ int CU_handle_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance, sctp_assoc_t F1AP_GTPTunnel_t *dl_up_tnl0 = dl_up_tnl_info_p->dLUPTNLInformation.choice.gTPTunnel; BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&dl_up_tnl0->transportLayerAddress, drb_p->up_dl_tnl[0].tl_address); OCTET_STRING_TO_UINT32(&dl_up_tnl0->gTP_TEID, drb_p->up_dl_tnl[0].teid); - GtpuUpdateTunnelOutgoingAddressAndTeid(getCxt(instance)->gtpInst, - f1ap_ue_context_modification_resp->gNB_CU_ue_id, - (ebi_t)drbs_setupmod_item_p->dRBID, - drb_p->up_dl_tnl[0].tl_address, - drb_p->up_dl_tnl[0].teid); } } // SRBs_FailedToBeSetupMod_List diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c index e306463b66..e175b215bb 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -40,24 +40,6 @@ #include #include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h" -bool DURecvCb(protocol_ctxt_t *ctxt_pP, - const srb_flag_t srb_flagP, - const rb_id_t rb_idP, - const mui_t muiP, - const confirm_t confirmP, - const sdu_size_t sdu_buffer_sizeP, - unsigned char *const sdu_buffer_pP, - const pdcp_transmission_mode_t modeP, - const uint32_t *sourceL2Id, - const uint32_t *destinationL2Id) -{ - // The buffer comes from the stack in gtp-u thread, we have a make a separate buffer to enqueue in a inter-thread message queue - uint8_t *sdu = malloc16(sdu_buffer_sizeP); - memcpy(sdu, sdu_buffer_pP, sdu_buffer_sizeP); - du_rlc_data_req(ctxt_pP, srb_flagP, false, rb_idP, muiP, confirmP, sdu_buffer_sizeP, sdu); - return true; -} - int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { F1AP_UEContextSetupRequest_t *container; @@ -305,6 +287,7 @@ int DU_send_UE_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_set ie7->criticality = F1AP_Criticality_ignore; ie7->value.present = F1AP_UEContextSetupResponseIEs__value_PR_DRBs_Setup_List; for (int i=0; i< resp->drbs_to_be_setup_length; i++) { + f1ap_drb_to_be_setup_t *drb = &resp->drbs_to_be_setup[i]; // asn1cSequenceAdd(ie7->value.choice.DRBs_Setup_List.list, F1AP_DRBs_Setup_ItemIEs_t, drbs_setup_item_ies); @@ -315,14 +298,17 @@ int DU_send_UE_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_set /* ADD */ F1AP_DRBs_Setup_Item_t *drbs_setup_item=&drbs_setup_item_ies->value.choice.DRBs_Setup_Item; /* dRBID */ - drbs_setup_item->dRBID = resp->drbs_to_be_setup[i].drb_id; + drbs_setup_item->dRBID = drb->drb_id; /* OPTIONAL */ /* lCID */ //drbs_setup_item.lCID = (F1AP_LCID_t *)calloc(1, sizeof(F1AP_LCID_t)); //drbs_setup_item.lCID = 1L; - for (int j=0; jdrbs_to_be_setup[i].up_dl_tnl_length; j++) { + for (int j = 0; j < drb->up_dl_tnl_length; j++) { + const f1ap_up_tnl_t *tnl = &drb->up_dl_tnl[j]; + DevAssert(tnl->teid > 0); + /* ADD */ asn1cSequenceAdd(drbs_setup_item->dLUPTNLInformation_ToBeSetup_List.list, F1AP_DLUPTNLInformation_ToBeSetup_Item_t, dLUPTNLInformation_ToBeSetup_Item); @@ -330,12 +316,9 @@ int DU_send_UE_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_set /* gTPTunnel */ asn1cCalloc(dLUPTNLInformation_ToBeSetup_Item->dLUPTNLInformation.choice.gTPTunnel,gTPTunnel); /* transportLayerAddress */ - struct sockaddr_in addr= {0}; - inet_pton(AF_INET, getCxt(0)->net_config.DU_f1_ip_address.ipv4_address, &addr.sin_addr.s_addr); - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(addr.sin_addr.s_addr, - &gTPTunnel->transportLayerAddress); + TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(tnl->tl_address, &gTPTunnel->transportLayerAddress); /* gTP_TEID */ - INT32_TO_OCTET_STRING(resp->drbs_to_be_setup[i].up_dl_tnl[j].teid, &gTPTunnel->gTP_TEID); + INT32_TO_OCTET_STRING(tnl->teid, &gTPTunnel->gTP_TEID); } // for j } // for i @@ -1008,7 +991,6 @@ int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, sctp_assoc_t DevAssert(tbrel->id == F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_Item); DevAssert(tbrel->value.present == F1AP_DRBs_ToBeReleased_ItemIEs__value_PR_DRBs_ToBeReleased_Item); f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id = tbrel->value.choice.DRBs_ToBeReleased_Item.dRBID; - newGtpuDeleteOneTunnel(0, f1ap_ue_context_modification_req->gNB_DU_ue_id, f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id); } } @@ -1166,20 +1148,8 @@ int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_cont drbs_setupmod_item->dRBID = resp->drbs_to_be_setup[i].drb_id; for (int j=0; jdrbs_to_be_setup[i].up_dl_tnl_length; j++) { - f1ap_drb_to_be_setup_t *drb = &resp->drbs_to_be_setup[i]; - transport_layer_addr_t tl_addr = {0}; - memcpy(tl_addr.buffer, &drb->up_ul_tnl[0].tl_address, sizeof(drb->up_ul_tnl[0].tl_address)); - tl_addr.length = sizeof(drb->up_ul_tnl[0].tl_address) * 8; - drb->up_dl_tnl[j].teid = newGtpuCreateTunnel(getCxt(0)->gtpInst, - resp->gNB_DU_ue_id, - drb->drb_id, - drb->drb_id, - drb->up_ul_tnl[j].teid, - -1, // no qfi - tl_addr, - drb->up_ul_tnl[0].port, - DURecvCb, - NULL); + const f1ap_up_tnl_t *tnl = &resp->drbs_to_be_setup[i].up_dl_tnl[j]; + DevAssert(tnl->teid > 0); /* ADD */ asn1cSequenceAdd(drbs_setupmod_item->dLUPTNLInformation_ToBeSetup_List.list, @@ -1188,12 +1158,9 @@ int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_cont /* gTPTunnel */ asn1cCalloc(dLUPTNLInformation_ToBeSetup_Item->dLUPTNLInformation.choice.gTPTunnel,gTPTunnel); /* transportLayerAddress */ - struct sockaddr_in addr= {0}; - inet_pton(AF_INET, getCxt(0)->net_config.DU_f1_ip_address.ipv4_address, &addr.sin_addr.s_addr); - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(addr.sin_addr.s_addr, - &gTPTunnel->transportLayerAddress); + TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(tnl->tl_address, &gTPTunnel->transportLayerAddress); /* gTP_TEID */ - INT32_TO_OCTET_STRING(resp->drbs_to_be_setup[i].up_dl_tnl[j].teid, &gTPTunnel->gTP_TEID); + INT32_TO_OCTET_STRING(tnl->teid, &gTPTunnel->gTP_TEID); } // for j } // for i } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index 04f2c2fdc9..44c7839463 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -23,8 +23,11 @@ #include "mac_proto.h" #include "openair2/F1AP/f1ap_ids.h" +#include "openair2/F1AP/f1ap_common.h" #include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h" #include "F1AP_CauseRadioNetwork.h" +#include "openair3/ocp-gtpu/gtp_itf.h" +#include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h" #include "uper_decoder.h" #include "uper_encoder.h" @@ -34,6 +37,59 @@ const uint64_t qos_fiveqi[26] = {1, 2, 3, 4, 65, 66, 67, 71, 72, 73, 74, 76, 5, const uint64_t qos_priority[26] = {20, 40, 30, 50, 7, 20, 15, 56, 56, 56, 56, 56, 10, 60, 70, 80, 90, 5, 55, 65, 68, 19, 22, 24, 21, 18}; +static instance_t get_f1_gtp_instance(void) +{ + const f1ap_cudu_inst_t *inst = getCxt(0); + if (!inst) + return -1; // means no F1 + return inst->gtpInst; +} + +static int drb_gtpu_create(instance_t instance, + uint32_t ue_id, + int incoming_id, + int outgoing_id, + int qfi, + in_addr_t tlAddress, // only IPv4 now + teid_t outgoing_teid, + gtpCallback callBack, + gtpCallbackSDAP callBackSDAP, + gtpv1u_gnb_create_tunnel_resp_t *create_tunnel_resp) +{ + gtpv1u_gnb_create_tunnel_req_t create_tunnel_req = {0}; + create_tunnel_req.incoming_rb_id[0] = incoming_id; + create_tunnel_req.pdusession_id[0] = outgoing_id; + memcpy(&create_tunnel_req.dst_addr[0].buffer, &tlAddress, sizeof(uint8_t) * 4); + create_tunnel_req.dst_addr[0].length = 32; + create_tunnel_req.outgoing_teid[0] = outgoing_teid; + create_tunnel_req.outgoing_qfi[0] = qfi; + create_tunnel_req.num_tunnels = 1; + create_tunnel_req.ue_id = ue_id; + + // we use gtpv1u_create_ngu_tunnel because it returns the interface + // address and port of the interface; apart from that, we also might call + // newGtpuCreateTunnel() directly + return gtpv1u_create_ngu_tunnel(instance, &create_tunnel_req, create_tunnel_resp, callBack, callBackSDAP); +} + +bool DURecvCb(protocol_ctxt_t *ctxt_pP, + const srb_flag_t srb_flagP, + const rb_id_t rb_idP, + const mui_t muiP, + const confirm_t confirmP, + const sdu_size_t sdu_buffer_sizeP, + unsigned char *const sdu_buffer_pP, + const pdcp_transmission_mode_t modeP, + const uint32_t *sourceL2Id, + const uint32_t *destinationL2Id) +{ + // The buffer comes from the stack in gtp-u thread, we have a make a separate buffer to enqueue in a inter-thread message queue + uint8_t *sdu = malloc16(sdu_buffer_sizeP); + memcpy(sdu, sdu_buffer_pP, sdu_buffer_sizeP); + du_rlc_data_req(ctxt_pP, srb_flagP, false, rb_idP, muiP, confirmP, sdu_buffer_sizeP, sdu); + return true; +} + static long get_lcid_from_drbid(int drb_id) { return drb_id + 3; /* LCID is DRB + 3 */ @@ -133,6 +189,7 @@ static int handle_ue_context_drbs_setup(int rnti, NR_CellGroupConfig_t *cellGroupConfig) { DevAssert(req_drbs != NULL && resp_drbs != NULL && cellGroupConfig != NULL); + instance_t f1inst = get_f1_gtp_instance(); /* Note: the actual GTP tunnels are created in the F1AP breanch of * ue_context_*_response() */ @@ -140,12 +197,32 @@ static int handle_ue_context_drbs_setup(int rnti, AssertFatal(*resp_drbs != NULL, "out of memory\n"); for (int i = 0; i < drbs_len; i++) { const f1ap_drb_to_be_setup_t *drb = &req_drbs[i]; + f1ap_drb_to_be_setup_t *resp_drb = &(*resp_drbs)[i]; NR_RLC_BearerConfig_t *rlc_BearerConfig = get_bearerconfig_from_drb(drb); nr_rlc_add_drb(rnti, drb->drb_id, rlc_BearerConfig); - (*resp_drbs)[i] = *drb; + *resp_drb = *drb; // just put same number of tunnels in DL as in UL - (*resp_drbs)[i].up_dl_tnl_length = drb->up_ul_tnl_length; + DevAssert(drb->up_ul_tnl_length == 1); + resp_drb->up_dl_tnl_length = drb->up_ul_tnl_length; + + if (f1inst >= 0) { // we actually use F1-U + int qfi = -1; // don't put PDU session marker in GTP + gtpv1u_gnb_create_tunnel_resp_t resp_f1 = {0}; + int ret = drb_gtpu_create(f1inst, + rnti, + drb->drb_id, + drb->drb_id, + qfi, + drb->up_ul_tnl[0].tl_address, + drb->up_ul_tnl[0].teid, + DURecvCb, + NULL, + &resp_f1); + AssertFatal(ret >= 0, "Unable to create GTP Tunnel for F1-U\n"); + memcpy(&resp_drb->up_dl_tnl[0].tl_address, &resp_f1.gnb_addr.buffer, 4); + resp_drb->up_dl_tnl[0].teid = resp_f1.gnb_NGu_teid[0]; + } int ret = ASN_SEQUENCE_ADD(&cellGroupConfig->rlc_BearerToAddModList->list, rlc_BearerConfig); DevAssert(ret == 0); @@ -159,6 +236,7 @@ static int handle_ue_context_drbs_release(int rnti, NR_CellGroupConfig_t *cellGroupConfig) { DevAssert(req_drbs != NULL && cellGroupConfig != NULL); + instance_t f1inst = get_f1_gtp_instance(); cellGroupConfig->rlc_BearerToReleaseList = calloc(1, sizeof(*cellGroupConfig->rlc_BearerToReleaseList)); AssertFatal(cellGroupConfig->rlc_BearerToReleaseList != NULL, "out of memory\n"); @@ -178,6 +256,8 @@ static int handle_ue_context_drbs_release(int rnti, } if (idx < cellGroupConfig->rlc_BearerToAddModList->list.count) { nr_rlc_release_entity(rnti, lcid); + if (f1inst >= 0) + newGtpuDeleteOneTunnel(f1inst, rnti, drb->rb_id); asn_sequence_del(&cellGroupConfig->rlc_BearerToAddModList->list, idx, 1); long *plcid = malloc(sizeof(*plcid)); AssertFatal(plcid != NULL, "out of memory\n"); @@ -557,6 +637,10 @@ void ue_context_release_command(const f1ap_ue_context_release_cmd_t *cmd) return; } + instance_t f1inst = get_f1_gtp_instance(); + if (f1inst >= 0) + newGtpuDeleteAllTunnels(f1inst, cmd->gNB_DU_ue_id); + if (UE->UE_sched_ctrl.ul_failure || cmd->rrc_container_length == 0) { /* The UE is already not connected anymore or we have nothing to forward*/ nr_mac_release_ue(mac, cmd->gNB_DU_ue_id);