mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 20:50:28 +00:00
Compare commits
23 Commits
pre-commit
...
bearer-con
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
04d981d97b | ||
|
|
71705fb0cf | ||
|
|
471ee10b14 | ||
|
|
c218cf14f5 | ||
|
|
beadd5109b | ||
|
|
dcd0c83b11 | ||
|
|
556b2299b8 | ||
|
|
156a49175e | ||
|
|
bc58d63bcf | ||
|
|
457dee8f1c | ||
|
|
31eb6e1b40 | ||
|
|
8a40be05c1 | ||
|
|
f9b4e1a8b4 | ||
|
|
cb7b168cdf | ||
|
|
5e74a3b64b | ||
|
|
f9a0e8a9f9 | ||
|
|
c8fbd968e8 | ||
|
|
4af29d6420 | ||
|
|
891eaddac8 | ||
|
|
b76dafac23 | ||
|
|
2c9b640df9 | ||
|
|
f5c15847c9 | ||
|
|
b1c6a0baba |
@@ -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 ../../..
|
||||
)
|
||||
|
||||
|
||||
121
common/utils/telnetsrv/telnetsrv_bearer.c
Normal file
121
common/utils/telnetsrv/telnetsrv_bearer.c
Normal 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);
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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];
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user