/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see .
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/
/*
rlc_rrc.c
-------------------
AUTHOR : Lionel GAUTHIER
COMPANY : EURECOM
EMAIL : Lionel.Gauthier at eurecom dot fr
*/
#define RLC_RRC_C
#include "rlc.h"
#include "rlc_am.h"
#include "rlc_um.h"
#include "rlc_tm.h"
#include "UTIL/LOG/log.h"
#ifdef OAI_EMU
#include "UTIL/OCG/OCG_vars.h"
#endif
#include "RLC-Config.h"
#include "DRB-ToAddMod.h"
#include "DRB-ToAddModList.h"
#include "SRB-ToAddMod.h"
#include "SRB-ToAddModList.h"
#include "DL-UM-RLC.h"
#ifdef Rel10
#include "PMCH-InfoList-r9.h"
#endif
#include "LAYER2/MAC/extern.h"
#include "assertions.h"
//-----------------------------------------------------------------------------
rlc_op_status_t rrc_rlc_config_asn1_req (const module_id_t enb_mod_idP,
const module_id_t ue_mod_idP,
const frame_t frameP,
const eNB_flag_t enb_flagP,
const SRB_ToAddModList_t * const srb2add_listP,
const DRB_ToAddModList_t * const drb2add_listP,
const DRB_ToReleaseList_t * const drb2release_listP
#if defined(Rel10)
,const PMCH_InfoList_r9_t * const pmch_InfoList_r9_pP
#endif
) {
//-----------------------------------------------------------------------------
rb_id_t rb_id = 0;
logical_chan_id_t lc_id = 0;
DRB_Identity_t drb_id = 0;
DRB_Identity_t* pdrb_id = NULL;
long int cnt = 0;
const SRB_ToAddMod_t *srb_toaddmod_p = NULL;
const DRB_ToAddMod_t *drb_toaddmod_p = NULL;
rlc_union_t *rlc_union_p = NULL;
hash_key_t key = HASHTABLE_QUESTIONABLE_KEY_VALUE;
hashtable_rc_t h_rc;
#if defined(Rel10)
int i, j;
MBMS_SessionInfoList_r9_t *mbms_SessionInfoList_r9_p = NULL;
MBMS_SessionInfo_r9_t *MBMS_SessionInfo_p = NULL;
mbms_session_id_t mbms_session_id;
mbms_service_id_t mbms_service_id;
DL_UM_RLC_t dl_um_rlc;
#endif
LOG_D(RLC, "[FRAME %5u][%s][RLC_RRC][MOD %u/%u] CONFIG REQ ASN1 \n",
frameP,
(enb_flagP) ? "eNB" : "UE",
enb_mod_idP,
ue_mod_idP);
#ifdef OAI_EMU
if (enb_flagP) {
AssertFatal ((enb_mod_idP >= oai_emulation.info.first_enb_local) && (oai_emulation.info.nb_enb_local > 0),
"eNB module id is too low (%u/%d)!\n",
enb_mod_idP,
oai_emulation.info.first_enb_local);
AssertFatal ((enb_mod_idP < (oai_emulation.info.first_enb_local + oai_emulation.info.nb_enb_local)) && (oai_emulation.info.nb_enb_local > 0),
"eNB module id is too high (%u/%d)!\n",
enb_mod_idP,
oai_emulation.info.first_enb_local + oai_emulation.info.nb_enb_local);
AssertFatal (ue_mod_idP < NB_UE_INST,
"UE module id is too high (%u/%d)!\n",
ue_mod_idP,
oai_emulation.info.first_ue_local + oai_emulation.info.nb_ue_local);
} else {
AssertFatal (ue_mod_idP < (oai_emulation.info.first_ue_local + oai_emulation.info.nb_ue_local),
"UE module id is too high (%u/%d)!\n",
ue_mod_idP,
oai_emulation.info.first_ue_local + oai_emulation.info.nb_ue_local);
AssertFatal (ue_mod_idP >= oai_emulation.info.first_ue_local,
"UE module id is too low (%u/%d)!\n",
ue_mod_idP,
oai_emulation.info.first_ue_local);
}
#endif
if (srb2add_listP != NULL) {
for (cnt=0;cntlist.count;cnt++) {
rb_id = srb2add_listP->list.array[cnt]->srb_Identity;
lc_id = rb_id + 2;
LOG_D(RLC, "Adding SRB %d, rb_id %d\n",srb2add_listP->list.array[cnt]->srb_Identity,rb_id);
srb_toaddmod_p = srb2add_listP->list.array[cnt];
if (srb_toaddmod_p->rlc_Config) {
switch (srb_toaddmod_p->rlc_Config->present) {
case SRB_ToAddMod__rlc_Config_PR_NOTHING:
break;
case SRB_ToAddMod__rlc_Config_PR_explicitValue:
switch (srb_toaddmod_p->rlc_Config->choice.explicitValue.present) {
case RLC_Config_PR_NOTHING:
break;
case RLC_Config_PR_am:
if (rrc_rlc_add_rlc (enb_mod_idP, ue_mod_idP, frameP, enb_flagP, SRB_FLAG_YES, MBMS_FLAG_NO, rb_id, lc_id, RLC_MODE_AM) != NULL) {
config_req_rlc_am_asn1 (
enb_mod_idP,
ue_mod_idP,
frameP,
enb_flagP,
SRB_FLAG_YES,
&srb_toaddmod_p->rlc_Config->choice.explicitValue.choice.am,
rb_id);
} else {
LOG_E(RLC, "[FRAME %5u][%s][RLC_RRC][MOD %u/%u] ERROR IN ALLOCATING SRB %d \n",
frameP,
(enb_flagP) ? "eNB" : "UE",
enb_mod_idP,
ue_mod_idP,
rb_id);
}
break;
case RLC_Config_PR_um_Bi_Directional:
if (rrc_rlc_add_rlc (enb_mod_idP, ue_mod_idP, frameP, enb_flagP, SRB_FLAG_YES, MBMS_FLAG_NO, rb_id, lc_id, RLC_MODE_UM) != NULL) {
config_req_rlc_um_asn1(
enb_mod_idP,
ue_mod_idP,
frameP,
enb_flagP,
SRB_FLAG_YES,
MBMS_FLAG_NO,
UNUSED_PARAM_MBMS_SESSION_ID,
UNUSED_PARAM_MBMS_SERVICE_ID,
&srb_toaddmod_p->rlc_Config->choice.explicitValue.choice.um_Bi_Directional.ul_UM_RLC,
&srb_toaddmod_p->rlc_Config->choice.explicitValue.choice.um_Bi_Directional.dl_UM_RLC,
rb_id);
} else {
LOG_E(RLC, "[FRAME %5u][%s][RLC_RRC][MOD %u/%u] ERROR IN ALLOCATING SRB %d \n",
frameP,
(enb_flagP) ? "eNB" : "UE",
enb_mod_idP,
ue_mod_idP,
rb_id);
}
break;
case RLC_Config_PR_um_Uni_Directional_UL:
if (rrc_rlc_add_rlc (enb_mod_idP, ue_mod_idP, frameP, enb_flagP, SRB_FLAG_YES, MBMS_FLAG_NO, rb_id, lc_id, RLC_MODE_UM) != NULL) {
config_req_rlc_um_asn1(
enb_mod_idP,
ue_mod_idP,
frameP,
enb_flagP,
SRB_FLAG_YES,
MBMS_FLAG_NO,
UNUSED_PARAM_MBMS_SESSION_ID,
UNUSED_PARAM_MBMS_SERVICE_ID,
&srb_toaddmod_p->rlc_Config->choice.explicitValue.choice.um_Uni_Directional_UL.ul_UM_RLC,
NULL,
rb_id);
} else {
LOG_E(RLC, "[FRAME %5u][%s][RLC_RRC][MOD %u/%u] ERROR IN ALLOCATING SRB %d \n",
frameP,
(enb_flagP) ? "eNB" : "UE",
enb_mod_idP,
ue_mod_idP,
rb_id);
}
break;
case RLC_Config_PR_um_Uni_Directional_DL:
if (rrc_rlc_add_rlc (enb_mod_idP, ue_mod_idP, frameP, enb_flagP, SRB_FLAG_YES, MBMS_FLAG_NO, rb_id, lc_id, RLC_MODE_UM) != NULL) {
config_req_rlc_um_asn1(
enb_mod_idP,
ue_mod_idP,
frameP,
enb_flagP,
SRB_FLAG_YES,
MBMS_FLAG_NO,
UNUSED_PARAM_MBMS_SESSION_ID,
UNUSED_PARAM_MBMS_SERVICE_ID,
NULL,
&srb_toaddmod_p->rlc_Config->choice.explicitValue.choice.um_Uni_Directional_DL.dl_UM_RLC,
rb_id);
} else {
LOG_E(RLC, "[FRAME %5u][%s][RLC_RRC][MOD %u/%u] ERROR IN ALLOCATING SRB %d \n",
frameP,
(enb_flagP) ? "eNB" : "UE",
enb_mod_idP,
ue_mod_idP,
rb_id);
}
break;
default:
LOG_E(RLC, "[FRAME %5u][%s][RLC_RRC][MOD %u/%u] UNKNOWN RLC CONFIG %d \n",
frameP,
(enb_flagP) ? "eNB" : "UE",
enb_mod_idP,
ue_mod_idP,
srb_toaddmod_p->rlc_Config->choice.explicitValue.present);
break;
}
break;
case SRB_ToAddMod__rlc_Config_PR_defaultValue:
#warning TO DO SRB_ToAddMod__rlc_Config_PR_defaultValue
if (rrc_rlc_add_rlc (enb_mod_idP, ue_mod_idP, frameP, enb_flagP, SRB_FLAG_YES, MBMS_FLAG_NO, rb_id, lc_id, RLC_MODE_UM) != NULL) {
config_req_rlc_um_asn1(
enb_mod_idP,
ue_mod_idP,
frameP,
enb_flagP,
SRB_FLAG_YES,
MBMS_FLAG_NO,
UNUSED_PARAM_MBMS_SESSION_ID,
UNUSED_PARAM_MBMS_SERVICE_ID,
NULL, // TO DO DEFAULT CONFIG
NULL, // TO DO DEFAULT CONFIG
rb_id);
} else {
LOG_D(RLC, "[FRAME %5u][%s][RLC_RRC][MOD %u/%u] ERROR IN ALLOCATING SRB %d \n",
frameP,
(enb_flagP) ? "eNB" : "UE",
enb_mod_idP,
ue_mod_idP,
rb_id);
}
break;
default:;
}
}
}
}
if (drb2add_listP != NULL) {
for (cnt=0;cntlist.count;cnt++) {
drb_toaddmod_p = drb2add_listP->list.array[cnt];
drb_id = drb_toaddmod_p->drb_Identity;
lc_id = drb_id + 2;
LOG_D(RLC, "Adding DRB %d, lc_id %d\n",drb_id,lc_id);
if (drb_toaddmod_p->rlc_Config) {
switch (drb_toaddmod_p->rlc_Config->present) {
case RLC_Config_PR_NOTHING:
break;
case RLC_Config_PR_am:
if (rrc_rlc_add_rlc (enb_mod_idP, ue_mod_idP, frameP, enb_flagP, SRB_FLAG_NO, MBMS_FLAG_NO, drb_id, lc_id, RLC_MODE_AM) != NULL) {
config_req_rlc_am_asn1 (
enb_mod_idP,
ue_mod_idP,
frameP,
enb_flagP,
SRB_FLAG_NO,
&drb_toaddmod_p->rlc_Config->choice.am,
drb_id);
}
break;
case RLC_Config_PR_um_Bi_Directional:
if (rrc_rlc_add_rlc (enb_mod_idP, ue_mod_idP, frameP, enb_flagP, SRB_FLAG_NO, MBMS_FLAG_NO, drb_id, lc_id, RLC_MODE_UM) != NULL) {
config_req_rlc_um_asn1(
enb_mod_idP,
ue_mod_idP,
frameP,
enb_flagP,
SRB_FLAG_NO,
MBMS_FLAG_NO,
UNUSED_PARAM_MBMS_SESSION_ID,
UNUSED_PARAM_MBMS_SERVICE_ID,
&drb_toaddmod_p->rlc_Config->choice.um_Bi_Directional.ul_UM_RLC,
&drb_toaddmod_p->rlc_Config->choice.um_Bi_Directional.dl_UM_RLC,
drb_id);
}
break;
case RLC_Config_PR_um_Uni_Directional_UL:
if (rrc_rlc_add_rlc (enb_mod_idP, ue_mod_idP, frameP, enb_flagP, SRB_FLAG_NO, MBMS_FLAG_NO, drb_id, lc_id, RLC_MODE_UM) != NULL) {
config_req_rlc_um_asn1(
enb_mod_idP,
ue_mod_idP,
frameP,
enb_flagP,
SRB_FLAG_NO,
MBMS_FLAG_NO,
UNUSED_PARAM_MBMS_SESSION_ID,
UNUSED_PARAM_MBMS_SERVICE_ID,
&drb_toaddmod_p->rlc_Config->choice.um_Uni_Directional_UL.ul_UM_RLC,
NULL,
drb_id);
}
break;
case RLC_Config_PR_um_Uni_Directional_DL:
if (rrc_rlc_add_rlc (enb_mod_idP, ue_mod_idP, frameP, enb_flagP, SRB_FLAG_NO, MBMS_FLAG_NO, drb_id, lc_id, RLC_MODE_UM) != NULL) {
config_req_rlc_um_asn1(
enb_mod_idP,
ue_mod_idP,
frameP,
enb_flagP,
SRB_FLAG_NO,
MBMS_FLAG_NO,
UNUSED_PARAM_MBMS_SESSION_ID,
UNUSED_PARAM_MBMS_SERVICE_ID,
NULL,
&drb_toaddmod_p->rlc_Config->choice.um_Uni_Directional_DL.dl_UM_RLC,
drb_id);
}
break;
default:
LOG_W(RLC, "[FRAME %5u][%s][RLC_RRC][MOD %u/%u][RB %u] unknown drb_toaddmod_p->rlc_Config->present \n",
frameP,
(enb_flagP) ? "eNB" : "UE",
enb_mod_idP,
ue_mod_idP,
drb_id);
}
}
}
}
if (drb2release_listP != NULL) {
for (cnt=0;cntlist.count;cnt++) {
pdrb_id = drb2release_listP->list.array[cnt];
rrc_rlc_remove_rlc(enb_mod_idP, ue_mod_idP, frameP, enb_flagP, SRB_FLAG_NO, MBMS_FLAG_NO, *pdrb_id);
}
}
#if defined(Rel10)
if (pmch_InfoList_r9_pP != NULL) {
for (i=0;ilist.count;i++) {
mbms_SessionInfoList_r9_p = &(pmch_InfoList_r9_pP->list.array[i]->mbms_SessionInfoList_r9);
for (j=0;jlist.count;j++) {
MBMS_SessionInfo_p = mbms_SessionInfoList_r9_p->list.array[j];
mbms_session_id = MBMS_SessionInfo_p->sessionId_r9->buf[0];
lc_id = mbms_session_id;
mbms_service_id = MBMS_SessionInfo_p->tmgi_r9.serviceId_r9.buf[2]; //serviceId is 3-octet string
// can set the mch_id = i
if (enb_flagP) {
rb_id = (mbms_service_id * maxSessionPerPMCH ) + mbms_session_id;//+ (maxDRB + 3) * MAX_MOBILES_PER_ENB; // 1
rlc_mbms_lcid2service_session_id_eNB[enb_mod_idP][lc_id].service_id = mbms_service_id;
rlc_mbms_lcid2service_session_id_eNB[enb_mod_idP][lc_id].session_id = mbms_session_id;
rlc_mbms_enb_set_lcid_by_rb_id(enb_mod_idP,rb_id,lc_id);
} else {
rb_id = (mbms_service_id * maxSessionPerPMCH ) + mbms_session_id; // + (maxDRB + 3); // 15
rlc_mbms_lcid2service_session_id_ue[ue_mod_idP][lc_id].service_id = mbms_service_id;
rlc_mbms_lcid2service_session_id_ue[ue_mod_idP][lc_id].session_id = mbms_session_id;
rlc_mbms_ue_set_lcid_by_rb_id(ue_mod_idP,rb_id,lc_id);
}
key = RLC_COLL_KEY_MBMS_VALUE(enb_mod_idP, ue_mod_idP, enb_flagP, mbms_service_id, mbms_session_id);
h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);
if (h_rc == HASH_TABLE_KEY_NOT_EXISTS) {
rlc_union_p = rrc_rlc_add_rlc (
enb_mod_idP,
ue_mod_idP,
frameP,
enb_flagP,
SRB_FLAG_NO,
MBMS_FLAG_YES,
rb_id,
lc_id,
RLC_MODE_UM);
AssertFatal(rlc_union_p != NULL, "ADD MBMS RLC UM FAILED");
}
LOG_D(RLC, "[FRAME %5u][%s][RLC_RRC][MOD %u/%u] CONFIG REQ MBMS ASN1 LC ID %u RB ID %u SESSION ID %u SERVICE ID %u\n",
frameP,
(enb_flagP) ? "eNB" : "UE",
enb_mod_idP,
ue_mod_idP,
lc_id,
rb_id,
mbms_session_id,
mbms_service_id
);
dl_um_rlc.sn_FieldLength = SN_FieldLength_size5;
dl_um_rlc.t_Reordering = T_Reordering_ms0;
config_req_rlc_um_asn1 (
enb_mod_idP,
ue_mod_idP,
frameP,
enb_flagP,
SRB_FLAG_NO,
MBMS_FLAG_YES,
mbms_session_id,
mbms_service_id,
NULL,
&dl_um_rlc,
rb_id);
}
}
}
#endif
LOG_D(RLC, "[FRAME %5u][%s][RLC_RRC][MOD %u/%u] CONFIG REQ ASN1 END \n",
frameP,
(enb_flagP) ? "eNB" : "UE",
enb_flagP,
enb_mod_idP,
ue_mod_idP);
return RLC_OP_STATUS_OK;
}
//-----------------------------------------------------------------------------
void
rb_free_rlc_union (void *rlcu_pP)
{
//-----------------------------------------------------------------------------
rlc_union_t * rlcu_p;
if (rlcu_pP) {
rlcu_p = (rlc_union_t *)(rlcu_pP);
switch (rlcu_p->mode) {
case RLC_MODE_AM:
rlc_am_cleanup(&rlcu_p->rlc.am);
break;
case RLC_MODE_UM:
rlc_um_cleanup(&rlcu_p->rlc.um);
break;
case RLC_MODE_TM:
rlc_tm_cleanup(&rlcu_p->rlc.tm);
break;
default:
LOG_W(RLC,
"%s %p unknown RLC type\n",
__FUNCTION__,
rlcu_pP);
break;
}
LOG_D(RLC,
"%s %p \n",
__FUNCTION__,
rlcu_pP);
free(rlcu_p);
}
}
//-----------------------------------------------------------------------------
rlc_op_status_t rrc_rlc_remove_ue (
const module_id_t enb_mod_idP,
const module_id_t ue_mod_idP,
const eNB_flag_t enb_flagP,
const frame_t frameP,
const eNB_flag_t enb_flagP) {
//-----------------------------------------------------------------------------
logical_chan_id_t lcid = 0;
rb_id_t rb_id;
for (rb_id = 1; rb_id <= 2; rb_id++) {
rrc_rlc_remove_rlc(enb_mod_idP,
ue_mod_idP,
frameP,
enb_flagP,
SRB_FLAG_YES,
MBMS_FLAG_NO,
rb_id);
}
for (rb_id = 1; rb_id <= maxDRB; rb_id++) {
rrc_rlc_remove_rlc(enb_mod_idP,
ue_mod_idP,
frameP,
enb_flagP,
SRB_FLAG_NO,
MBMS_FLAG_NO,
rb_id);
}
return RLC_OP_STATUS_OK;
}
//-----------------------------------------------------------------------------
rlc_op_status_t rrc_rlc_remove_rlc (
const module_id_t enb_mod_idP,
const module_id_t ue_mod_idP,
const frame_t frameP,
const eNB_flag_t enb_flagP,
const srb_flag_t srb_flagP,
const MBMS_flag_t MBMS_flagP,
const rb_id_t rb_idP) {
//-----------------------------------------------------------------------------
logical_chan_id_t lcid = 0;
hash_key_t key = HASHTABLE_QUESTIONABLE_KEY_VALUE;
hashtable_rc_t h_rc;
rlc_union_t *rlc_union_p = NULL;
#ifdef Rel10
rlc_mbms_id_t *mbms_id_p = NULL;
#endif
#ifdef OAI_EMU
AssertFatal ((enb_mod_idP >= oai_emulation.info.first_enb_local) && (oai_emulation.info.nb_enb_local > 0),
"eNB module id is too low (%u/%d)!\n",
enb_mod_idP,
oai_emulation.info.first_enb_local);
AssertFatal (enb_mod_idP < (oai_emulation.info.first_enb_local + oai_emulation.info.nb_enb_local),
"eNB module id is too high (%u/%d)!\n",
enb_mod_idP,
oai_emulation.info.first_enb_local + oai_emulation.info.nb_enb_local);
if (enb_flagP) {
AssertFatal (ue_mod_idP < NB_UE_INST,
"UE module id is too high (%u/%d)!\n",
ue_mod_idP,
oai_emulation.info.first_ue_local + oai_emulation.info.nb_ue_local);
} else {
AssertFatal (ue_mod_idP < (oai_emulation.info.first_ue_local + oai_emulation.info.nb_ue_local),
"UE module id is too high (%u/%d)!\n",
ue_mod_idP,
oai_emulation.info.first_ue_local + oai_emulation.info.nb_ue_local);
AssertFatal (ue_mod_idP >= oai_emulation.info.first_ue_local,
"UE module id is too low (%u/%d)!\n",
ue_mod_idP,
oai_emulation.info.first_ue_local);
}
#endif
#ifdef Rel10
if (MBMS_flagP == TRUE) {
if (enb_flagP) {
lcid = rlc_mbms_enb_get_lcid_by_rb_id(enb_mod_idP,rb_idP);
mbms_id_p = &rlc_mbms_lcid2service_session_id_eNB[enb_mod_idP][lcid];
rlc_mbms_lcid2service_session_id_eNB[enb_mod_idP][lcid].service_id = 0;
rlc_mbms_lcid2service_session_id_eNB[enb_mod_idP][lcid].session_id = 0;
rlc_mbms_rbid2lcid_ue[enb_mod_idP][rb_idP] = RLC_LC_UNALLOCATED;
} else {
lcid = rlc_mbms_ue_get_lcid_by_rb_id(ue_mod_idP,rb_idP);
mbms_id_p = &rlc_mbms_lcid2service_session_id_ue[ue_mod_idP][lcid];
rlc_mbms_lcid2service_session_id_eNB[ue_mod_idP][lcid].service_id = 0;
rlc_mbms_lcid2service_session_id_eNB[ue_mod_idP][lcid].session_id = 0;
rlc_mbms_rbid2lcid_ue[ue_mod_idP][rb_idP] = RLC_LC_UNALLOCATED;
}
key = RLC_COLL_KEY_MBMS_VALUE(enb_mod_idP, ue_mod_idP, enb_flagP, mbms_id_p->service_id, mbms_id_p->session_id);
} else
#endif
{
key = RLC_COLL_KEY_VALUE(enb_mod_idP, ue_mod_idP, enb_flagP, rb_idP, srb_flagP);
}
AssertFatal (rb_idP < NB_RB_MAX, "RB id is too high (%u/%d)!\n", rb_idP, NB_RB_MAX);
h_rc = hashtable_get(rlc_coll_p, key, &rlc_union_p);
if (h_rc == HASH_TABLE_OK) {
switch (rlc_union_p->mode) {
case RLC_MODE_AM:
rlc_am_cleanup(&rlc_union_p->rlc.am);
break;
case RLC_MODE_UM:
rlc_um_cleanup(&rlc_union_p->rlc.um);
break;
case RLC_MODE_TM:
rlc_tm_cleanup(&rlc_union_p->rlc.tm);
break;
default:
}
h_rc = hashtable_remove(rlc_coll_p, key);
LOG_D(RLC, "[Frame %05u][%s][RLC_RRC][INST %u/%u][%s %u] RELEASED %s\n",
frameP,
(enb_flagP) ? "eNB" : "UE",
enb_mod_idP,
ue_mod_idP,
(srb_flagP) ? "SRB" : "DRB",
rb_idP,
(srb_flagP) ? "SRB" : "DRB");
} else if (h_rc == HASH_TABLE_KEY_NOT_EXISTS) {
LOG_W(RLC, "[Frame %05u][%s][RLC_RRC][INST %u/%u][%s %u] RELEASE : RLC NOT FOUND %s\n",
frameP,
(enb_flagP) ? "eNB" : "UE",
enb_mod_idP,
ue_mod_idP,
(srb_flagP) ? "SRB" : "DRB",
rb_idP,
(srb_flagP) ? "SRB" : "DRB");
} else {
LOG_E(RLC, "[Frame %05u][%s][RLC_RRC][INST %u/%u][%s %u] RELEASE : INTERNAL ERROR %s\n",
frameP,
(enb_flagP) ? "eNB" : "UE",
enb_mod_idP,
ue_mod_idP,
(srb_flagP) ? "SRB" : "DRB",
rb_idP,
(srb_flagP) ? "SRB" : "DRB"); }
return RLC_OP_STATUS_OK;
}
//-----------------------------------------------------------------------------
rlc_union_t* rrc_rlc_add_rlc (
const module_id_t enb_mod_idP,
const module_id_t ue_mod_idP,
const frame_t frameP,
const eNB_flag_t enb_flagP,
const srb_flag_t srb_flagP,
const MBMS_flag_t MBMS_flagP,
const rb_id_t rb_idP,
const logical_chan_id_t chan_idP,
const rlc_mode_t rlc_modeP) {
//-----------------------------------------------------------------------------
hash_key_t key = HASHTABLE_QUESTIONABLE_KEY_VALUE;
hashtable_rc_t h_rc;
rlc_union_t *rlc_union_p = NULL;
#ifdef Rel10
rlc_mbms_id_t *mbms_id_p = NULL;
logical_chan_id_t lcid = 0;
#endif
#ifdef OAI_EMU
if (enb_flagP) {
AssertFatal ((enb_mod_idP >= oai_emulation.info.first_enb_local) && (oai_emulation.info.nb_enb_local > 0),
"eNB module id is too low (%u/%d)!\n",
enb_mod_idP,
oai_emulation.info.first_enb_local);
AssertFatal ((enb_mod_idP < (oai_emulation.info.first_enb_local + oai_emulation.info.nb_enb_local)) && (oai_emulation.info.nb_enb_local > 0),
"eNB module id is too high (%u/%d)!\n",
enb_mod_idP,
oai_emulation.info.first_enb_local + oai_emulation.info.nb_enb_local);
AssertFatal (ue_mod_idP < NB_UE_INST,
"UE module id is too high (%u/%d)!\n",
ue_mod_idP,
oai_emulation.info.first_ue_local + oai_emulation.info.nb_ue_local);
} else {
AssertFatal (ue_mod_idP < (oai_emulation.info.first_ue_local + oai_emulation.info.nb_ue_local),
"UE module id is too high (%u/%d)!\n",
ue_mod_idP,
oai_emulation.info.first_ue_local + oai_emulation.info.nb_ue_local);
AssertFatal (ue_mod_idP >= oai_emulation.info.first_ue_local,
"UE module id is too low (%u/%d)!\n",
ue_mod_idP,
oai_emulation.info.first_ue_local);
}
#endif
if (MBMS_flagP == FALSE) {
AssertFatal (rb_idP < NB_RB_MAX, "RB id is too high (%u/%d)!\n", rb_idP, NB_RB_MAX);
AssertFatal (chan_idP < RLC_MAX_LC, "LC id is too high (%u/%d)!\n", chan_idP, RLC_MAX_LC);
}
#ifdef Rel10
if (MBMS_flagP == TRUE) {
if (enb_flagP) {
lcid = rlc_mbms_enb_get_lcid_by_rb_id(enb_mod_idP,rb_idP);
LOG_I(RLC,
"[Frame %05u] lcid %d = rlc_mbms_enb_get_lcid_by_rb_id(enb_mod_idP %u, rb_idP %u)\n",
frameP,lcid, enb_mod_idP, rb_idP);
mbms_id_p = &rlc_mbms_lcid2service_session_id_eNB[enb_mod_idP][lcid];
//LG 2014-04-15rlc_mbms_lcid2service_session_id_eNB[enb_mod_idP][lcid].service_id = 0;
//LG 2014-04-15rlc_mbms_lcid2service_session_id_eNB[enb_mod_idP][lcid].session_id = 0;
//LG 2014-04-15rlc_mbms_rbid2lcid_eNB[enb_mod_idP][rb_idP] = RLC_LC_UNALLOCATED;
} else {
lcid = rlc_mbms_ue_get_lcid_by_rb_id(ue_mod_idP,rb_idP);
mbms_id_p = &rlc_mbms_lcid2service_session_id_ue[ue_mod_idP][lcid];
//LG 2014-04-15rlc_mbms_lcid2service_session_id_eNB[ue_mod_idP][lcid].service_id = 0;
//LG 2014-04-15rlc_mbms_lcid2service_session_id_eNB[ue_mod_idP][lcid].session_id = 0;
//LG 2014-04-15rlc_mbms_rbid2lcid_ue[ue_mod_idP][rb_idP] = RLC_LC_UNALLOCATED;
}
key = RLC_COLL_KEY_MBMS_VALUE(enb_mod_idP, ue_mod_idP, enb_flagP, mbms_id_p->service_id, mbms_id_p->session_id);
} else
#endif
{
key = RLC_COLL_KEY_VALUE(enb_mod_idP, ue_mod_idP, enb_flagP, rb_idP, srb_flagP);
}
h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);
if (h_rc == HASH_TABLE_OK) {
LOG_W(RLC, "[Frame %05u][%s][RLC_RRC][INST %u/%u][%s %u] rrc_rlc_add_rlc , already exist %s\n",
frameP,
(enb_flagP) ? "eNB" : "UE",
enb_mod_idP,
ue_mod_idP,
(srb_flagP) ? "SRB" : "DRB",
rb_idP,
(srb_flagP) ? "SRB" : "DRB");
AssertFatal(rlc_union_p->mode == rlc_modeP, "Error rrc_rlc_add_rlc , already exist but RLC mode differ");
return rlc_union_p;
} else if (h_rc == HASH_TABLE_KEY_NOT_EXISTS) {
rlc_union_p = calloc(1, sizeof(rlc_union_t));
h_rc = hashtable_insert(rlc_coll_p, key, rlc_union_p);
if (h_rc == HASH_TABLE_OK) {
#ifdef Rel10
if (MBMS_flagP == TRUE) {
LOG_I(RLC, "[Frame %05u][%s][RLC_RRC][INST %u/%u] RLC service id %u session id %u rrc_rlc_add_rlc\n",
frameP,
(enb_flagP) ? "eNB" : "UE",
enb_mod_idP,
ue_mod_idP,
mbms_id_p->service_id,
mbms_id_p->session_id);
} else
#endif
{
LOG_I(RLC, "[Frame %05u][%s][RLC_RRC][INST %u/%u][%s %u] rrc_rlc_add_rlc %s\n",
frameP,
(enb_flagP) ? "eNB" : "UE",
enb_mod_idP,
ue_mod_idP,
(srb_flagP) ? "SRB" : "DRB",
rb_idP,
(srb_flagP) ? "SRB" : "DRB");
}
rlc_union_p->mode = rlc_modeP;
return rlc_union_p;
} else {
LOG_E(RLC, "[Frame %05u][%s][RLC_RRC][INST %u/%u][%s %u] rrc_rlc_add_rlc FAILED %s\n",
frameP,
(enb_flagP) ? "eNB" : "UE",
enb_mod_idP,
ue_mod_idP,
(srb_flagP) ? "SRB" : "DRB",
rb_idP,
(srb_flagP) ? "SRB" : "DRB");
free(rlc_union_p);
rlc_union_p = NULL;
return NULL;
}
} else {
LOG_E(RLC, "[Frame %05u][%s][RLC_RRC][INST %u/%u][%s %u] rrc_rlc_add_rlc , INTERNAL ERROR %s\n",
frameP,
(enb_flagP) ? "eNB" : "UE",
enb_mod_idP,
ue_mod_idP,
(srb_flagP) ? "SRB" : "DRB",
rb_idP,
(srb_flagP) ? "SRB" : "DRB");
}
return NULL;
}
//-----------------------------------------------------------------------------
rlc_op_status_t rrc_rlc_config_req (
const module_id_t enb_mod_idP,
const module_id_t ue_mod_idP,
const frame_t frameP,
const eNB_flag_t enb_flagP,
const srb_flag_t srb_flagP,
const MBMS_flag_t mbms_flagP,
const config_action_t actionP,
const rb_id_t rb_idP,
const rlc_info_t rlc_infoP) {
//-----------------------------------------------------------------------------
rlc_op_status_t status;
LOG_D(RLC, "[FRAME %05u][%s][RLC][MOD %u/%u] CONFIG_REQ for Rab %u\n",
frameP,
(enb_flagP) ? "eNB" : "UE",
enb_mod_idP,
ue_mod_idP,
rb_idP);
#ifdef OAI_EMU
if (enb_flagP) {
AssertFatal ((enb_mod_idP >= oai_emulation.info.first_enb_local) && (oai_emulation.info.nb_enb_local > 0),
"eNB module id is too low (%u/%d)!\n",
enb_mod_idP,
oai_emulation.info.first_enb_local);
AssertFatal ((enb_mod_idP < (oai_emulation.info.first_enb_local + oai_emulation.info.nb_enb_local)) && (oai_emulation.info.nb_enb_local > 0),
"eNB module id is too high (%u/%d)!\n",
enb_mod_idP,
oai_emulation.info.first_enb_local + oai_emulation.info.nb_enb_local);
AssertFatal (ue_mod_idP < NB_UE_INST,
"UE module id is too high (%u/%d)!\n",
ue_mod_idP,
oai_emulation.info.first_ue_local + oai_emulation.info.nb_ue_local);
} else {
AssertFatal (ue_mod_idP < (oai_emulation.info.first_ue_local + oai_emulation.info.nb_ue_local),
"UE module id is too high (%u/%d)!\n",
ue_mod_idP,
oai_emulation.info.first_ue_local + oai_emulation.info.nb_ue_local);
AssertFatal (ue_mod_idP >= oai_emulation.info.first_ue_local,
"UE module id is too low (%u/%d)!\n",
ue_mod_idP,
oai_emulation.info.first_ue_local);
}
#endif
AssertFatal (rb_idP < NB_RB_MAX, "RB id is too high (%u/%d)!\n", rb_idP, NB_RB_MAX);
switch (actionP) {
case CONFIG_ACTION_ADD:
if (rrc_rlc_add_rlc(enb_mod_idP, ue_mod_idP, frameP, enb_flagP, srb_flagP, MBMS_FLAG_NO, rb_idP, rb_idP, rlc_infoP.rlc_mode) != NULL) {
return RLC_OP_STATUS_INTERNAL_ERROR;
}
// no break, fall to next case
case CONFIG_ACTION_MODIFY:
switch (rlc_infoP.rlc_mode) {
case RLC_MODE_AM:
LOG_I(RLC, "[Frame %05u][UE][RLC_RRC][INST %u/%u][RB %u] MODIFY RB AM\n",
frameP,
enb_mod_idP,
ue_mod_idP,
rb_idP);
config_req_rlc_am(
enb_mod_idP,
ue_mod_idP,
frameP,
enb_flagP,
srb_flagP,
&rlc_infoP.rlc.rlc_am_info,
rb_idP);
break;
case RLC_MODE_UM:
LOG_I(RLC, "[Frame %05u][UE][RLC_RRC][INST %u/%u][RB %u] MODIFY RB UM\n",
frameP,
enb_mod_idP,
ue_mod_idP,
rb_idP);
config_req_rlc_um(
enb_mod_idP,
ue_mod_idP,
frameP,
enb_flagP,
srb_flagP,
&rlc_infoP.rlc.rlc_um_info,
rb_idP);
break;
case RLC_MODE_TM:
LOG_I(RLC, "[Frame %05u][UE][RLC_RRC][INST %u/%u][RB %u] MODIFY RB TM\n",
frameP,
enb_mod_idP,
ue_mod_idP,
rb_idP);
config_req_rlc_tm(
enb_mod_idP,
ue_mod_idP,
frameP,
enb_flagP,
srb_flagP,
&rlc_infoP.rlc.rlc_tm_info,
rb_idP);
break;
default:
return RLC_OP_STATUS_BAD_PARAMETER;
}
break;
case CONFIG_ACTION_REMOVE:
return rrc_rlc_remove_rlc(enb_mod_idP, ue_mod_idP, frameP, enb_flagP, srb_flagP, mbms_flagP, rb_idP);
break;
default:
return RLC_OP_STATUS_BAD_PARAMETER;
}
return RLC_OP_STATUS_OK;
}
//-----------------------------------------------------------------------------
rlc_op_status_t rrc_rlc_data_req (
const module_id_t enb_mod_idP,
const module_id_t ue_mod_idP,
const frame_t frameP,
const eNB_flag_t enb_flagP,
const MBMS_flag_t MBMS_flagP,
const rb_id_t rb_idP,
const mui_t muiP,
const confirm_t confirmP,
const sdu_size_t sdu_sizeP,
char* sduP) {
//-----------------------------------------------------------------------------
mem_block_t* sdu;
sdu = get_free_mem_block(sdu_sizeP);
if (sdu != NULL) {
memcpy (sdu->data, sduP, sdu_sizeP);
return rlc_data_req(enb_mod_idP, ue_mod_idP, frameP, enb_flagP, SRB_FLAG_YES, MBMS_flagP, rb_idP, muiP, confirmP, sdu_sizeP, sdu);
} else {
return RLC_OP_STATUS_INTERNAL_ERROR;
}
}
//-----------------------------------------------------------------------------
void rrc_rlc_register_rrc (rrc_data_ind_cb_t rrc_data_indP, rrc_data_conf_cb_t rrc_data_confP) {
//-----------------------------------------------------------------------------
rlc_rrc_data_ind = rrc_data_indP;
rlc_rrc_data_conf = rrc_data_confP;
}