Commit 2676e9a5 authored by Robert Schmidt's avatar Robert Schmidt

Merge remote-tracking branch 'origin/bearer-release' into integration_2023_w39

parents e1976711 c6e9992e
......@@ -59,8 +59,13 @@ add_library(telnetsrv_ci MODULE telnetsrv_ci.c)
target_link_libraries(telnetsrv_ci PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
add_dependencies(telnetsrv telnetsrv_ci)
message(STATUS "Add bearer specific telnet functions in libtelnetsrv_bearer.so")
add_library(telnetsrv_bearer MODULE telnetsrv_bearer.c)
target_link_libraries(telnetsrv_bearer PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
add_dependencies(telnetsrv telnetsrv_bearer)
# all libraries should be written to root build dir
set_target_properties(telnetsrv telnetsrv_enb telnetsrv_5Gue telnetsrv_ci
set_target_properties(telnetsrv telnetsrv_enb telnetsrv_5Gue telnetsrv_ci telnetsrv_bearer
PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../../..
)
/*
* 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
*/
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "openair2/RRC/NR/rrc_gNB_UE_context.h"
#define TELNETSERVERCODE
#include "telnetsrv.h"
#define ERROR_MSG_RET(mSG, aRGS...) do { prnt(mSG, ##aRGS); return 1; } while (0)
static int get_single_ue_rnti(void)
{
rrc_gNB_ue_context_t *ue_context_p = NULL;
RB_FOREACH(ue_context_p, rrc_nr_ue_tree_s, &(RC.nrrrc[0]->rrc_ue_head)) {
return ue_context_p->ue_context.rnti;
}
return -1;
}
int get_single_rnti(char *buf, int debug, telnet_printfunc_t prnt)
{
if (buf)
ERROR_MSG_RET("no parameter allowed\n");
int rnti = get_single_ue_rnti();
if (rnti < 1)
ERROR_MSG_RET("different number of UEs\n");
prnt("single UE RNTI %04x\n", rnti);
return 0;
}
void rrc_gNB_trigger_new_bearer(int rnti);
int add_bearer(char *buf, int debug, telnet_printfunc_t prnt)
{
int rnti = -1;
if (!buf) {
rnti = get_single_ue_rnti();
if (rnti < 1)
ERROR_MSG_RET("no UE found\n");
} else {
rnti = strtol(buf, NULL, 16);
if (rnti < 1 || rnti >= 0xfffe)
ERROR_MSG_RET("RNTI needs to be [1,0xfffe]\n");
}
// verify it exists in RRC as well
rrc_gNB_ue_context_t *rrcue = rrc_gNB_get_ue_context_by_rnti(RC.nrrrc[0], rnti);
if (!rrcue)
ERROR_MSG_RET("could not find UE with RNTI %04x\n", rnti);
rrc_gNB_trigger_new_bearer(rnti);
prnt("called rrc_gNB_trigger_new_bearer(%04x)\n", rnti);
return 0;
}
void rrc_gNB_trigger_release_bearer(int rnti);
int release_bearer(char *buf, int debug, telnet_printfunc_t prnt)
{
int rnti = -1;
if (!buf) {
rnti = get_single_ue_rnti();
if (rnti < 1)
ERROR_MSG_RET("no UE found\n");
} else {
rnti = strtol(buf, NULL, 16);
if (rnti < 1 || rnti >= 0xfffe)
ERROR_MSG_RET("RNTI needs to be [1,0xfffe]\n");
}
// verify it exists in RRC as well
rrc_gNB_ue_context_t *rrcue = rrc_gNB_get_ue_context_by_rnti(RC.nrrrc[0], rnti);
if (!rrcue)
ERROR_MSG_RET("could not find UE with RNTI %04x\n", rnti);
rrc_gNB_trigger_release_bearer(rnti);
prnt("called rrc_gNB_trigger_release_bearer(%04x)\n", rnti);
return 0;
}
static telnetshell_cmddef_t bearercmds[] = {
{"get_single_rnti", "", get_single_rnti},
{"add_bearer", "[rnti(hex,opt)]", add_bearer},
{"release_bearer", "[rnti(hex,opt)]", release_bearer},
{"", "", NULL},
};
static telnetshell_vardef_t bearervars[] = {
{"", 0, 0, NULL}
};
void add_bearer_cmds(void) {
add_telnetcmd("bearer", bearervars, bearercmds);
}
......@@ -301,6 +301,10 @@ typedef struct f1ap_rb_failed_to_be_setup_s {
long rb_id;
} f1ap_rb_failed_to_be_setup_t;
typedef struct f1ap_drb_to_be_released_t {
long rb_id;
} f1ap_drb_to_be_released_t;
typedef struct cu_to_du_rrc_information_s {
uint8_t * cG_ConfigInfo;
uint32_t cG_ConfigInfo_length;
......@@ -354,6 +358,8 @@ typedef struct f1ap_ue_context_setup_s {
f1ap_srb_to_be_setup_t *srbs_to_be_setup;
uint8_t srbs_to_be_setup_length;
uint8_t srbs_failed_to_be_setup_length;
uint8_t drbs_to_be_released_length;
f1ap_drb_to_be_released_t *drbs_to_be_released;
f1ap_rb_failed_to_be_setup_t *srbs_failed_to_be_setup;
ReconfigurationCompl_t ReconfigComplOutcome;
uint8_t *rrc_container;
......
......@@ -1531,14 +1531,14 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, f1ap_ue_context
}
/* optional */
if(0){
if (f1ap_ue_context_modification_req->drbs_to_be_released_length > 0) {
/* c15. DRBs_ToBeReleased_List */
asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie15);
ie15->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_List;
ie15->criticality = F1AP_Criticality_reject;
ie15->value.present = F1AP_UEContextModificationRequestIEs__value_PR_DRBs_ToBeReleased_List;
for (int i=0; i<1; i++) {
for (int i = 0; i < f1ap_ue_context_modification_req->drbs_to_be_released_length; i++) {
//
asn1cSequenceAdd(ie15->value.choice.DRBs_ToBeReleased_List.list,
F1AP_DRBs_ToBeReleased_ItemIEs_t, drbs_toBeReleased_item_ies);
......@@ -1549,7 +1549,10 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, f1ap_ue_context
F1AP_DRBs_ToBeReleased_Item_t *drbs_toBeReleased_item=
&drbs_toBeReleased_item_ies->value.choice.DRBs_ToBeReleased_Item;
/* dRBID */
drbs_toBeReleased_item->dRBID = 30L;
drbs_toBeReleased_item->dRBID = f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id;
newGtpuDeleteOneTunnel(getCxt(instance)->gtpInst,
f1ap_ue_context_modification_req->gNB_CU_ue_id,
f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id);
}
}
......
......@@ -881,6 +881,24 @@ int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, sctp_assoc_t
}
}
}
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieDrb, container,
F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_List, false);
if (ieDrb != NULL) {
f1ap_ue_context_modification_req->drbs_to_be_released_length = ieDrb->value.choice.DRBs_ToBeReleased_List.list.count;
f1ap_ue_context_modification_req->drbs_to_be_released =
calloc(f1ap_ue_context_modification_req->drbs_to_be_released_length, sizeof(f1ap_drb_to_be_released_t));
AssertFatal(f1ap_ue_context_modification_req->drbs_to_be_released,
"could not allocate memory for f1ap_ue_context_released_req->drbs_to_be_released\n");
for (i = 0; i < f1ap_ue_context_modification_req->drbs_to_be_released_length; ++i) {
F1AP_DRBs_ToBeReleased_ItemIEs_t *tbrel = (F1AP_DRBs_ToBeReleased_ItemIEs_t *)ieDrb->value.choice.DRBs_ToBeReleased_List.list.array[i];
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);
}
}
/* RRC Reconfiguration Complete indicator */
F1AP_UEContextModificationRequestIEs_t *ieReconf;
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieReconf, container,
......
......@@ -2750,6 +2750,14 @@ static void nr_mac_apply_cellgroup(gNB_MAC_INST *mac, NR_UE_info_t *UE, frame_t
if (LOG_DEBUGFLAG(DEBUG_ASN1))
xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *)UE->CellGroup);
/* remove the rlc_BearerToReleaseList, we don't need it anymore */
if (UE->CellGroup->rlc_BearerToReleaseList != NULL) {
struct NR_CellGroupConfig__rlc_BearerToReleaseList *l = UE->CellGroup->rlc_BearerToReleaseList;
asn_sequence_del(&l->list, l->list.count, /* free */1);
free(UE->CellGroup->rlc_BearerToReleaseList);
UE->CellGroup->rlc_BearerToReleaseList = NULL;
}
}
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
......
......@@ -138,6 +138,42 @@ static int handle_ue_context_drbs_setup(int rnti,
return drbs_len;
}
static int handle_ue_context_drbs_release(int rnti,
int drbs_len,
const f1ap_drb_to_be_released_t *req_drbs,
NR_CellGroupConfig_t *cellGroupConfig)
{
DevAssert(req_drbs != NULL && cellGroupConfig != NULL);
cellGroupConfig->rlc_BearerToReleaseList = calloc(1, sizeof(*cellGroupConfig->rlc_BearerToReleaseList));
AssertFatal(cellGroupConfig->rlc_BearerToReleaseList != NULL, "out of memory\n");
/* Note: the actual GTP tunnels are already removed in the F1AP message
* decoding */
for (int i = 0; i < drbs_len; i++) {
const f1ap_drb_to_be_released_t *drb = &req_drbs[i];
long lcid = drb->rb_id + 3; /* LCID is DRB + 3 */
int idx = 0;
while (idx < cellGroupConfig->rlc_BearerToAddModList->list.count) {
const NR_RLC_BearerConfig_t *bc = cellGroupConfig->rlc_BearerToAddModList->list.array[idx];
if (bc->logicalChannelIdentity == lcid)
break;
++idx;
}
if (idx < cellGroupConfig->rlc_BearerToAddModList->list.count) {
nr_rlc_release_entity(rnti, lcid);
asn_sequence_del(&cellGroupConfig->rlc_BearerToAddModList->list, idx, 1);
long *plcid = malloc(sizeof(*plcid));
AssertFatal(plcid != NULL, "out of memory\n");
*plcid = lcid;
int ret = ASN_SEQUENCE_ADD(&cellGroupConfig->rlc_BearerToReleaseList->list, plcid);
DevAssert(ret == 0);
}
}
return drbs_len;
}
static NR_UE_NR_Capability_t *get_ue_nr_cap(int rnti, uint8_t *buf, uint32_t len)
{
if (buf == NULL || len == 0)
......@@ -287,6 +323,11 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req)
NR_SCHED_LOCK(&mac->sched_lock);
NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[0]->UE_info, req->gNB_DU_ue_id);
if (!UE) {
LOG_E(NR_MAC, "could not find UE with RNTI %04x\n", req->gNB_DU_ue_id);
NR_SCHED_UNLOCK(&mac->sched_lock);
return;
}
NR_CellGroupConfig_t *new_CellGroup = clone_CellGroupConfig(UE->CellGroup);
......@@ -306,6 +347,11 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req)
new_CellGroup);
}
if (req->drbs_to_be_released_length > 0) {
resp.drbs_to_be_released_length =
handle_ue_context_drbs_release(req->gNB_DU_ue_id, req->drbs_to_be_released_length, req->drbs_to_be_released, new_CellGroup);
}
if (req->rrc_container != NULL)
nr_rlc_srb_recv_sdu(req->gNB_DU_ue_id, DCCH, req->rrc_container, req->rrc_container_length);
......@@ -323,7 +369,7 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req)
update_cellGroupConfig(new_CellGroup, UE->uid, UE->capability, &mac->radio_config, scc);
}
if (req->srbs_to_be_setup_length > 0 || req->drbs_to_be_setup_length > 0 || ue_cap != NULL) {
if (req->srbs_to_be_setup_length > 0 || req->drbs_to_be_setup_length > 0 || req->drbs_to_be_released_length > 0) {
resp.du_to_cu_rrc_information = calloc(1, sizeof(du_to_cu_rrc_information_t));
AssertFatal(resp.du_to_cu_rrc_information != NULL, "out of memory\n");
resp.du_to_cu_rrc_information->cellGroupConfig = calloc(1, 1024);
......
......@@ -166,21 +166,15 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset
UE->rnti,
stats->ulsch_total_bytes_scheduled, stats->ul.total_bytes);
for (int lc_id = 0; lc_id < 63; lc_id++) {
if (stats->dl.lc_bytes[lc_id] > 0)
output += snprintf(output,
end - output,
"UE %04x: LCID %d: %"PRIu64" bytes TX\n",
UE->rnti,
lc_id,
stats->dl.lc_bytes[lc_id]);
if (stats->ul.lc_bytes[lc_id] > 0)
output += snprintf(output,
end - output,
"UE %04x: LCID %d: %"PRIu64" bytes RX\n",
UE->rnti,
lc_id,
stats->ul.lc_bytes[lc_id]);
for (int i = 0; i < sched_ctrl->dl_lc_num; i++) {
int lc_id = sched_ctrl->dl_lc_ids[i];
output += snprintf(output,
end - output,
"UE %04x: LCID %d: TX %14"PRIu64" RX %14"PRIu64" bytes\n",
UE->rnti,
lc_id,
stats->dl.lc_bytes[lc_id],
stats->ul.lc_bytes[lc_id]);
}
}
NR_SCHED_UNLOCK(&gNB->UE_info.mutex);
......
......@@ -1081,7 +1081,7 @@ void nr_pdcp_reconfigure_drb(ue_id_t ue_id, int drb_id, long t_Reordering)
nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
}
void nr_release_srb(ue_id_t ue_id, int srb_id)
void nr_pdcp_release_srb(ue_id_t ue_id, int srb_id)
{
nr_pdcp_manager_lock(nr_pdcp_ue_manager);
nr_pdcp_ue_t *ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id);
......@@ -1094,7 +1094,7 @@ void nr_release_srb(ue_id_t ue_id, int srb_id)
nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
}
void nr_release_drb(ue_id_t ue_id, int drb_id)
void nr_pdcp_release_drb(ue_id_t ue_id, int drb_id)
{
nr_pdcp_manager_lock(nr_pdcp_ue_manager);
nr_pdcp_ue_t *ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id);
......
......@@ -68,8 +68,8 @@ void nr_pdcp_reestablishment(ue_id_t ue_id);
void nr_pdcp_reconfigure_srb(ue_id_t ue_id, int srb_id, long t_Reordering);
void nr_pdcp_reconfigure_drb(ue_id_t ue_id, int drb_id, long t_Reordering);
void nr_release_srb(ue_id_t ue_id, int srb_id);
void nr_release_drb(ue_id_t ue_id, int drb_id);
void nr_pdcp_release_srb(ue_id_t ue_id, int srb_id);
void nr_pdcp_release_drb(ue_id_t ue_id, int drb_id);
void add_srb(int is_gnb,
ue_id_t rntiMaybeUEid,
......
......@@ -100,7 +100,7 @@ static nr_rlc_entity_t *get_rlc_entity_from_lcid(nr_rlc_ue_t *ue, logical_chan_i
}
}
void nr_release_rlc_entity(int rnti, logical_chan_id_t channel_id)
void nr_rlc_release_entity(int rnti, logical_chan_id_t channel_id)
{
nr_rlc_manager_lock(nr_rlc_ue_manager);
nr_rlc_ue_t *ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, rnti);
......
......@@ -51,7 +51,7 @@ bool nr_rlc_update_rnti(int from_rnti, int to_rnti);
/* test function for CI to trigger reestablishments */
void nr_rlc_test_trigger_reestablishment(int rnti);
void nr_release_rlc_entity(int rnti, logical_chan_id_t channel_id);
void nr_rlc_release_entity(int rnti, logical_chan_id_t channel_id);
void nr_rlc_reconfigure_entity(int rnti, int lc_id, struct NR_RLC_Config *rlc_Config, struct NR_LogicalChannelConfig *lc_Config);
......
......@@ -94,6 +94,13 @@ static void ue_context_modification_request_f1ap(const f1ap_ue_context_modif_req
AssertFatal(f1ap_msg->srbs_to_be_setup != NULL, "out of memory\n");
memcpy(f1ap_msg->srbs_to_be_setup, req->srbs_to_be_setup, n * sizeof(*f1ap_msg->srbs_to_be_setup));
}
if (req->drbs_to_be_released_length > 0) {
int n = req->drbs_to_be_released_length;
f1ap_msg->drbs_to_be_released_length = n;
f1ap_msg->drbs_to_be_released = calloc(n, sizeof(*f1ap_msg->drbs_to_be_released));
AssertFatal(f1ap_msg->drbs_to_be_released != NULL, "out of memory\n");
memcpy(f1ap_msg->drbs_to_be_released, req->drbs_to_be_released, n * sizeof(*f1ap_msg->drbs_to_be_released));
}
if (req->rrc_container_length > 0) {
f1ap_msg->rrc_container = calloc(req->rrc_container_length, sizeof(*f1ap_msg->rrc_container));
AssertFatal(f1ap_msg->rrc_container != NULL, "out of memory\n");
......
......@@ -238,6 +238,7 @@ typedef enum {
typedef struct gNB_RRC_UE_s {
drb_t established_drbs[MAX_DRBS_PER_UE];
uint8_t DRB_active[MAX_DRBS_PER_UE];
NR_DRB_ToReleaseList_t *DRB_ReleaseList;
NR_SRB_INFO_TABLE_ENTRY Srb[maxSRBs]; // 3gpp max is 3 SRBs, number 1..3, we waste the entry 0 for code simplicity
NR_MeasConfig_t *measConfig;
......
......@@ -46,6 +46,7 @@
#include "LAYER2/NR_MAC_gNB/mac_proto.h"
#include "common/utils/LOG/log.h"
#include "RRC/NR/MESSAGES/asn1_msg.h"
#include "openair2/E1AP/e1ap_asnc.h"
#include "NR_BCCH-BCH-Message.h"
#include "NR_UL-DCCH-Message.h"
......@@ -672,7 +673,7 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c
xid,
SRBs,
DRBs,
NULL,
ue_p->DRB_ReleaseList,
NULL,
NULL,
dedicatedNAS_MessageList,
......@@ -680,6 +681,9 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c
LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)buffer,size,"[MSG] RRC Reconfiguration\n");
freeSRBlist(SRBs);
freeDRBlist(DRBs);
ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToReleaseList, ue_p->DRB_ReleaseList);
ue_p->DRB_ReleaseList = NULL;
LOG_I(NR_RRC, "[gNB %d] Frame %d, Logical Channel DL-DCCH, Generate RRCReconfiguration (bytes %d, UE RNTI %x)\n", ctxt_pP->module_id, ctxt_pP->frame, size, ue_p->rnti);
LOG_D(NR_RRC,
"[FRAME %05d][RRC_gNB][MOD %u][][--- PDCP_DATA_REQ/%d Bytes (rrcReconfiguration to UE %x MUI %d) --->][PDCP][MOD %u][RB %u]\n",
......@@ -2855,6 +2859,147 @@ rrc_gNB_generate_RRCRelease(
/* UE will be freed after UE context release complete */
}
void rrc_gNB_trigger_new_bearer(int rnti)
{
/* get RRC and UE */
gNB_RRC_INST *rrc = RC.nrrrc[0];
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_by_rnti(rrc, rnti);
if (ue_context_p == NULL) {
LOG_E(RRC, "unknown UE RNTI %04x\n", rnti);
return;
}
gNB_RRC_UE_t *ue = &ue_context_p->ue_context;
/* get the existing PDU sessoin */
if (ue->nb_of_pdusessions < 1) {
LOG_E(RRC, "no PDU session set up yet, cannot create additional bearer\n");
return;
}
if (ue->established_drbs[0].status != DRB_INACTIVE
&& ue->established_drbs[1].status != DRB_INACTIVE) {
LOG_E(RRC, "already have two established bearers, aborting\n");
return;
}
e1ap_bearer_setup_req_t bearer_req = {0};
bearer_req.gNB_cu_cp_ue_id = ue->rrc_ue_id;
bearer_req.cipheringAlgorithm = ue->ciphering_algorithm;
memcpy(bearer_req.encryptionKey, ue->kgnb, sizeof(ue->kgnb));
bearer_req.integrityProtectionAlgorithm = ue->integrity_algorithm;
memcpy(bearer_req.integrityProtectionKey, ue->kgnb, sizeof(ue->kgnb));
bearer_req.ueDlAggMaxBitRate = 10000; /* probably does not matter */
pdu_session_to_setup_t *pdu = &bearer_req.pduSession[0];
//bearer_req.numPDUSessions++;
bearer_req.numPDUSessions = 1;
//pdu->sessionId = session->pdusession_id;
//pdu->sst = msg->allowed_nssai[i].sST;
//pdu->integrityProtectionIndication = rrc->security.do_drb_integrity ? E1AP_IntegrityProtectionIndication_required : E1AP_IntegrityProtectionIndication_not_needed;
//pdu->confidentialityProtectionIndication = rrc->security.do_drb_ciphering ? E1AP_ConfidentialityProtectionIndication_required : E1AP_ConfidentialityProtectionIndication_not_needed;
//pdu->teId = session->gtp_teid;
pdu->numDRB2Setup = 1; // One DRB per PDU Session. TODO: Remove hardcoding
DRB_nGRAN_to_setup_t *drb = &pdu->DRBnGRanList[0];
int drb_id = 2;
drb->id = drb_id;
drb->defaultDRB = E1AP_DefaultDRB_false;
drb->sDAP_Header_UL = !(rrc->configuration.enable_sdap);
drb->sDAP_Header_DL = !(rrc->configuration.enable_sdap);
drb->pDCP_SN_Size_UL = E1AP_PDCP_SN_Size_s_18;
drb->pDCP_SN_Size_DL = E1AP_PDCP_SN_Size_s_18;
drb->discardTimer = E1AP_DiscardTimer_infinity;
drb->reorderingTimer = E1AP_T_Reordering_ms0;
drb->rLC_Mode = E1AP_RLC_Mode_rlc_am;
drb->numCellGroups = 1; // assume one cell group associated with a DRB
for (int k=0; k < drb->numCellGroups; k++) {
cell_group_t *cellGroup = drb->cellGroupList + k;
cellGroup->id = 0; // MCG
}
int xid = rrc_gNB_get_next_transaction_identifier(0);
/* generate a new bearer, it will be put into internal RRC state and picked
* up later */
generateDRB(ue,
drb_id,
&ue->pduSession[0],
rrc->configuration.enable_sdap,
rrc->security.do_drb_integrity,
rrc->security.do_drb_ciphering);
/* associate the new bearer to it */
ue->xids[xid] = RRC_PDUSESSION_MODIFY;
ue->pduSession[0].xid = xid; // hack: fake xid for ongoing PDU session
LOG_W(RRC, "trigger new bearer %ld for UE %04x xid %d\n", drb->id, ue->rnti, xid);
rrc->cucp_cuup.bearer_context_setup(&bearer_req, 0);
}
void rrc_gNB_trigger_release_bearer(int rnti)
{
/* get RRC and UE */
gNB_RRC_INST *rrc = RC.nrrrc[0];
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_by_rnti(rrc, rnti);
if (ue_context_p == NULL) {
LOG_E(RRC, "unknown UE RNTI %04x\n", rnti);
return;
}
gNB_RRC_UE_t *ue = &ue_context_p->ue_context;
if (ue->established_drbs[1].status == DRB_INACTIVE) {
LOG_E(RRC, "no second bearer, aborting\n");
return;
}
// don't use E1: bearer release is not implemented, call directly
// into PDCP/SDAP and then send corresponding message via F1
int drb_id = 2;
ue->established_drbs[1].status = DRB_INACTIVE;
ue->DRB_ReleaseList = calloc(1, sizeof(*ue->DRB_ReleaseList));
AssertFatal(ue->DRB_ReleaseList != NULL, "out of memory\n");
NR_DRB_Identity_t *asn1_drb = malloc(sizeof(*asn1_drb));
AssertFatal(asn1_drb != NULL, "out of memory\n");
int idx = 0;
NR_DRB_ToAddModList_t *drb_list = createDRBlist(ue, false);
while (idx < drb_list->list.count) {
const NR_DRB_ToAddMod_t *drbc = drb_list->list.array[idx];
if (drbc->drb_Identity == drb_id)
break;
++idx;
}
if (idx < drb_list->list.count) {
nr_pdcp_release_drb(rnti, drb_id);
asn_sequence_del(&drb_list->list, idx, 1);
}
*asn1_drb = drb_id;
asn1cSeqAdd(&ue->DRB_ReleaseList->list, asn1_drb);
f1ap_drb_to_be_released_t drbs_to_be_released[1] = {{.rb_id = drb_id}};
f1_ue_data_t ue_data = cu_get_f1_ue_data(ue->rrc_ue_id);
f1ap_ue_context_modif_req_t ue_context_modif_req = {
.gNB_CU_ue_id = ue->rrc_ue_id,
.gNB_DU_ue_id = ue_data.secondary_ue,
.plmn.mcc = rrc->configuration.mcc[0],
.plmn.mnc = rrc->configuration.mnc[0],
.plmn.mnc_digit_length = rrc->configuration.mnc_digit_length[0],
.nr_cellid = rrc->nr_cellid,
.servCellId = 0, /* TODO: correct value? */
.srbs_to_be_setup_length = 0,
.srbs_to_be_setup = NULL,
.drbs_to_be_setup_length = 0,
.drbs_to_be_setup = NULL,
.drbs_to_be_released_length = 1,
.drbs_to_be_released = drbs_to_be_released,
};
rrc->mac_rrc.ue_context_modification_request(&ue_context_modif_req);
}
int rrc_gNB_generate_pcch_msg(uint32_t tmsi, uint8_t paging_drx, instance_t instance, uint8_t CC_id){
const unsigned int Ttab[4] = {32,64,128,256};
uint8_t Tc;
......
......@@ -759,7 +759,7 @@ void nr_rrc_manage_rlc_bearers(const NR_CellGroupConfig_t *cellGroupConfig,
for (int i = 0; i < cellGroupConfig->rlc_BearerToReleaseList->list.count; i++) {
NR_LogicalChannelIdentity_t *lcid = cellGroupConfig->rlc_BearerToReleaseList->list.array[i];
AssertFatal(lcid, "LogicalChannelIdentity shouldn't be null here\n");
nr_release_rlc_entity(rnti, *lcid);
nr_rlc_release_entity(rnti, *lcid);
}
}
......@@ -1460,7 +1460,7 @@ void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB
NR_UE_RRC_INST_t *ue_rrc = &NR_UE_rrc_inst[ctxt_pP->module_id];
if (radioBearerConfig->srb3_ToRelease)
nr_release_srb(ctxt_pP->rntiMaybeUEid, 3);
nr_pdcp_release_srb(ctxt_pP->rntiMaybeUEid, 3);
uint8_t kRRCenc[16] = {0};
uint8_t kRRCint[16] = {0};
......@@ -1514,7 +1514,7 @@ void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB
for (int cnt = 0; cnt < radioBearerConfig->drb_ToReleaseList->list.count; cnt++) {
NR_DRB_Identity_t *DRB_id = radioBearerConfig->drb_ToReleaseList->list.array[cnt];
if (DRB_id)
nr_release_drb(ctxt_pP->rntiMaybeUEid, *DRB_id);
nr_pdcp_release_drb(ctxt_pP->rntiMaybeUEid, *DRB_id);
}
}
......
......@@ -803,6 +803,32 @@ int gtpv1u_create_x2u_tunnel(
AssertFatal( false, "to be developped\n");
}
int newGtpuDeleteOneTunnel(instance_t instance, ue_id_t ue_id, int rb_id)
{
pthread_mutex_lock(&globGtp.gtp_lock);
getInstRetInt(compatInst(instance));
map<uint64_t, teidData_t>::iterator ue_it = inst->ue2te_mapping.find(ue_id);
if (ue_it == inst->ue2te_mapping.end()) {
LOG_E(GTPU, "%s() no such UE %ld\n", __func__, ue_id);
pthread_mutex_unlock(&globGtp.gtp_lock);
return !GTPNOK;
}
map<ue_id_t, gtpv1u_bearer_t>::iterator rb_it = ue_it->second.bearers.find(rb_id);
if (rb_it == ue_it->second.bearers.end()) {
LOG_E(GTPU, "%s() UE %ld has no bearer %d, available\n", __func__, ue_id, rb_id);
pthread_mutex_unlock(&globGtp.gtp_lock);
return !GTPNOK;
}
int teid = rb_it->second.teid_incoming;
globGtp.te2ue_mapping.erase(teid);
ue_it->second.bearers.erase(rb_id);
pthread_mutex_unlock(&globGtp.gtp_lock);
LOG_I(GTPU, "Deleted tunnel TEID %d (RB %d) for ue id %ld, remaining bearers:\n", teid, rb_id, ue_id);
for (auto b: ue_it->second.bearers)
LOG_I(GTPU, "bearer %ld\n", b.first);
return !GTPNOK;
}
int newGtpuDeleteAllTunnels(instance_t instance, ue_id_t ue_id) {
LOG_D(GTPU, "[%ld] Start delete tunnels for ue id %lu\n",
instance, ue_id);
......
......@@ -98,6 +98,7 @@ extern "C" {
in_addr_t newOutgoingAddr,
teid_t newOutgoingTeid);
int newGtpuDeleteOneTunnel(instance_t instance, ue_id_t ue_id, int rb_id);
int newGtpuDeleteAllTunnels(instance_t instance, ue_id_t ue_id);
int newGtpuDeleteTunnels(instance_t instance, ue_id_t ue_id, int nbTunnels, pdusessionid_t *pdusession_id);
instance_t gtpv1Init(openAddr_t context);
......
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