This reverts commit 0f100a6e94, which
introduced a hack to possibly wait with a PDU session setup at the RRC
in case a RRC UE capability transaction (requesting UE capabilities from
a UE) was ongoing. This happened, as we delayed the UE capabilities to
after the first RRC reconfiguration; in that case, certain UEs were
requesting the next PDU session, and if RRC did not delay the new PDU
session (as requested from the core), this procedure might occur while
UE capability enquiry was ongoing, leading to failures in these
transactions.
215 lines
8.1 KiB
C
215 lines
8.1 KiB
C
/*
|
|
* 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_UE_context.h
|
|
* \brief rrc procedures for UE context
|
|
* \author Lionel GAUTHIER
|
|
* \date 2015
|
|
* \version 1.0
|
|
* \company Eurecom
|
|
* \email: lionel.gauthier@eurecom.fr
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <limits.h>
|
|
#include <time.h>
|
|
|
|
#include "common/utils/LOG/log.h"
|
|
#include "rrc_gNB_UE_context.h"
|
|
#include "openair2/F1AP/f1ap_ids.h"
|
|
|
|
static void rrc_gNB_ue_context_update_time(rrc_gNB_ue_context_t *ctxt)
|
|
{
|
|
ctxt->ue_context.last_seen = time(NULL);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
int rrc_gNB_compare_ue_rnti_id(rrc_gNB_ue_context_t *c1_pP, rrc_gNB_ue_context_t *c2_pP)
|
|
//------------------------------------------------------------------------------
|
|
{
|
|
if (c1_pP->ue_context.rrc_ue_id > c2_pP->ue_context.rrc_ue_id) {
|
|
return 1;
|
|
}
|
|
|
|
if (c1_pP->ue_context.rrc_ue_id < c2_pP->ue_context.rrc_ue_id) {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Generate the tree management functions */
|
|
RB_GENERATE(rrc_nr_ue_tree_s, rrc_gNB_ue_context_s, entries,
|
|
rrc_gNB_compare_ue_rnti_id);
|
|
|
|
//------------------------------------------------------------------------------
|
|
rrc_gNB_ue_context_t *rrc_gNB_allocate_new_ue_context(gNB_RRC_INST *rrc_instance_pP)
|
|
//------------------------------------------------------------------------------
|
|
{
|
|
rrc_gNB_ue_context_t *new_p = calloc(1, sizeof(*new_p));
|
|
|
|
if (new_p == NULL) {
|
|
LOG_E(NR_RRC, "Cannot allocate new ue context\n");
|
|
return NULL;
|
|
}
|
|
new_p->ue_context.rrc_ue_id = uid_linear_allocator_new(&rrc_instance_pP->uid_allocator) + 1;
|
|
rrc_gNB_ue_context_update_time(new_p);
|
|
|
|
for(int i = 0; i < NB_RB_MAX; i++)
|
|
new_p->ue_context.pduSession[i].xid = -1;
|
|
|
|
LOG_D(NR_RRC, "Returning new RRC UE context RRC ue id: %d\n", new_p->ue_context.rrc_ue_id);
|
|
return(new_p);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
rrc_gNB_ue_context_t *rrc_gNB_get_ue_context(gNB_RRC_INST *rrc_instance_pP, ue_id_t ue)
|
|
//------------------------------------------------------------------------------
|
|
{
|
|
rrc_gNB_ue_context_t temp;
|
|
/* gNB ue rrc id = 24 bits wide */
|
|
temp.ue_context.rrc_ue_id = ue;
|
|
return RB_FIND(rrc_nr_ue_tree_s, &rrc_instance_pP->rrc_ue_head, &temp);
|
|
}
|
|
|
|
rrc_gNB_ue_context_t *rrc_gNB_get_ue_context_by_rnti(gNB_RRC_INST *rrc_instance_pP, sctp_assoc_t assoc_id, rnti_t rntiP)
|
|
{
|
|
rrc_gNB_ue_context_t *ue_context_p;
|
|
RB_FOREACH(ue_context_p, rrc_nr_ue_tree_s, &(rrc_instance_pP->rrc_ue_head)) {
|
|
f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_context_p->ue_context.rrc_ue_id);
|
|
if (ue_data.du_assoc_id == assoc_id && ue_context_p->ue_context.rnti == rntiP) {
|
|
rrc_gNB_ue_context_update_time(ue_context_p);
|
|
return ue_context_p;
|
|
}
|
|
}
|
|
LOG_W(NR_RRC, "search by RNTI %04x and assoc_id %d: no UE found\n", rntiP, assoc_id);
|
|
return NULL;
|
|
}
|
|
|
|
rrc_gNB_ue_context_t *rrc_gNB_get_ue_context_by_rnti_any_du(gNB_RRC_INST *rrc_instance_pP, rnti_t rntiP)
|
|
{
|
|
rrc_gNB_ue_context_t *ue_context_p;
|
|
RB_FOREACH(ue_context_p, rrc_nr_ue_tree_s, &(rrc_instance_pP->rrc_ue_head))
|
|
{
|
|
if (ue_context_p->ue_context.rnti == rntiP) {
|
|
rrc_gNB_ue_context_update_time(ue_context_p);
|
|
return ue_context_p;
|
|
}
|
|
}
|
|
LOG_W(NR_RRC, "search by rnti not found %04x\n", rntiP);
|
|
return NULL;
|
|
}
|
|
|
|
void rrc_gNB_free_mem_ue_context(rrc_gNB_ue_context_t *const ue_context_pP)
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
LOG_T(NR_RRC, " Clearing UE context 0x%p (free internal structs)\n", ue_context_pP);
|
|
free(ue_context_pP);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void rrc_gNB_remove_ue_context(gNB_RRC_INST *rrc_instance_pP, rrc_gNB_ue_context_t *ue_context_pP)
|
|
//------------------------------------------------------------------------------
|
|
{
|
|
if (rrc_instance_pP == NULL) {
|
|
LOG_E(NR_RRC, " Bad RRC instance\n");
|
|
return;
|
|
}
|
|
|
|
if (ue_context_pP == NULL) {
|
|
LOG_E(NR_RRC, "Trying to free a NULL UE context\n");
|
|
return;
|
|
}
|
|
|
|
RB_REMOVE(rrc_nr_ue_tree_s, &rrc_instance_pP->rrc_ue_head, ue_context_pP);
|
|
uid_linear_allocator_free(&rrc_instance_pP->uid_allocator, ue_context_pP->ue_context.rrc_ue_id - 1);
|
|
cu_remove_f1_ue_data(ue_context_pP->ue_context.rrc_ue_id);
|
|
rrc_gNB_free_mem_ue_context(ue_context_pP);
|
|
LOG_I(NR_RRC, "Removed UE context\n");
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// return the ue context if there is already an UE with ue_identityP, NULL otherwise
|
|
rrc_gNB_ue_context_t *rrc_gNB_ue_context_random_exist(gNB_RRC_INST *rrc_instance_pP, const uint64_t ue_identityP)
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
rrc_gNB_ue_context_t *ue_context_p = NULL;
|
|
RB_FOREACH(ue_context_p, rrc_nr_ue_tree_s, &rrc_instance_pP->rrc_ue_head) {
|
|
if (ue_context_p->ue_context.random_ue_identity == ue_identityP) {
|
|
rrc_gNB_ue_context_update_time(ue_context_p);
|
|
return ue_context_p;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// return the ue context if there is already an UE with the same S-TMSI, NULL otherwise
|
|
rrc_gNB_ue_context_t *rrc_gNB_ue_context_5g_s_tmsi_exist(gNB_RRC_INST *rrc_instance_pP, const uint64_t s_TMSI)
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
rrc_gNB_ue_context_t *ue_context_p = NULL;
|
|
RB_FOREACH(ue_context_p, rrc_nr_ue_tree_s, &rrc_instance_pP->rrc_ue_head)
|
|
{
|
|
LOG_I(NR_RRC, "Checking for UE 5G S-TMSI %ld: RNTI %04x\n", s_TMSI, ue_context_p->ue_context.rnti);
|
|
if (ue_context_p->ue_context.ng_5G_S_TMSI_Part1 == s_TMSI) {
|
|
rrc_gNB_ue_context_update_time(ue_context_p);
|
|
return ue_context_p;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// return a new ue context structure if ue_identityP, rnti not found in collection
|
|
rrc_gNB_ue_context_t *rrc_gNB_create_ue_context(sctp_assoc_t assoc_id,
|
|
rnti_t rnti,
|
|
gNB_RRC_INST *rrc_instance_pP,
|
|
const uint64_t ue_identityP,
|
|
uint32_t du_ue_id)
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_allocate_new_ue_context(rrc_instance_pP);
|
|
if (ue_context_p == NULL)
|
|
return NULL;
|
|
|
|
gNB_RRC_UE_t *ue = &ue_context_p->ue_context;
|
|
ue->rnti = rnti;
|
|
ue->random_ue_identity = ue_identityP;
|
|
f1_ue_data_t ue_data = {.secondary_ue = du_ue_id, .du_assoc_id = assoc_id};
|
|
AssertFatal(!cu_exists_f1_ue_data(ue->rrc_ue_id),
|
|
"UE F1 Context for ID %d already exists, logic bug\n",
|
|
ue->rrc_ue_id);
|
|
cu_add_f1_ue_data(ue->rrc_ue_id, &ue_data);
|
|
|
|
RB_INSERT(rrc_nr_ue_tree_s, &rrc_instance_pP->rrc_ue_head, ue_context_p);
|
|
LOG_I(NR_RRC,
|
|
"Created new UE context: CU UE ID %u DU UE ID %u (rnti: %04x, random ue id %lx)\n",
|
|
ue->rrc_ue_id,
|
|
du_ue_id,
|
|
ue->rnti,
|
|
ue->random_ue_identity);
|
|
return ue_context_p;
|
|
}
|