Compare commits

...

23 Commits

Author SHA1 Message Date
Robert Schmidt
04d981d97b Hacks for UE to keep latency after DRB5 add low 2023-06-14 08:26:53 +02:00
Robert Schmidt
71705fb0cf More UBSan 2023-06-13 11:04:30 +02:00
Robert Schmidt
471ee10b14 Fix UB problems found with UBSan 2023-06-13 11:04:38 +02:00
Robert Schmidt
c218cf14f5 Add newGtpuDeleteOneTunnel() to remove one GTP tunnel 2023-06-12 18:08:10 +02:00
Robert Schmidt
beadd5109b UE: mark rlc_BearerToReleaseList as NULL if nothing received 2023-06-12 14:20:39 +02:00
Robert Schmidt
dcd0c83b11 Activate SRB2 only once 2023-06-12 14:20:39 +02:00
Robert Schmidt
556b2299b8 fixup 2023-06-12 14:20:39 +02:00
Robert Schmidt
156a49175e rlc_BearerToReleaseList should not be persisted 2023-06-12 12:43:34 +02:00
Robert Schmidt
bc58d63bcf Hacks to make SDAP pass after bearer release 2023-06-12 12:23:29 +02:00
Robert Schmidt
457dee8f1c Speed up RFsim rfsimulator_write_internal() using SIMD 2023-06-10 13:42:08 +02:00
Robert Schmidt
31eb6e1b40 Speed up RFsim rfsimulator_read() using SIMD 2023-06-10 13:42:07 +02:00
Robert Schmidt
8a40be05c1 Make LCID added output debug 2023-06-08 17:31:31 +02:00
Robert Schmidt
f9b4e1a8b4 Make LCID output nicer 2023-06-08 17:31:31 +02:00
Robert Schmidt
cb7b168cdf NAS PDU is optional 2023-06-08 17:15:43 +02:00
Robert Schmidt
5e74a3b64b Add encoding/decoding of UE Ctxt Modif Req DRB Release 2023-06-08 15:16:31 +02:00
Robert Schmidt
f9a0e8a9f9 fix bug (is included in 2023.w22) 2023-06-08 14:40:32 +02:00
Robert Schmidt
c8fbd968e8 Hack to route ping to different bearers 2023-06-08 13:26:53 +02:00
Robert Schmidt
4af29d6420 Basic and crude bearer release 2023-06-08 13:26:52 +02:00
Robert Schmidt
891eaddac8 hack to make classifier work on UE 2023-06-08 13:26:04 +02:00
Robert Schmidt
b76dafac23 Remove RRC handling code from SDAP 2023-06-08 13:26:04 +02:00
mir
2c9b640df9 Naive ICMP classifier added 2023-06-08 13:26:04 +02:00
Robert Schmidt
f5c15847c9 Scheduler: sort second bearer before first one 2023-06-08 13:26:04 +02:00
Robert Schmidt
b1c6a0baba Add bearer 2023-06-08 13:26:03 +02:00
27 changed files with 596 additions and 89 deletions

View File

@@ -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 ../../..
)

View File

@@ -0,0 +1,121 @@
/*
* 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);
}

View File

@@ -346,7 +346,7 @@ typedef struct f1ap_srb_to_be_setup_s {
typedef struct f1ap_rb_failed_to_be_setup_s {
long rb_id;
} f1ap_rb_failed_to_be_setup_t;
} f1ap_rb_failed_to_be_setup_t, f1ap_drb_to_be_released_t;
typedef struct cu_to_du_rrc_information_s {
uint8_t * cG_ConfigInfo;
@@ -404,6 +404,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;

View File

@@ -36,7 +36,7 @@ static f1ap_cudu_inst_t *f1_du_inst[NUMBER_OF_gNB_MAX]= {0};
static f1ap_cudu_inst_t *f1_cu_inst[NUMBER_OF_gNB_MAX]= {0};
uint8_t F1AP_get_next_transaction_identifier(instance_t mod_idP, instance_t cu_mod_idP) {
static uint8_t transaction_identifier[NUMBER_OF_gNB_MAX];
static uint8_t transaction_identifier[NUMBER_OF_gNB_MAX] = {0};
transaction_identifier[mod_idP+cu_mod_idP] =
(transaction_identifier[mod_idP+cu_mod_idP] + 1) % F1AP_TRANSACTION_IDENTIFIER_NUMBER;
return transaction_identifier[mod_idP+cu_mod_idP];

View File

@@ -694,7 +694,7 @@ int CU_handle_UE_CONTEXT_SETUP_RESPONSE(instance_t instance,
F1AP_DLUPTNLInformation_ToBeSetup_Item_t *dl_up_tnl_info_p = (F1AP_DLUPTNLInformation_ToBeSetup_Item_t *)drbs_setup_item_p->dLUPTNLInformation_ToBeSetup_List.list.array[0];
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_INT32(&dl_up_tnl0->gTP_TEID, drb_p->up_dl_tnl[0].teid);
OCTET_STRING_TO_UINT32(&dl_up_tnl0->gTP_TEID, drb_p->up_dl_tnl[0].teid);
GtpuUpdateTunnelOutgoingAddressAndTeid(getCxt(CUtype, instance)->gtpInst,
f1ap_ue_context_setup_resp->rnti,
(ebi_t)drbs_setup_item_p->dRBID,
@@ -1560,14 +1560,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);
@@ -1578,7 +1578,8 @@ 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(CUtype, instance)->gtpInst, f1ap_ue_context_modification_req->rnti, f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id);
}
}
@@ -1655,7 +1656,7 @@ int CU_handle_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance,
F1AP_DLUPTNLInformation_ToBeSetup_Item_t *dl_up_tnl_info_p = (F1AP_DLUPTNLInformation_ToBeSetup_Item_t *)drbs_setupmod_item_p->dLUPTNLInformation_ToBeSetup_List.list.array[0];
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_INT32(&dl_up_tnl0->gTP_TEID, drb_p->up_dl_tnl[0].teid);
OCTET_STRING_TO_UINT32(&dl_up_tnl0->gTP_TEID, drb_p->up_dl_tnl[0].teid);
GtpuUpdateTunnelOutgoingAddressAndTeid(getCxt(CUtype, instance)->gtpInst,
f1ap_ue_context_modification_resp->rnti,
(ebi_t)drbs_setupmod_item_p->dRBID,

View File

@@ -218,7 +218,7 @@ int DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(instance_t instanceP,
ie6->id = F1AP_ProtocolIE_ID_id_TransactionID;
ie6->criticality = F1AP_Criticality_ignore;
ie6->value.present = F1AP_InitialULRRCMessageTransferIEs__value_PR_TransactionID;
ie6->value.choice.TransactionID = F1AP_get_next_transaction_identifier(f1ap_req(false, instanceP)->gNB_DU_id, f1ap_req(false, instanceP)->gNB_DU_id);
ie6->value.choice.TransactionID = F1AP_get_next_transaction_identifier(0, 0);
/* encode */
if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) {

View File

@@ -162,7 +162,7 @@ int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance,
F1AP_ULUPTNLInformation_ToBeSetup_Item_t *ul_up_tnl_info_p = (F1AP_ULUPTNLInformation_ToBeSetup_Item_t *)drbs_tobesetup_item_p->uLUPTNLInformation_ToBeSetup_List.list.array[0];
F1AP_GTPTunnel_t *ul_up_tnl0 = ul_up_tnl_info_p->uLUPTNLInformation.choice.gTPTunnel;
BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&ul_up_tnl0->transportLayerAddress, drb_p->up_ul_tnl[0].tl_address);
OCTET_STRING_TO_INT32(&ul_up_tnl0->gTP_TEID, drb_p->up_ul_tnl[0].teid);
OCTET_STRING_TO_UINT32(&ul_up_tnl0->gTP_TEID, drb_p->up_ul_tnl[0].teid);
// 3GPP assumes GTP-U is on port 2152, but OAI is configurable
drb_p->up_ul_tnl[0].port=getCxt(false,instance)->setupReq.CUport;
@@ -878,7 +878,7 @@ int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, uint32_t asso
F1AP_ULUPTNLInformation_ToBeSetup_Item_t *ul_up_tnl_info_p = (F1AP_ULUPTNLInformation_ToBeSetup_Item_t *)drbs_tobesetupmod_item_p->uLUPTNLInformation_ToBeSetup_List.list.array[0];
F1AP_GTPTunnel_t *ul_up_tnl0 = ul_up_tnl_info_p->uLUPTNLInformation.choice.gTPTunnel;
BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&ul_up_tnl0->transportLayerAddress, drb_p->up_ul_tnl[0].tl_address);
OCTET_STRING_TO_INT32(&ul_up_tnl0->gTP_TEID, drb_p->up_ul_tnl[0].teid);
OCTET_STRING_TO_UINT32(&ul_up_tnl0->gTP_TEID, drb_p->up_ul_tnl[0].teid);
// 3GPP assumes GTP-U is on port 2152, but OAI is configurable
drb_p->up_ul_tnl[0].port=getCxt(false,instance)->setupReq.CUport;
@@ -915,6 +915,24 @@ int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, uint32_t asso
}
}
}
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->rnti, 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,

View File

@@ -61,10 +61,12 @@ static void process_rlcBearerConfig(struct NR_CellGroupConfig__rlc_BearerToAddMo
if (rlc_bearer2release_list) {
for (int i = 0; i < rlc_bearer2release_list->list.count; i++) {
for (int idx = 0; idx < sched_ctrl->dl_lc_num; idx++) {
if (sched_ctrl->dl_lc_ids[idx] == *rlc_bearer2release_list->list.array[i]) {
const int lcid = *rlc_bearer2release_list->list.array[i];
if (sched_ctrl->dl_lc_ids[idx] == lcid) {
const int remaining_lcs = sched_ctrl->dl_lc_num - idx - 1;
memmove(&sched_ctrl->dl_lc_ids[idx], &sched_ctrl->dl_lc_ids[idx + 1], sizeof(sched_ctrl->dl_lc_ids[idx]) * remaining_lcs);
sched_ctrl->dl_lc_num--;
LOG_I(NR_MAC, "remove LCID %d (%s %d)\n", lcid, lcid < 4 ? "SRB" : "DRB", lcid);
break;
}
}
@@ -74,7 +76,7 @@ static void process_rlcBearerConfig(struct NR_CellGroupConfig__rlc_BearerToAddMo
if (rlc_bearer2add_list) {
// keep lcids
for (int i = 0; i < rlc_bearer2add_list->list.count; i++) {
const int lcid = rlc_bearer2add_list->list.array[i]->logicalChannelIdentity;
const uint8_t lcid = rlc_bearer2add_list->list.array[i]->logicalChannelIdentity;
bool found = false;
for (int idx = 0; idx < sched_ctrl->dl_lc_num; idx++) {
if (sched_ctrl->dl_lc_ids[idx] == lcid) {
@@ -84,9 +86,21 @@ static void process_rlcBearerConfig(struct NR_CellGroupConfig__rlc_BearerToAddMo
}
if (!found) {
/* we assume that the first two are SRB bearers, and we add before
* other DRB */
uint8_t i = 0;
/* go beyond all SRBs */
while (i < sched_ctrl->dl_lc_num && sched_ctrl->dl_lc_ids[i] < 4)
i++;
uint8_t remaining_lcs = sched_ctrl->dl_lc_num - i;
memmove(&sched_ctrl->dl_lc_ids[i + 1], &sched_ctrl->dl_lc_ids[i], sizeof(sched_ctrl->dl_lc_ids[i]) * remaining_lcs);
sched_ctrl->dl_lc_ids[i] = lcid;
sched_ctrl->dl_lc_num++;
sched_ctrl->dl_lc_ids[sched_ctrl->dl_lc_num - 1] = lcid;
LOG_D(NR_MAC, "Adding LCID %d (%s %d)\n", lcid, lcid < 4 ? "SRB" : "DRB", lcid);
LOG_I(NR_MAC, "Adding LCID %d (%s %d)\n", lcid, lcid < 4 ? "SRB" : "DRB", lcid);
for (i = 0; i < sched_ctrl->dl_lc_num; ++i)
LOG_D(NR_MAC, "bearer %d LCID %s %d\n", i, lcid < 4 ? "SRB" : "DRB", sched_ctrl->dl_lc_ids[i]);
}
}
}

View File

@@ -329,7 +329,7 @@ static void nr_store_dlsch_buffer(module_id_t module_id, frame_t frame, sub_fram
const int lcid = sched_ctrl->dl_lc_ids[i];
const uint16_t rnti = UE->rnti;
LOG_D(NR_MAC, "In %s: UE %x: LCID %d\n", __FUNCTION__, rnti, lcid);
if (lcid == DL_SCH_LCID_DTCH && sched_ctrl->rrc_processing_timer > 0) {
if (lcid >= DL_SCH_LCID_DTCH && sched_ctrl->rrc_processing_timer > 0) {
continue;
}
start_meas(&RC.nrmac[module_id]->rlc_status_ind);

View File

@@ -90,6 +90,41 @@ 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 = malloc(sizeof(*lcid));
AssertFatal(lcid != NULL, "out of memory\n");
*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_remove_drb(rnti, drb->rb_id);
asn_sequence_del(&cellGroupConfig->rlc_BearerToAddModList->list, idx, 1);
int ret = ASN_SEQUENCE_ADD(&cellGroupConfig->rlc_BearerToReleaseList->list, lcid);
DevAssert(ret == 0);
}
}
return drbs_len;
}
void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
{
gNB_MAC_INST *mac = RC.nrmac[0];
@@ -196,6 +231,11 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req)
UE->CellGroup);
}
if (req->drbs_to_be_released > 0) {
resp.drbs_to_be_released_length =
handle_ue_context_drbs_release(req->rnti, req->drbs_to_be_released_length, req->drbs_to_be_released, UE->CellGroup);
}
if (req->rrc_container != NULL)
nr_rlc_srb_recv_sdu(req->rnti, DCCH, req->rrc_container, req->rrc_container_length);
@@ -204,7 +244,7 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req)
"RRC reconfiguration outcome unsuccessful, but no rollback mechanism implemented to come back to old configuration\n");
}
if (req->srbs_to_be_setup_length > 0 || req->drbs_to_be_setup_length > 0) {
if (req->srbs_to_be_setup_length > 0 || req->drbs_to_be_setup_length > 0 || req->drbs_to_be_released_length > 0) {
/* TODO: if we change e.g. BWP or MCS table, need to automatically call
* configure_UE_BWP() (form nr_mac_update_timers()) after some time? */
@@ -222,6 +262,15 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req)
/* works? */
nr_mac_update_cellgroup(RC.nrmac[0], req->rnti, UE->CellGroup);
/* remove the rlc_BearerToReleaseList, we don't need it anymore */
if (UE->CellGroup->rlc_BearerToReleaseList != NULL) {
//for (int i = 0; UE->CellGroup->rlc_BearerToReleaseList->list.count; ++i)
// free(UE->CellGroup->rlc_BearerToReleaseList->list.array[i]);
free(UE->CellGroup->rlc_BearerToReleaseList->list.array);
free(UE->CellGroup->rlc_BearerToReleaseList);
UE->CellGroup->rlc_BearerToReleaseList = NULL;
}
}
NR_SCHED_UNLOCK(&mac->sched_lock);

View File

@@ -164,21 +164,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++) {
const int lc_id = sched_ctrl->dl_lc_ids[i];
output += snprintf(output,
end - output,
"UE %04x: LCID %d: TX %9"PRIu64" RX %9"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);

View File

@@ -908,7 +908,7 @@ static void add_drb(int is_gnb,
__FILE__, __LINE__, __FUNCTION__);
exit(1);
}
LOG_I(PDCP, "%s:%s:%d: added DRB for UE ID/RNTI %ld\n", __FILE__, __FUNCTION__, __LINE__, rntiMaybeUEid);
LOG_I(PDCP, "%s:%s:%d: added DRB %ld for UE ID/RNTI %ld\n", __FILE__, __FUNCTION__, __LINE__, s->drb_Identity, rntiMaybeUEid);
}
void nr_pdcp_add_srbs(eNB_flag_t enb_flag, ue_id_t rntiMaybeUEid, NR_SRB_ToAddModList_t *const srb2add_list, const uint8_t security_modeP, uint8_t *const kRRCenc, uint8_t *const kRRCint)
@@ -938,6 +938,30 @@ void nr_pdcp_add_drbs(eNB_flag_t enb_flag,
LOG_W(PDCP, "nr_pdcp_add_drbs() with void list\n");
}
void nr_pdcp_remove_drb(ue_id_t ue_id, int drb_id, int pdu_session_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);
if (ue && ue->drb[drb_id-1] != NULL) {
ue->drb[drb_id-1]->delete_entity(ue->drb[drb_id-1]);
ue->drb[drb_id-1] = NULL;
nr_sdap_entity_t *sdap = nr_sdap_get_entity(ue_id, pdu_session_id);
if (sdap) {
if (1) {
NR_QFI_t qfi = 6;
nr_sdap_ue_qfi2drb_config(sdap, 0, ue_id, &qfi, 1, 1, false, false);
}
sdap->has_second_bearer = 0;
}
LOG_I(PDCP, "%s:%d:%s: removed drb %d from UE %ld and set SDAP\n", __FILE__, __LINE__, __FUNCTION__, drb_id, ue_id);
} else if (ue) {
LOG_W(PDCP, "%s:%d:%s: error: UE %ld has no DRB %d\n", __FILE__, __LINE__, __FUNCTION__, ue_id, drb_id);
} else {
LOG_E(PDCP, "%s:%d:%s: error: no such UE %ld\n", __FILE__, __LINE__, __FUNCTION__, ue_id);
}
nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
}
/* Dummy function due to dependency from LTE libraries */
bool rrc_pdcp_config_asn1_req(const protocol_ctxt_t *const ctxt_pP,
LTE_SRB_ToAddModList_t *const srb2add_list,

View File

@@ -55,6 +55,8 @@ void nr_pdcp_add_drbs(eNB_flag_t enb_flag,
uint8_t *const kUPint,
struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list);
void nr_pdcp_remove_drb(ue_id_t ue_id, int drb_id, int pdu_session_id);
void nr_DRB_preconfiguration(ue_id_t crntiMaybeUEid);
bool nr_pdcp_remove_UE(ue_id_t ue_id);

View File

@@ -860,6 +860,22 @@ void nr_rlc_add_drb(int rnti, int drb_id, const NR_RLC_BearerConfig_t *rlc_Beare
LOG_I(RLC, "%s:%s:%d: added DRB to UE with RNTI 0x%x\n", __FILE__, __FUNCTION__, __LINE__, rnti);
}
void nr_rlc_remove_drb(int rnti, int drb_id)
{
nr_rlc_manager_lock(nr_rlc_ue_manager);
nr_rlc_ue_t *ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, rnti);
if (ue && ue->drb[drb_id-1] != NULL) {
ue->drb[drb_id-1]->delete(ue->drb[drb_id-1]);
ue->drb[drb_id-1] = NULL;
LOG_I(RLC, "%s:%d:%s: removed drb %d from UE with RNTI 0x%x\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
} else if (ue) {
LOG_W(RLC, "%s:%d:%s: error: UE %04x has no DRB %d\n", __FILE__, __LINE__, __FUNCTION__, rnti, drb_id);
} else {
LOG_E(RLC, "%s:%d:%s: error: no such UE %04x\n", __FILE__, __LINE__, __FUNCTION__, rnti);
}
nr_rlc_manager_unlock(nr_rlc_ue_manager);
}
/* Dummy function due to dependency from LTE libraries */
rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP,
const LTE_SRB_ToAddModList_t * const srb2add_listP,

View File

@@ -41,6 +41,7 @@ struct NR_LogicalChannelConfig;
void nr_rlc_add_srb(int rnti, int srb_id, const NR_RLC_BearerConfig_t *rlc_BearerConfig);
void nr_rlc_add_drb(int rnti, int drb_id, const NR_RLC_BearerConfig_t *rlc_BearerConfig);
void nr_rlc_remove_drb(int rnti, int drb_id);
void nr_rlc_remove_ue(int rnti);

View File

@@ -836,7 +836,7 @@ int16_t do_RRCReconfiguration(
dl_dcch_msg.message.choice.c1->choice.rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration = ie;
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
if (true) {
xer_fprint(stdout, &asn_DEF_NR_DL_DCCH_Message, (void *)&dl_dcch_msg);
}

View File

@@ -85,16 +85,13 @@ void CU_update_UP_DL_tunnel(e1ap_bearer_setup_req_t *const req, instance_t insta
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));
in_addr_t addr = {0};
memcpy(&addr, &drb_p->DlUpParamList[0].tlAddress, sizeof(in_addr_t));
GtpuUpdateTunnelOutgoingAddressAndTeid(instance,
(ue_id & 0xFFFF),
(ebi_t)drb_p->id,
*(in_addr_t*)&newRemoteAddr.buffer,
addr,
drb_p->DlUpParamList[0].teId);
}
}

View File

@@ -240,6 +240,7 @@ typedef struct gNB_RRC_UE_s {
NR_SRB_ToAddModList_t *SRB_configList;
NR_SRB_ToAddModList_t *SRB_configList2[NR_RRC_TRANSACTION_IDENTIFIER_NUMBER];
NR_DRB_ToAddModList_t *DRB_configList;
NR_DRB_ToReleaseList_t *DRB_ReleaseList;
NR_DRB_ToAddModList_t *DRB_configList2[NR_RRC_TRANSACTION_IDENTIFIER_NUMBER];
NR_DRB_ToReleaseList_t *DRB_Release_configList2[NR_RRC_TRANSACTION_IDENTIFIER_NUMBER];
drb_t established_drbs[NGAP_MAX_DRBS_PER_UE];

View File

@@ -48,6 +48,7 @@
#include "common/utils/LOG/log.h"
#include "COMMON/mac_rrc_primitives.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"
@@ -568,12 +569,8 @@ void fill_DRB_configList(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_contex
if (!ue_p->DRB_configList)
ue_p->DRB_configList = CALLOC(1, sizeof(*ue_p->DRB_configList));
else
memset(ue_p->DRB_configList, 0, sizeof(*ue_p->DRB_configList));
if (!ue_p->DRB_configList2[xid])
ue_p->DRB_configList2[xid] = CALLOC(1, sizeof(**ue_p->DRB_configList2));
else
memset(ue_p->DRB_configList2[xid], 0, sizeof(**ue_p->DRB_configList2));
for (i = 0; i < ue_p->nb_of_pdusessions; i++) {
if (ue_p->pduSession[i].status >= PDU_SESSION_STATUS_DONE) {
continue;
@@ -680,7 +677,7 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c
xid,
SRB_configList2,
DRB_configList,
NULL,
ue_p->DRB_ReleaseList,
NULL,
NULL,
NULL,
@@ -691,6 +688,8 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c
NULL,
cellGroupConfig);
LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)buffer,size,"[MSG] RRC Reconfiguration\n");
ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToReleaseList, ue_p->DRB_ReleaseList);
ue_p->DRB_ReleaseList = NULL;
/* Free all NAS PDUs */
for (int i = 0; i < ue_p->nb_of_pdusessions; i++) {
@@ -1007,20 +1006,21 @@ static void rrc_gNB_process_RRCReconfigurationComplete(const protocol_ctxt_t *co
/* Refresh SRBs/DRBs */
LOG_D(NR_RRC, "Configuring PDCP DRBs/SRBs for UE %04x\n", ue_p->rnti);
ue_id_t reestablish_ue_id = 0;
if (DRB_configList && DRB_configList->list.array[0]->reestablishPDCP && *DRB_configList->list.array[0]->reestablishPDCP == NR_DRB_ToAddMod__reestablishPDCP_true) {
for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) {
nr_reestablish_rnti_map_t *nr_reestablish_rnti_map = &(RC.nrrrc[ctxt_pP->module_id])->nr_reestablish_rnti_map[i];
if (nr_reestablish_rnti_map->ue_id == ctxt_pP->rntiMaybeUEid) {
ue_context_pP->ue_context.ue_reconfiguration_after_reestablishment_counter++;
reestablish_ue_id = nr_reestablish_rnti_map[i].c_rnti;
LOG_D(NR_RRC, "Removing reestablish_rnti_map[%d] UEid %lx, RNTI %04x\n", i, nr_reestablish_rnti_map->ue_id, nr_reestablish_rnti_map->c_rnti);
// clear current C-RNTI from map
nr_reestablish_rnti_map->ue_id = 0;
nr_reestablish_rnti_map->c_rnti = 0;
break;
}
}
}
// we don't consider Reestablishment right now, uncomment to prevent segfault
//if (DRB_configList && DRB_configList->list.array[0]->reestablishPDCP && *DRB_configList->list.array[0]->reestablishPDCP == NR_DRB_ToAddMod__reestablishPDCP_true) {
// for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) {
// nr_reestablish_rnti_map_t *nr_reestablish_rnti_map = &(RC.nrrrc[ctxt_pP->module_id])->nr_reestablish_rnti_map[i];
// if (nr_reestablish_rnti_map->ue_id == ctxt_pP->rntiMaybeUEid) {
// ue_context_pP->ue_context.ue_reconfiguration_after_reestablishment_counter++;
// reestablish_ue_id = nr_reestablish_rnti_map[i].c_rnti;
// LOG_D(NR_RRC, "Removing reestablish_rnti_map[%d] UEid %lx, RNTI %04x\n", i, nr_reestablish_rnti_map->ue_id, nr_reestablish_rnti_map->c_rnti);
// // clear current C-RNTI from map
// nr_reestablish_rnti_map->ue_id = 0;
// nr_reestablish_rnti_map->c_rnti = 0;
// break;
// }
// }
//}
nr_pdcp_add_srbs(ctxt_pP->enb_flag, ctxt_pP->rntiMaybeUEid, SRB_configList, (ue_p->integrity_algorithm << 4) | ue_p->ciphering_algorithm, kRRCenc, kRRCint);
@@ -2649,10 +2649,14 @@ void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_contex
}
/* Instruction towards the DU for SRB2 configuration */
int nb_srb = 1;
f1ap_srb_to_be_setup_t srbs[nb_srb];
srbs[0].srb_id = 2;
srbs[0].lcid = 2;
int nb_srb = 0;
f1ap_srb_to_be_setup_t srbs[1] = {0};
if (UE->Srb[2].Active == 0) {
UE->Srb[2].Active = 1;
nb_srb = 1;
srbs[0].srb_id = 2;
srbs[0].lcid = 2;
}
f1ap_ue_context_modif_req_t ue_context_modif_req = {
.gNB_CU_ue_id = 0xffffffff, /* filled by F1 for the moment */
@@ -3036,6 +3040,152 @@ 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->gNB_ue_ngap_id;
bearer_req.rnti = ue->rnti;
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);
/* GIGANTIC HACK: DRBs would be added internally in fill_DRB_configList(),
* but it checks and will skip our request because the PDU session is up.
* Below, simply add the new bearer to DRB_configList so the reconfiguration
* will have all bearers */
generateDRB(ue,
drb_id,
&ue->pduSession[0],
rrc->configuration.enable_sdap,
rrc->security.do_drb_integrity,
rrc->security.do_drb_ciphering);
NR_DRB_ToAddMod_t *DRB_config = generateDRB_ASN1(&ue->established_drbs[drb_id - 1]);
asn1cSeqAdd(&ue->DRB_configList->list, DRB_config);
//asn1cSeqAdd(&ue->DRB_configList2[xid]->list, DRB_config);
/* 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, xid);
}
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;
while (idx < ue->DRB_configList->list.count) {
const NR_DRB_ToAddMod_t *drbc = ue->DRB_configList->list.array[idx];
if (drbc->drb_Identity == drb_id)
break;
++idx;
}
if (idx < ue->DRB_configList->list.count) {
nr_pdcp_remove_drb(rnti, drb_id, ue->pduSession[0].param.pdusession_id);
asn_sequence_del(&ue->DRB_configList->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}};
f1ap_ue_context_modif_req_t ue_context_modif_req = {
.gNB_CU_ue_id = 0xffffffff, /* filled by F1 for the moment */
.gNB_DU_ue_id = 0xffffffff, /* filled by F1 for the moment */
.rnti = ue->rnti,
.mcc = rrc->configuration.mcc[0],
.mnc = rrc->configuration.mnc[0],
.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;

View File

@@ -1197,6 +1197,20 @@ void nr_rrc_ue_process_masterCellGroup(const protocol_ctxt_t *const ctxt_pP,
sizeof(struct NR_CellGroupConfig__rlc_BearerToAddModList));
}
if( cellGroupConfig->rlc_BearerToReleaseList != NULL){
//TODO (perform the RLC bearer addition/modification as specified in 5.3.5.5.4)
if(NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->rlc_BearerToAddModList != NULL){
// Laurent: there are cases where the not NULL value is also not coming from a previous malloc
// so it is better to let the potential memory leak than corrupting the heap //free(NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->rlc_BearerToAddModList);
}
NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->rlc_BearerToReleaseList = calloc(1, sizeof(struct NR_CellGroupConfig__rlc_BearerToReleaseList));
memcpy(NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->rlc_BearerToReleaseList,cellGroupConfig->rlc_BearerToReleaseList,
sizeof(struct NR_CellGroupConfig__rlc_BearerToReleaseList));
} else {
free(NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->rlc_BearerToReleaseList);
NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->rlc_BearerToReleaseList = NULL;
}
if( cellGroupConfig->mac_CellGroupConfig != NULL){
//TODO (configure the MAC entity of this cell group as specified in 5.3.5.5.5)
LOG_I(RRC, "Received mac_CellGroupConfig from gNB\n");
@@ -1948,9 +1962,9 @@ nr_rrc_ue_establish_srb2(
for (cnt = 0; cnt < radioBearerConfig->drb_ToAddModList->list.count; cnt++) {
DRB_id = radioBearerConfig->drb_ToAddModList->list.array[cnt]->drb_Identity;
if (NR_UE_rrc_inst[ctxt_pP->module_id].DRB_config[gNB_index][DRB_id-1]) {
memcpy(NR_UE_rrc_inst[ctxt_pP->module_id].DRB_config[gNB_index][DRB_id-1],
radioBearerConfig->drb_ToAddModList->list.array[cnt], sizeof(NR_DRB_ToAddMod_t));
} else {
free(NR_UE_rrc_inst[ctxt_pP->module_id].DRB_config[gNB_index][DRB_id-1]);
}
{
//LOG_D(NR_RRC, "Adding DRB %ld %p\n", DRB_id-1, radioBearerConfig->drb_ToAddModList->list.array[cnt]);
NR_UE_rrc_inst[ctxt_pP->module_id].DRB_config[gNB_index][DRB_id-1] = radioBearerConfig->drb_ToAddModList->list.array[cnt];
int j;
@@ -2001,13 +2015,17 @@ nr_rrc_ue_establish_srb2(
if (radioBearerConfig->drb_ToReleaseList != NULL) {
for (i = 0; i < radioBearerConfig->drb_ToReleaseList->list.count; i++) {
DRB_id = *radioBearerConfig->drb_ToReleaseList->list.array[i];
free(NR_UE_rrc_inst[ctxt_pP->module_id].DRB_config[gNB_index][DRB_id-1]);
LOG_W(RRC, "trigger PDCP remove DRB, PDU session is hardcoded to 10!\n");
nr_pdcp_remove_drb(ctxt_pP->rntiMaybeUEid, DRB_id, 10);
//free(NR_UE_rrc_inst[ctxt_pP->module_id].DRB_config[gNB_index][DRB_id-1]);
}
}
if (NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->rlc_BearerToReleaseList != NULL) {
for (i = 0; i < NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->rlc_BearerToReleaseList->list.count; i++) {
NR_LogicalChannelIdentity_t lcid = *NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->rlc_BearerToReleaseList->list.array[i];
/* the RLC handles DRB IDs, and not using the LCID! */
nr_rlc_remove_drb(ctxt_pP->rntiMaybeUEid, lcid - 3);
LOG_I(NR_RRC, "[FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ (RB lcid %ld gNB %d release) --->][MAC_UE][MOD %02d][]\n",
ctxt_pP->frame, ctxt_pP->module_id, lcid, 0, ctxt_pP->module_id);
nr_rrc_mac_config_req_ue_logicalChannelBearer(ctxt_pP->module_id,0,0,lcid,false); //todo handle mac_LogicalChannelConfig

View File

@@ -25,6 +25,13 @@
#include <openair3/ocp-gtpu/gtp_itf.h>
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.h"
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
@@ -92,7 +99,25 @@ static bool nr_sdap_tx_entity(nr_sdap_entity_t *entity,
if(!pdcp_ent_has_sdap){
LOG_D(SDAP, "TX - DRB ID: %ld does not have SDAP\n", entity->qfi2drb_table[qfi].drb_id);
ret = nr_pdcp_data_req_drb(ctxt_p,
// mir
// Naive L4/L3 packet classifier
struct iphdr* hdr = (struct iphdr*)sdu_buffer;
if(hdr->protocol == IPPROTO_TCP){
//printf("TCP packet detected \n");
} else if(hdr->protocol == IPPROTO_UDP){
//printf("UDP packet detected \n");
} else if(hdr->protocol == IPPROTO_ICMP){
//printf("Ping packet detected \n");
if (entity->is_gnb && entity->has_second_bearer) {
sdap_drb_id += 1; //cnt%2;
}
printf("ping to bearer %ld\n", sdap_drb_id);
//cnt++;
}
ret = nr_pdcp_data_req_drb(ctxt_p,
srb_flag,
sdap_drb_id,
mui,
@@ -407,11 +432,12 @@ void nr_sdap_ue_qfi2drb_config(nr_sdap_entity_t *existing_sdap_entity, rb_id_t p
nr_sdap_entity_t *new_nr_sdap_entity(int is_gnb, bool has_sdap_rx, bool has_sdap_tx, ue_id_t ue_id, int pdusession_id, bool is_defaultDRB, uint8_t drb_identity, NR_QFI_t *mapped_qfi_2_add, uint8_t mappedQFIs2AddCount)
{
if (nr_sdap_get_entity(ue_id, pdusession_id)) {
LOG_E(SDAP, "SDAP Entity for UE already exists with RNTI/UE ID: %lu and PDU SESSION ID: %d\n", ue_id, pdusession_id);
LOG_I(SDAP, "SDAP Entity for UE already exists with RNTI/UE ID: %lu and PDU SESSION ID: %d\n", ue_id, pdusession_id);
nr_sdap_entity_t *existing_sdap_entity = nr_sdap_get_entity(ue_id, pdusession_id);
rb_id_t pdcp_entity = existing_sdap_entity->default_drb;
if(!is_gnb)
nr_sdap_ue_qfi2drb_config(existing_sdap_entity, pdcp_entity, ue_id, mapped_qfi_2_add, mappedQFIs2AddCount, drb_identity, has_sdap_rx, has_sdap_tx);
existing_sdap_entity->has_second_bearer = 1;
return existing_sdap_entity;
}
@@ -425,6 +451,7 @@ nr_sdap_entity_t *new_nr_sdap_entity(int is_gnb, bool has_sdap_rx, bool has_sdap
sdap_entity->ue_id = ue_id;
sdap_entity->pdusession_id = pdusession_id;
sdap_entity->is_gnb = is_gnb;
sdap_entity->tx_entity = nr_sdap_tx_entity;
sdap_entity->rx_entity = nr_sdap_rx_entity;

View File

@@ -77,6 +77,8 @@ void nr_pdcp_submit_sdap_ctrl_pdu(ue_id_t ue_id, rb_id_t sdap_ctrl_pdu_drb, nr_s
typedef struct nr_sdap_entity_s {
ue_id_t ue_id;
rb_id_t default_drb;
int is_gnb;
int has_second_bearer;
int pdusession_id;
qfi2drb_t qfi2drb_table[SDAP_MAX_QFI];

View File

@@ -763,7 +763,8 @@ static int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, uint32_t s
NGAP_PDUSessionResourceSetupItemCxtReq_t *item_p = ie->value.choice.PDUSessionResourceSetupListCxtReq.list.array[i];
msg->pdusession_param[i].pdusession_id = item_p->pDUSessionID;
allocCopy(&msg->pdusession_param[i].nas_pdu, *item_p->nAS_PDU);
if (item_p->nAS_PDU)
allocCopy(&msg->pdusession_param[i].nas_pdu, *item_p->nAS_PDU);
allocCopy(&msg->pdusession_param[i].pdusessionTransfer, item_p->pDUSessionResourceSetupRequestTransfer);
}
}

View File

@@ -119,10 +119,10 @@ do { \
/* Convert an array of char containing vALUE to x */
#define BUFFER_TO_UINT32(buf, x) \
do { \
x = (((uint32_t)(buf)[0] << 24) | \
(uint32_t)((buf)[1] << 16) | \
(uint32_t)((buf)[2] << 8) | \
(uint32_t)((buf)[3]); \
x = (((uint32_t)((buf)[0])) << 24) | \
(((uint32_t)((buf)[1])) << 16) | \
(((uint32_t)((buf)[2])) << 8) | \
(((uint32_t)((buf)[3]))); \
} while (0)
/* Convert an integer on 32 bits to an octet string from aSN1c tool */

View File

@@ -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));
auto 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;
}
auto 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);

View File

@@ -100,6 +100,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);

View File

@@ -41,6 +41,8 @@
#include <sys/epoll.h>
#include <string.h>
#include <simde/x86/avx2.h>
#include <common/utils/assertions.h>
#include <common/utils/LOG/log.h>
#include <common/utils/load_module_shlib.h>
@@ -54,7 +56,7 @@
#include "rfsimulator.h"
#define PORT 4043 //default TCP port for this simulator
#define CirSize 6144000 // 100ms is enough
#define CirSize 6144000 // 100ms is enough, needs to be 32 byte-aligned for SIMD
#define sampleToByte(a,b) ((a)*(b)*sizeof(sample_t))
#define byteToSample(a,b) ((a)/(sizeof(sample_t)*(b)))
@@ -148,7 +150,8 @@ typedef struct {
static void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
buffer_t *ptr=&bridge->buf[sock];
AssertFatal ( (ptr->circularBuf=(sample_t *) malloc(sampleToByte(CirSize,1))) != NULL, "");
int rc = posix_memalign((void**)&ptr->circularBuf, 32, sampleToByte(CirSize,1));
AssertFatal(rc == 0, "posix_memalign(): rc %d, errno %d, %s", rc, errno, strerror(errno));
ptr->circularBufEnd=((char *)ptr->circularBuf)+sampleToByte(CirSize,1);
ptr->conn_sock=sock;
ptr->lastReceivedTS=0;
@@ -620,12 +623,19 @@ static int rfsimulator_write_internal(rfsimulator_state_t *t, openair0_timestamp
samplesBlockHeader_t header= {t->typeStamp, nsamps, nbAnt, timestamp};
fullwrite(b->conn_sock,&header, sizeof(header), t);
sample_t tmpSamples[nsamps][nbAnt];
AssertFatal(nbAnt == 1, "nbAnt %d not handled yet\n", nbAnt);
for(int a=0; a<nbAnt; a++) {
sample_t *in=(sample_t *)samplesVoid[a];
for(int s=0; s<nsamps; s++)
tmpSamples[s][a]=in[s];
int s = 0;
for (; s < nsamps - 7; s += 8) {
simde__m256i sample = simde_mm256_loadu_si256(&in[s]);
simde_mm256_storeu_si256(&tmpSamples[s][a], sample);
}
for (; s < nsamps; s++)
tmpSamples[s][a] = in[s];
}
if (b->conn_sock >= 0 ) {
@@ -886,22 +896,49 @@ static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimest
CirSize);
}
else { // no channel modeling
double H_awgn_mimo[4][4] ={{1.0, 0.2, 0.1, 0.05}, //rx 0
{0.2, 1.0, 0.2, 0.1}, //rx 1
{0.1, 0.2, 1.0, 0.2}, //rx 2
{0.05, 0.1, 0.2, 1.0}};//rx 3
// this matrice corresponds to weights as indicated
const unsigned H_awgn_mimo[4][4] = {
{32, 8, 4, 1}, //rx 0: 1.0000, 0.2500, 0.1250, 0.0625
{8, 32, 8, 4}, //rx 1: 0.2500, 1.0000, 0.2500, 0.1250
{4, 8, 32, 8}, //rx 2: 0.1250, 0.2500, 1.0000, 0.2500
{1, 4, 8, 32} //rx 3: 0.0625, 0.1250, 0.2500, 1.0000
};
sample_t *out=(sample_t *)samplesVoid[a];
int nbAnt_tx = ptr->th.nbAnt;//number of Tx antennas
int nbAnt_tx = ptr->th.nbAnt > 0 ? ptr->th.nbAnt : 1;
//LOG_I(HW, "nbAnt_tx %d\n",nbAnt_tx);
for (int i=0; i < nsamps; i++) {//loop over nsamps
const unsigned h0 = H_awgn_mimo[a][0], h1 = H_awgn_mimo[a][1], h2 = H_awgn_mimo[a][2], h3 = H_awgn_mimo[a][3];
const simde__m256i factor = nbAnt_tx == 1
? simde_mm256_set_epi16(h0, h0, h0, h0, h0, h0, h0, h0, h0, h0, h0, h0, h0, h0, h0, h0)
: (nbAnt_tx == 2
? simde_mm256_set_epi16(h0, h1, h0, h1, h0, h1, h0, h1, h0, h1, h0, h1, h0, h1, h0, h1)
: simde_mm256_set_epi16(h0, h1, h2, h3, h0, h1, h2, h3, h0, h1, h2, h3, h0, h1, h2, h3));
int i = 0;
for (; i < nsamps && ((t->nextRxTstamp + i) % 8) != 0; ++i) {
for (int a_tx=0; a_tx<nbAnt_tx; a_tx++) { //sum up signals from nbAnt_tx antennas
out[i].r += (short)(ptr->circularBuf[((t->nextRxTstamp+i)*nbAnt_tx+a_tx)%CirSize].r*H_awgn_mimo[a][a_tx]);
out[i].i += (short)(ptr->circularBuf[((t->nextRxTstamp+i)*nbAnt_tx+a_tx)%CirSize].i*H_awgn_mimo[a][a_tx]);
} // end for a_tx
const sample_t sample = ptr->circularBuf[((t->nextRxTstamp + i) * nbAnt_tx + a_tx) % CirSize];
const unsigned factor = H_awgn_mimo[a][a_tx];
out[i].r += sample.r * factor >> 5;
out[i].i += sample.i * factor >> 5;
}
}
//LOG_I(HW, "nbAnt_tx %d nsamps %d (nextRxTstamp+i) %ld CirSize %d\n",nbAnt_tx, nsamps, t->nextRxTstamp + i, CirSize);
for (; i < nsamps - 7; i+=8) {//loop over nsamps
simde__m256i sample = simde_mm256_loadu_si256(&ptr->circularBuf[(t->nextRxTstamp + i) % CirSize]);
simde__m256i reslo = simde_mm256_srli_epi16(simde_mm256_mullo_epi16(sample, factor), 5);
simde__m256i reshi = simde_mm256_slli_epi16(simde_mm256_mulhi_epi16(sample, factor), 11);
simde__m256i res = simde_mm256_or_si256(reslo, reshi);
simde__m256i out256 = simde_mm256_loadu_si256(&out[i]);
simde_mm256_storeu_si256(&out[i], simde_mm256_adds_epi16(out256, res));
} // end for i (number of samps)
for (; i < nsamps; ++i) {
for (int a_tx=0; a_tx<nbAnt_tx; a_tx++) { //sum up signals from nbAnt_tx antennas
const sample_t sample = ptr->circularBuf[((t->nextRxTstamp + i) * nbAnt_tx + a_tx) % CirSize];
const unsigned factor = H_awgn_mimo[a][a_tx];
out[i].r += sample.r * factor >> 5;
out[i].i += sample.i * factor >> 5;
}
}
} // end of no channel modeling
} // end for a (number of rx antennas)
}