Commit 85367ea1 authored by Jerome Peraldi's avatar Jerome Peraldi

Merge branch 'private/bugz127854' into 'sqn/3GPP_TTCN_System_Simulator'

Private/bugz127854

See merge request sequans/system/ttcn/openairinterface5g!26
parents fed058c6 63812554
...@@ -1698,6 +1698,7 @@ set(SS_SRC ...@@ -1698,6 +1698,7 @@ set(SS_SRC
${OPENAIR3_DIR}/SS/ss_gNB_sys_task.c ${OPENAIR3_DIR}/SS/ss_gNB_sys_task.c
${OPENAIR3_DIR}/SS/ss_gNB_vtp_task.c ${OPENAIR3_DIR}/SS/ss_gNB_vtp_task.c
${OPENAIR3_DIR}/SS/ss_gNB_drb_task.c ${OPENAIR3_DIR}/SS/ss_gNB_drb_task.c
${OPENAIR3_DIR}/SS/ss_gNB_vt_timer_task.c
${OPENAIR3_DIR}/SS/ss_utils.c ${OPENAIR3_DIR}/SS/ss_utils.c
) )
file(GLOB ss_sidl ${SIDL_CMPLR}/src/*.c) file(GLOB ss_sidl ${SIDL_CMPLR}/src/*.c)
......
...@@ -87,6 +87,7 @@ unsigned short config_frames[4] = {2,9,11,13}; ...@@ -87,6 +87,7 @@ unsigned short config_frames[4] = {2,9,11,13};
#include "udp_eNB_task.h" #include "udp_eNB_task.h"
#include "ss_gNB_drb_task.h" #include "ss_gNB_drb_task.h"
#include "ss_gNB_vtp_task.h" #include "ss_gNB_vtp_task.h"
#include "ss_gNB_vt_timer_task.h"
pthread_cond_t nfapi_sync_cond; pthread_cond_t nfapi_sync_cond;
pthread_mutex_t nfapi_sync_mutex; pthread_mutex_t nfapi_sync_mutex;
...@@ -437,6 +438,11 @@ static int create_gNB_tasks(void) { ...@@ -437,6 +438,11 @@ static int create_gNB_tasks(void) {
LOG_E(SCTP, "Create task for TASK_VTP failed\n"); LOG_E(SCTP, "Create task for TASK_VTP failed\n");
return -1; return -1;
} }
if(itti_create_task(TASK_VT_TIMER, ss_gNB_vt_timer_task, NULL) < 0) {
LOG_E(SCTP, "Create task for TASK_VT_TIMER failed\n");
return -1;
}
} }
LOG_I(NR_RRC, "Creating NR RRC gNB Task, that will also create TASKS\n"); LOG_I(NR_RRC, "Creating NR RRC gNB Task, that will also create TASKS\n");
......
...@@ -106,6 +106,7 @@ typedef struct ss_set_timinfo_s { ...@@ -106,6 +106,7 @@ typedef struct ss_set_timinfo_s {
typedef ss_set_timinfo_t ss_upd_timinfo_t; typedef ss_set_timinfo_t ss_upd_timinfo_t;
typedef struct ss_nrset_timinfo_s { typedef struct ss_nrset_timinfo_s {
uint16_t hsfn;
uint16_t sfn; uint16_t sfn;
uint32_t slot; uint32_t slot;
} ss_nrset_timinfo_t; } ss_nrset_timinfo_t;
......
...@@ -1604,7 +1604,7 @@ void pf_ul(module_id_t module_id, ...@@ -1604,7 +1604,7 @@ void pf_ul(module_id_t module_id,
gNB_MAC_INST *nrmac = RC.nrmac[module_id]; gNB_MAC_INST *nrmac = RC.nrmac[module_id];
NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[CC_id].ServingCellConfigCommon; NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[CC_id].ServingCellConfigCommon;
int min_rb = max(nrmac->min_grant_prb, 5); int min_rb = nrmac->min_grant_prb? nrmac->min_grant_prb:5;
// UEs that could be scheduled // UEs that could be scheduled
UEsched_t UE_sched[MAX_MOBILES_PER_GNB] = {0}; UEsched_t UE_sched[MAX_MOBILES_PER_GNB] = {0};
int remainUEs = max_num_ue; int remainUEs = max_num_ue;
......
...@@ -671,19 +671,21 @@ static void deliver_extra_pdu(nr_rlc_entity_um_t *entity, char *buffer, int size ...@@ -671,19 +671,21 @@ static void deliver_extra_pdu(nr_rlc_entity_um_t *entity, char *buffer, int size
int data_size; int data_size;
int is_first; int is_first;
int is_last; int is_last;
int sn_field_length;
nr_rlc_pdu_decoder_init(&decoder, buffer, size); nr_rlc_pdu_decoder_init(&decoder, buffer, size);
si = nr_rlc_pdu_decoder_get_bits(&decoder, 2); R(decoder); si = nr_rlc_pdu_decoder_get_bits(&decoder, 2); R(decoder);
sn_field_length = si ? entity->sn_field_length : 6;
is_first = (si & 0x2) == 0; is_first = (si & 0x2) == 0;
is_last = (si & 0x1) == 0; is_last = (si & 0x1) == 0;
if (entity->sn_field_length == 12) { if (sn_field_length == 12) {
nr_rlc_pdu_decoder_get_bits(&decoder, 2); R(decoder); nr_rlc_pdu_decoder_get_bits(&decoder, 2); R(decoder);
} }
sn = nr_rlc_pdu_decoder_get_bits(&decoder, entity->sn_field_length); sn = nr_rlc_pdu_decoder_get_bits(&decoder, sn_field_length);
R(decoder); R(decoder);
if (!is_first) { if (!is_first) {
......
...@@ -541,6 +541,22 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { ...@@ -541,6 +541,22 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) {
slot_ind.slot = sched_info->slot; slot_ind.slot = sched_info->slot;
oai_nfapi_slot_ind(&slot_ind); oai_nfapi_slot_ind(&slot_ind);
} }
if (RC.ss.mode >= SS_SOFTMODEM)
{
MessageDef *message_p = itti_alloc_new_message(TASK_VT_TIMER, INSTANCE_DEFAULT, SS_NRUPD_TIM_INFO);
if (message_p)
{
SS_NRUPD_TIM_INFO(message_p).slot = sched_info->slot;
SS_NRUPD_TIM_INFO(message_p).sfn = sched_info->frame;
int send_res = itti_send_msg_to_task(TASK_VT_TIMER, INSTANCE_DEFAULT, message_p);
if (send_res < 0)
{
LOG_E(NR_PHY, "[SS] Error in L1_Thread itti_send_msg_to_task");
}
}
}
} }
} }
LOG_D(NR_MAC, "fxn:%s Exit\n", __FUNCTION__); LOG_D(NR_MAC, "fxn:%s Exit\n", __FUNCTION__);
......
...@@ -39,6 +39,12 @@ typedef struct SSConfigContext_s { ...@@ -39,6 +39,12 @@ typedef struct SSConfigContext_s {
uint16_t ss_rnti_g; uint16_t ss_rnti_g;
uint8_t vtp_enabled; uint8_t vtp_enabled;
ss_set_timinfo_t vtinfo; ss_set_timinfo_t vtinfo;
hash_table_t *vt_timer_table ; // key is SFN_SLOT
/** Timing info */
uint8_t mu; /*subcarrierSpace*/
uint16_t hsfn;
uint16_t sfn;
uint8_t slot;
/** TODO: To add more */ /** TODO: To add more */
} SSConfigContext_t; } SSConfigContext_t;
...@@ -52,4 +58,3 @@ typedef enum { ...@@ -52,4 +58,3 @@ typedef enum {
SS_STATE_MAX_STATE SS_STATE_MAX_STATE
} SS_STATE_t; } SS_STATE_t;
#endif /* _SS_GNB_CONTEXT_ */ #endif /* _SS_GNB_CONTEXT_ */
...@@ -149,9 +149,25 @@ static void ss_send_drb_data(ss_drb_pdu_ind_t *pdu_ind) ...@@ -149,9 +149,25 @@ static void ss_send_drb_data(ss_drb_pdu_ind_t *pdu_ind)
for (int i = 0; i < ind.U_Plane.SlotData.PduSduList.v.RlcPdu.d; i++) { for (int i = 0; i < ind.U_Plane.SlotData.PduSduList.v.RlcPdu.d; i++) {
struct NR_RLC_PDU_Type* rlcPdu = &ind.U_Plane.SlotData.PduSduList.v.RlcPdu.v[i]; struct NR_RLC_PDU_Type* rlcPdu = &ind.U_Plane.SlotData.PduSduList.v.RlcPdu.v[i];
// TODO: suppose, we have UMD NoSN/SN6Bit RLC PDU
rlcPdu->d = NR_RLC_PDU_Type_UMD; rlcPdu->d = NR_RLC_PDU_Type_UMD;
rlcPdu->v.UMD.d = ((pdu_ind->sdu[0] & 0xC0) == 0) ? NR_RLC_UMD_PDU_Type_NoSN : NR_RLC_UMD_PDU_Type_SN6Bit; long *sn_FieldLength = NULL;
NR_RLC_BearerConfig_t *rlcBearer = RC.NR_RB_Config[pdu_ind->physCellId][pdu_ind->drb_id+2].RlcBearer;
if (rlcBearer && rlcBearer->rlc_Config && rlcBearer->rlc_Config->choice.um_Bi_Directional)
{
sn_FieldLength = rlcBearer->rlc_Config->choice.um_Bi_Directional->ul_UM_RLC.sn_FieldLength;
}
if ((pdu_ind->sdu[0] & 0xC0) == 0)
{
rlcPdu->v.UMD.d = NR_RLC_UMD_PDU_Type_NoSN;
}
else if (sn_FieldLength && *sn_FieldLength == SQN_NR_SN_FieldLengthUM_e_size6)
{
rlcPdu->v.UMD.d = NR_RLC_UMD_PDU_Type_SN6Bit;
}
else if (sn_FieldLength && *sn_FieldLength == SQN_NR_SN_FieldLengthUM_e_size12)
{
rlcPdu->v.UMD.d = NR_RLC_UMD_PDU_Type_SN12Bit;
}
if (rlcPdu->d == NR_RLC_PDU_Type_UMD && rlcPdu->v.UMD.d == NR_RLC_UMD_PDU_Type_NoSN) if (rlcPdu->d == NR_RLC_PDU_Type_UMD && rlcPdu->v.UMD.d == NR_RLC_UMD_PDU_Type_NoSN)
{ {
...@@ -185,9 +201,28 @@ static void ss_send_drb_data(ss_drb_pdu_ind_t *pdu_ind) ...@@ -185,9 +201,28 @@ static void ss_send_drb_data(ss_drb_pdu_ind_t *pdu_ind)
DevAssert(data->v != NULL); DevAssert(data->v != NULL);
memcpy(data->v, pdu_ind->sdu + pdu_header_size, data->d); memcpy(data->v, pdu_ind->sdu + pdu_header_size, data->d);
} }
else if (rlcPdu->d == NR_RLC_PDU_Type_UMD && rlcPdu->v.UMD.d == NR_RLC_UMD_PDU_Type_SN12Bit)
{
struct NR_RLC_UMD_HeaderSN12Bit_Type *header = &rlcPdu->v.UMD.v.SN12Bit.Header;
NR_RLC_UMD_Data_Type *data = &rlcPdu->v.UMD.v.SN12Bit.Data;
int pdu_header_size = 2;
bits_copy_to_array((char *)header->SegmentationInfo, 0, (const char *)pdu_ind->sdu, 2);
bits_copy_to_array((char *)header->SequenceNumber, 4, (const char *)pdu_ind->sdu, 12);
if (pdu_ind->sdu[0] & 0x80)
{
pdu_header_size += 2;
header->SegmentOffset.d = true;
bits_copy_to_array((char *)header->SegmentOffset.v, 16, (const char *)pdu_ind->sdu, 16);
}
data->d = pdu_ind->sdu_size - pdu_header_size;
LOG_A(GNB_APP, "[SS_DRB] Length of RLC PDU received in NR_DRB_COMMON_IND: %lu\n", pdu_ind->sdu_size);
data->v = CALLOC(1, data->d);
DevAssert(data->v != NULL);
memcpy(data->v, pdu_ind->sdu + pdu_header_size, data->d);
}
else else
{ {
LOG_E(GNB_APP, "[SS_DRB] only UMD NoSN/SN6Bit are handled in RLC PDU in NR_DRB_COMMON_IND\n"); LOG_E(GNB_APP, "[SS_DRB] only UMD NoSN/SN6Bit/SN12Bit are handled in RLC PDU in NR_DRB_COMMON_IND\n");
} }
} }
} }
...@@ -237,14 +272,12 @@ static void ss_task_handle_drb_pdu_req(struct NR_DRB_COMMON_REQ *req) ...@@ -237,14 +272,12 @@ static void ss_task_handle_drb_pdu_req(struct NR_DRB_COMMON_REQ *req)
_drb_data_type = DRB_RlcPdu; _drb_data_type = DRB_RlcPdu;
RC.nr_drb_data_type = DRB_RlcPdu; RC.nr_drb_data_type = DRB_RlcPdu;
message_p = itti_alloc_new_message(task_id, 0, SS_DRB_PDU_REQ);
assert(message_p);
memset(SS_DRB_PDU_REQ(message_p).sdu, 0, SDU_SIZE);
for (int j = 0; j < req->U_Plane.SlotDataList.v[i].PduSduList.v.RlcPdu.d; j++) for (int j = 0; j < req->U_Plane.SlotDataList.v[i].PduSduList.v.RlcPdu.d; j++)
{ {
struct NR_RLC_PDU_Type *rlcPdu = &req->U_Plane.SlotDataList.v[i].PduSduList.v.RlcPdu.v[j]; struct NR_RLC_PDU_Type *rlcPdu = &req->U_Plane.SlotDataList.v[i].PduSduList.v.RlcPdu.v[j];
message_p = itti_alloc_new_message(task_id, 0, SS_DRB_PDU_REQ);
assert(message_p);
memset(SS_DRB_PDU_REQ(message_p).sdu, 0, SDU_SIZE);
if (rlcPdu->d == NR_RLC_PDU_Type_UMD && rlcPdu->v.UMD.d == NR_RLC_UMD_PDU_Type_NoSN) if (rlcPdu->d == NR_RLC_PDU_Type_UMD && rlcPdu->v.UMD.d == NR_RLC_UMD_PDU_Type_NoSN)
{ {
...@@ -275,9 +308,39 @@ static void ss_task_handle_drb_pdu_req(struct NR_DRB_COMMON_REQ *req) ...@@ -275,9 +308,39 @@ static void ss_task_handle_drb_pdu_req(struct NR_DRB_COMMON_REQ *req)
LOG_A(GNB_APP, "[SS_DRB] Length of RLC PDU received in NR_DRB_COMMON_REQ (SN6Bit): %lu\n", pdu_header_size + data->d); LOG_A(GNB_APP, "[SS_DRB] Length of RLC PDU received in NR_DRB_COMMON_REQ (SN6Bit): %lu\n", pdu_header_size + data->d);
memcpy(SS_DRB_PDU_REQ(message_p).sdu + pdu_header_size, data->v, data->d); memcpy(SS_DRB_PDU_REQ(message_p).sdu + pdu_header_size, data->v, data->d);
} }
else if (rlcPdu->d == NR_RLC_PDU_Type_UMD && rlcPdu->v.UMD.d == NR_RLC_UMD_PDU_Type_SN12Bit)
{
struct NR_RLC_UMD_HeaderSN12Bit_Type *header = &rlcPdu->v.UMD.v.SN12Bit.Header;
NR_RLC_UMD_Data_Type *data = &rlcPdu->v.UMD.v.SN12Bit.Data;
int pdu_header_size = 2;
bits_copy_from_array((char *)SS_DRB_PDU_REQ(message_p).sdu, 0, (const char *)header->SegmentationInfo, 2);
bits_copy_from_array((char *)SS_DRB_PDU_REQ(message_p).sdu, 4, (const char *)header->SequenceNumber, 12);
if (header->SegmentOffset.d)
{
pdu_header_size += 2;
bits_copy_from_array((char *)SS_DRB_PDU_REQ(message_p).sdu, 16, (const char *)header->SegmentOffset.v, 16);
//we consider only RLC payload is there meaning that RLC packet is segmented
RC.nr_drb_data_type = DRB_RlcSdu;
}
SS_DRB_PDU_REQ(message_p).sdu_size = pdu_header_size + data->d;
LOG_A(GNB_APP, "[SS_DRB] Length of RLC PDU received in NR_DRB_COMMON_REQ: %lu\n", pdu_header_size + data->d);
memcpy(SS_DRB_PDU_REQ(message_p).sdu + pdu_header_size, data->v, data->d);
}
else else
{ {
LOG_E(GNB_APP, "[SS_DRB] only UMD NoSN/SN6Bit are handled in RLC PDU in NR_DRB_COMMON_REQ\n"); LOG_E(GNB_APP, "[SS_DRB] only UMD NoSN/SN6Bit/SN12Bit are handled in RLC PDU in NR_DRB_COMMON_REQ\n");
}
SS_DRB_PDU_REQ(message_p).drb_id = req->Common.RoutingInfo.v.RadioBearerId.v.Drb;
SS_DRB_PDU_REQ(message_p).rnti = SS_context.ss_rnti_g;
if (!nr_vt_timer_push_msg(&req->Common.TimingInfo, req->U_Plane.SlotDataList.v[i].SlotOffset, task_id, instance_g, message_p))
{
int send_res = itti_send_msg_to_task(task_id, instance_g, message_p);
if (send_res < 0)
{
LOG_E(GNB_APP, "[SS_DRB] Error in itti_send_msg_to_task\n");
}
LOG_A(GNB_APP, "[SS_DRB] Send res: %d\n", send_res);
} }
} }
} }
...@@ -287,17 +350,30 @@ static void ss_task_handle_drb_pdu_req(struct NR_DRB_COMMON_REQ *req) ...@@ -287,17 +350,30 @@ static void ss_task_handle_drb_pdu_req(struct NR_DRB_COMMON_REQ *req)
_drb_data_type = DRB_PdcpSdu; _drb_data_type = DRB_PdcpSdu;
RC.nr_drb_data_type = DRB_PdcpSdu; RC.nr_drb_data_type = DRB_PdcpSdu;
task_id = TASK_PDCP_ENB;
message_p = itti_alloc_new_message(task_id, 0, SS_DRB_PDU_REQ);
assert(message_p);
memset(SS_DRB_PDU_REQ(message_p).sdu, 0, SDU_SIZE);
for (int j = 0; j < req->U_Plane.SlotDataList.v[i].PduSduList.v.PdcpSdu.d; j++) for (int j = 0; j < req->U_Plane.SlotDataList.v[i].PduSduList.v.PdcpSdu.d; j++)
{ {
task_id = TASK_PDCP_ENB;
message_p = itti_alloc_new_message(task_id, 0, SS_DRB_PDU_REQ);
assert(message_p);
memset(SS_DRB_PDU_REQ(message_p).sdu, 0, SDU_SIZE);
NR_PDCP_SDU_Type *pdcpSdu = &req->U_Plane.SlotDataList.v[i].PduSduList.v.PdcpSdu.v[j]; NR_PDCP_SDU_Type *pdcpSdu = &req->U_Plane.SlotDataList.v[i].PduSduList.v.PdcpSdu.v[j];
SS_DRB_PDU_REQ(message_p).sdu_size = pdcpSdu->d; SS_DRB_PDU_REQ(message_p).sdu_size = pdcpSdu->d;
memcpy(SS_DRB_PDU_REQ(message_p).sdu, pdcpSdu->v, pdcpSdu->d); memcpy(SS_DRB_PDU_REQ(message_p).sdu, pdcpSdu->v, pdcpSdu->d);
LOG_A(GNB_APP, "[SS_DRB] Length of PDCP SDU received in NR_DRB_COMMON_REQ: %lu, SDU:\n", pdcpSdu->d); LOG_A(GNB_APP, "[SS_DRB] Length of PDCP SDU received in NR_DRB_COMMON_REQ: %lu, SDU:\n", pdcpSdu->d);
SS_DRB_PDU_REQ(message_p).drb_id = req->Common.RoutingInfo.v.RadioBearerId.v.Drb;
SS_DRB_PDU_REQ(message_p).rnti = SS_context.ss_rnti_g;
if (!nr_vt_timer_push_msg(&req->Common.TimingInfo, req->U_Plane.SlotDataList.v[i].SlotOffset, task_id, instance_g, message_p))
{
int send_res = itti_send_msg_to_task(task_id, instance_g, message_p);
if (send_res < 0)
{
LOG_E(GNB_APP, "[SS_DRB] Error in itti_send_msg_to_task\n");
}
LOG_A(GNB_APP, "[SS_DRB] Send res: %d\n", send_res);
}
} }
} }
else else
...@@ -305,17 +381,6 @@ static void ss_task_handle_drb_pdu_req(struct NR_DRB_COMMON_REQ *req) ...@@ -305,17 +381,6 @@ static void ss_task_handle_drb_pdu_req(struct NR_DRB_COMMON_REQ *req)
LOG_E(GNB_APP, "[SS_DRB] NR_DRB_COMMON_REQ requested NR_L2DataList_Type %d that is not yet implemented\n", req->U_Plane.SlotDataList.v[i].PduSduList.d); LOG_E(GNB_APP, "[SS_DRB] NR_DRB_COMMON_REQ requested NR_L2DataList_Type %d that is not yet implemented\n", req->U_Plane.SlotDataList.v[i].PduSduList.d);
} }
} }
SS_DRB_PDU_REQ(message_p).drb_id = req->Common.RoutingInfo.v.RadioBearerId.v.Drb;
SS_DRB_PDU_REQ(message_p).rnti = SS_context.ss_rnti_g;
int send_res = itti_send_msg_to_task(task_id, instance_g, message_p);
if (send_res < 0)
{
LOG_E(GNB_APP, "[SS_DRB] Error in itti_send_msg_to_task\n");
}
LOG_A(GNB_APP, "[SS_DRB] Send res: %d\n", send_res);
} }
static void ss_gNB_read_from_drb_socket(acpCtx_t ctx) static void ss_gNB_read_from_drb_socket(acpCtx_t ctx)
......
...@@ -696,7 +696,7 @@ void *ss_gNB_sys_process_itti_msg(void *notUsed) ...@@ -696,7 +696,7 @@ void *ss_gNB_sys_process_itti_msg(void *notUsed)
{ {
MessageDef *received_msg = NULL; MessageDef *received_msg = NULL;
int result; int result;
static ss_nrset_timinfo_t tinfo = {.sfn = 0xFFFF, .slot = 0xFFFFFFFF}; static ss_nrset_timinfo_t tinfo = {.hsfn=0xFFFF, .sfn = 0xFFFF, .slot = 0xFFFFFFFF};
itti_receive_msg(TASK_SYS_GNB, &received_msg); itti_receive_msg(TASK_SYS_GNB, &received_msg);
...@@ -710,6 +710,18 @@ void *ss_gNB_sys_process_itti_msg(void *notUsed) ...@@ -710,6 +710,18 @@ void *ss_gNB_sys_process_itti_msg(void *notUsed)
LOG_D(GNB_APP, "TASK_SYS_GNB received SS_NRUPD_TIM_INFO with sfn=%d slot=%d\n", SS_NRUPD_TIM_INFO(received_msg).sfn, SS_NRUPD_TIM_INFO(received_msg).slot); LOG_D(GNB_APP, "TASK_SYS_GNB received SS_NRUPD_TIM_INFO with sfn=%d slot=%d\n", SS_NRUPD_TIM_INFO(received_msg).sfn, SS_NRUPD_TIM_INFO(received_msg).slot);
tinfo.slot = SS_NRUPD_TIM_INFO(received_msg).slot; tinfo.slot = SS_NRUPD_TIM_INFO(received_msg).slot;
tinfo.sfn = SS_NRUPD_TIM_INFO(received_msg).sfn; tinfo.sfn = SS_NRUPD_TIM_INFO(received_msg).sfn;
/*WA: calculate hsfn here */
if(tinfo.hsfn == 0xFFFF){
tinfo.hsfn = 0;
} else if(tinfo.sfn == 1023 && SS_NRUPD_TIM_INFO(received_msg).slot == 0){
tinfo.hsfn++;
if(tinfo.hsfn == 1024){
tinfo.hsfn = 0;
}
}
SS_context.hsfn = tinfo.hsfn;
SS_context.sfn = tinfo.sfn;
SS_context.slot = tinfo.slot;
g_log->sfn = tinfo.sfn; g_log->sfn = tinfo.sfn;
g_log->sf = tinfo.slot; g_log->sf = tinfo.slot;
} }
...@@ -1101,6 +1113,7 @@ bool ss_task_sys_nr_handle_cellConfig5G(struct NR_CellConfigRequest_Type *p_req, ...@@ -1101,6 +1113,7 @@ bool ss_task_sys_nr_handle_cellConfig5G(struct NR_CellConfigRequest_Type *p_req,
*RC.nrrrc[gnbId]->configuration.scc->ssbSubcarrierSpacing = *RC.nrrrc[gnbId]->configuration.scc->ssbSubcarrierSpacing =
RC.nrrrc[gnbId]->configuration.scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[i]->subcarrierSpacing; RC.nrrrc[gnbId]->configuration.scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[i]->subcarrierSpacing;
SS_context.mu = RC.nrrrc[gnbId]->configuration.scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[i]->subcarrierSpacing;
LOG_A(GNB_APP, "fxn:%s DL scs_SpecificCarrierList.offsetToCarrier :%ld subcarrierSpacing:%ld carrierBandwidth:%ld \n", LOG_A(GNB_APP, "fxn:%s DL scs_SpecificCarrierList.offsetToCarrier :%ld subcarrierSpacing:%ld carrierBandwidth:%ld \n",
...@@ -1422,6 +1435,26 @@ bool ss_task_sys_nr_handle_cellConfigRadioBearer(struct NR_SYSTEM_CTRL_REQ *req) ...@@ -1422,6 +1435,26 @@ bool ss_task_sys_nr_handle_cellConfigRadioBearer(struct NR_SYSTEM_CTRL_REQ *req)
else if(BearerList->v[i].Config.v.AddOrReconfigure.RlcBearer.v.v.Config.Rlc.v.Rb.v.d == NR_RLC_RbConfig_Type_TM) else if(BearerList->v[i].Config.v.AddOrReconfigure.RlcBearer.v.v.Config.Rlc.v.Rb.v.d == NR_RLC_RbConfig_Type_TM)
{ {
//TODO: TransparentMode //TODO: TransparentMode
// It is a workaround to provide SN size
if (BearerList->v[i].Id.d == NR_RadioBearerId_Type_Drb)
{
if (BearerList->v[i].Config.v.AddOrReconfigure.RlcBearer.v.v.Config.Rlc.v.Rb.v.v.TM && BearerList->v[i].Config.v.AddOrReconfigure.RlcBearer.v.v.Config.Rlc.v.TestMode.d)
{
if (BearerList->v[i].Config.v.AddOrReconfigure.RlcBearer.v.v.Config.Rlc.v.TestMode.v.v.Info.d == NR_RLC_TestModeInfo_Type_TransparentMode)
{
if (BearerList->v[i].Config.v.AddOrReconfigure.RlcBearer.v.v.Config.Rlc.v.TestMode.v.v.Info.v.TransparentMode.d == NR_RLC_TransparentMode_Umd)
{
rlc->present = NR_RLC_Config_PR_um_Bi_Directional;
rlc->choice.um_Bi_Directional = CALLOC(1,sizeof(*rlc->choice.um_Bi_Directional));
NR_UL_UM_RLC_t *ul_UM_RLC = &rlc->choice.um_Bi_Directional->ul_UM_RLC;
NR_DL_UM_RLC_t *dl_UM_RLC = &rlc->choice.um_Bi_Directional->dl_UM_RLC;
ul_UM_RLC->sn_FieldLength = CALLOC(1,sizeof(long));
dl_UM_RLC->sn_FieldLength = CALLOC(1,sizeof(long));
*(ul_UM_RLC->sn_FieldLength) = *(dl_UM_RLC->sn_FieldLength) = BearerList->v[i].Config.v.AddOrReconfigure.RlcBearer.v.v.Config.Rlc.v.TestMode.v.v.Info.v.TransparentMode.v.Umd;
}
}
}
}
} }
else else
{ {
......
/*
* 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 "intertask_interface.h"
#include "common/ran_context.h"
#include "ss_gNB_context.h"
#include "ss_gNB_proxy_iface.h"
#include "ss_gNB_vt_timer_task.h"
#include <assert.h>
extern SSConfigContext_t SS_context;
static inline uint32_t _vt_sfn_slot(uint16_t sfn, uint8_t slot)
{
return ((sfn << 8) | slot);
}
/*
* Function : _vt_subtract_slot
* Description: Helper function to substract offset to SFN_SLOT
*/
static void _vt_subtract_slot(uint16_t *frameP, uint8_t *slotP, int offset)
{
if (*slotP < offset)
{
*frameP = (*frameP+1024-1)%1024;
}
uint8_t slotsPerFrame = 10 *(1<<SS_context.mu);
*slotP = (*slotP+slotsPerFrame-offset)%slotsPerFrame;
}
/*
* Function : _vt_add_slot
* Description: Helper function to add offset to SFN_SLOT
*/
static void _vt_add_slot(uint16_t *frameP, uint8_t *slotP, int offset)
{
if (offset > 0) {
uint8_t slotsPerFrame = 10 *(1<<SS_context.mu);
*frameP = (*frameP + ((*slotP + offset) / slotsPerFrame)) % 1024;
*slotP = ((*slotP + offset) % slotsPerFrame);
} else {
_vt_subtract_slot(frameP,slotP,0-offset);
}
}
/*
* Function : _nr_msg_can_be_queued
* Description: Helper function to check if the received MSG shall be queued
*/
uint8_t _nr_msg_can_be_queued(ss_nrset_timinfo_t * req_tinfo)
{
ss_nrset_timinfo_t curr_tinfo;
curr_tinfo.sfn = SS_context.sfn;
curr_tinfo.slot = SS_context.slot;
LOG_D(GNB_APP,"VT_TIMER Enter msg_can_be_queued for SFN %d , SLOT %d\n",req_tinfo->sfn,req_tinfo->slot);
/*It is nonsense to check req_tinfo is after curr_tinfo */
if(req_tinfo->sfn != curr_tinfo.sfn || ((req_tinfo->sfn == curr_tinfo.sfn) && (req_tinfo->slot - curr_tinfo.slot) > 0) )
{
/* The actual DL message would be transfered in next slot after receiving SS_NRUPD_TIM_INFO(last DL slot TIME update) */
_vt_subtract_slot(&req_tinfo->sfn,&req_tinfo->slot, 1);
LOG_D(GNB_APP,"VT_TIMER MSG to be queued TRUE for SFN %d , SLOT %d\n",req_tinfo->sfn,req_tinfo->slot);
return true;
}
return false;
}
/*
* Function : _nr_vt_timer_setup
* Description: Function to set upt the VT timer for the SFN_SLOT
* and store the message to received
*/
static uint8_t _nr_vt_timer_setup(ss_nrset_timinfo_t* tinfo, task_id_t task_id,instance_t instance, void *msg)
{
uint32_t sfnSlotKey =_vt_sfn_slot(tinfo->sfn,tinfo->slot);
vt_timer_elm_t *timer_ele_p = calloc(1, sizeof(vt_timer_elm_t));
assert(timer_ele_p);
timer_ele_p->instance = instance;
timer_ele_p->task_id = task_id;
timer_ele_p->msg = msg;
if (hashtable_insert(SS_context.vt_timer_table,
(hash_key_t)sfnSlotKey, (void *)timer_ele_p) == HASH_TABLE_OK)
{
LOG_D(GNB_APP,"VT_TIMER setup for SFN %d , SLOT %d\n", tinfo->sfn,tinfo->slot);
return 1;
}
return 0;
}
void nr_vt_add_slot(struct TimingInfo_Type* at, int offset)
{
if (at!=NULL && at->d == TimingInfo_Type_SubFrame)
{
uint16_t sfn = SS_context.sfn;
uint8_t slot = SS_context.slot;
uint8_t slotsPerSubFrame = 1<<SS_context.mu;
if (at->v.SubFrame.SFN.d == SystemFrameNumberInfo_Type_Number)
{
sfn = at->v.SubFrame.SFN.v.Number;
}
if (at->v.SubFrame.Subframe.d == SubFrameInfo_Type_Number)
{
slot = at->v.SubFrame.Subframe.v.Number * slotsPerSubFrame;
}
if(at->v.SubFrame.Slot.d == SlotTimingInfo_Type_SlotOffset)
{
if(at->v.SubFrame.Slot.v.SlotOffset.d >= SlotOffset_Type_Numerology1){
slot += at->v.SubFrame.Slot.v.SlotOffset.v.Numerology1;
}
}
if(offset !=0){
_vt_add_slot(&sfn, &slot, offset);
}
at->d = TimingInfo_Type_SubFrame;
at->v.SubFrame.SFN.d = SystemFrameNumberInfo_Type_Number;
at->v.SubFrame.SFN.v.Number = sfn;
at->v.SubFrame.Subframe.d = SubFrameInfo_Type_Number;
at->v.SubFrame.Subframe.v.Number = slot/slotsPerSubFrame;
at->v.SubFrame.Slot.d = SlotTimingInfo_Type_SlotOffset;
at->v.SubFrame.Slot.v.SlotOffset.d = (enum SlotOffset_Type_Sel)(SS_context.mu+1);
if(at->v.SubFrame.Slot.v.SlotOffset.d > SlotOffset_Type_Numerology0){
at->v.SubFrame.Slot.v.SlotOffset.v.Numerology1 = slot%slotsPerSubFrame;
}else {
at->v.SubFrame.Slot.v.SlotOffset.v.Numerology0 = true;
}
}
}
int nr_vt_timer_push_msg(struct TimingInfo_Type* at, int32_t slotOffset, task_id_t task_id,instance_t instance, MessageDef *msg_p)
{
int msg_queued = 0;
if (at != NULL && at->d == TimingInfo_Type_SubFrame)
{
ss_nrset_timinfo_t timer_tinfo;
if (at->v.SubFrame.SFN.d == SystemFrameNumberInfo_Type_Number)
{
timer_tinfo.sfn = at->v.SubFrame.SFN.v.Number;
}
if (at->v.SubFrame.Subframe.d == SubFrameInfo_Type_Number)
{
uint8_t slotsPerSubFrame = 1<<SS_context.mu;
timer_tinfo.slot = at->v.SubFrame.Subframe.v.Number * slotsPerSubFrame;
}
else
{
return 0;
}
if(at->v.SubFrame.Slot.d == SlotTimingInfo_Type_SlotOffset)
{
if(at->v.SubFrame.Slot.v.SlotOffset.d >= SlotOffset_Type_Numerology1){
timer_tinfo.slot += at->v.SubFrame.Slot.v.SlotOffset.v.Numerology1;
}
}
_vt_add_slot(&timer_tinfo.sfn,&timer_tinfo.slot, slotOffset);
msg_queued = _nr_msg_can_be_queued(&timer_tinfo);
if(msg_queued)
{
msg_queued = _nr_vt_timer_setup(&timer_tinfo, task_id, instance ,msg_p);
LOG_D(GNB_APP, "Message Queued as the scheduled SFN is %d SLOT: %d and curr SFN %d , SLOT %d, msg_queued: %d\r\n",
timer_tinfo.sfn,timer_tinfo.slot, SS_context.sfn,SS_context.slot, msg_queued);
}
}
return msg_queued;
}
/*
* Function : ss_nr_vt_timer_check
* Description: Function to check if any SFN_SF is timed out and forward
* the stored message to requested TASK.
*/
static inline void ss_nr_vt_timer_check(ss_nrset_timinfo_t tinfo)
{
vt_timer_elm_t *timer_ele_p;
uint32_t sfnSlotKey =_vt_sfn_slot(tinfo.sfn,tinfo.slot);
while (hashtable_is_key_exists(SS_context.vt_timer_table, (hash_key_t)sfnSlotKey) == HASH_TABLE_OK)
{
LOG_D(GNB_APP,"VT_TIMER Timeout sending curr SFN %d SLOT %d\n",SS_context.sfn,SS_context.slot);
hashtable_get(SS_context.vt_timer_table, (hash_key_t)sfnSlotKey, (void **)&timer_ele_p);
AssertFatal(timer_ele_p, "VT Timer - timer element is NULL");
LOG_D(GNB_APP,"VT_TIMER Enter check SFN %d , SLOT %d taskID %d timer_ele.task_id instance %ld \n",
tinfo.sfn,tinfo.slot, timer_ele_p->task_id,timer_ele_p->instance);
int send_res = itti_send_msg_to_task(timer_ele_p->task_id,timer_ele_p->instance, (MessageDef *)timer_ele_p->msg);
if (send_res < 0)
{
LOG_E(GNB_APP, "[VT_TIMER] Error in SS_VT_TIME_OUT itti_send_msg_to_task");
}
else
{
LOG_A(GNB_APP,"VT_TIMER Sent message to taskID %d timer_ele.task_id instance %ld \n",
timer_ele_p->task_id,timer_ele_p->instance);
hashtable_remove(SS_context.vt_timer_table, (hash_key_t)sfnSlotKey);
}
LOG_D(GNB_APP,"VT_TIMER Timeout sending done curr SFN %d SLOT %d\n",
SS_context.sfn,SS_context.slot);
}
}
/*
* Function : ss_gNB_vt_timer_process_itti_msg
* Description: Function to hanle the ITTI messages for VT_TIMER_TASK
*/
void *ss_gNB_vt_timer_process_itti_msg(void *notUsed)
{
MessageDef *received_msg = NULL;
int result;
itti_receive_msg(TASK_VT_TIMER, &received_msg);
/* Check if there is a packet to handle */
if (received_msg != NULL)
{
switch (ITTI_MSG_ID(received_msg))
{
case SS_NRUPD_TIM_INFO:
{
ss_nrset_timinfo_t tinfo;
tinfo.sfn = SS_NRUPD_TIM_INFO(received_msg).sfn;
tinfo.slot = SS_NRUPD_TIM_INFO(received_msg).slot;
LOG_D(GNB_APP, "[VT_TIMER] received SS_NRUPD_TIM_INFO SFN: %d Slot: %d\n", tinfo.sfn, tinfo.slot);
ss_nr_vt_timer_check(tinfo);
}
break;
case TERMINATE_MESSAGE:
{
itti_exit_task();
break;
}
default:
LOG_E(GNB_APP, "[SS-VT_TIMER] Received unhandled message %d:%s\n",
ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg));
}
result = itti_free(ITTI_MSG_ORIGIN_ID(received_msg), received_msg);
AssertFatal(result == EXIT_SUCCESS, "[VT_TIMER] Failed to free memory (%d)!\n", result);
received_msg = NULL;
}
return NULL;
}
/*
* Function : ss_gNB_vt_timer_init
* Description: Function to initialize the TASK_VT_TIMER
*/
int ss_gNB_vt_timer_init(void)
{
SS_context.vt_timer_table = hashtable_create (32, NULL, NULL);
itti_mark_task_ready(TASK_VT_TIMER);
return 0;
}
/*
* Function : ss_gNB_vt_timer_task
* Description: Function to create the TASK_VT_TIMER
*/
void* ss_gNB_vt_timer_task(void *arg) {
int retVal = ss_gNB_vt_timer_init();
if (retVal != -1) {
LOG_A(GNB_APP, "[SS-VT_TIMER] Enabled TASK_VT_TIMER starting the itti_msg_handler \n");
while (1) {
(void) ss_gNB_vt_timer_process_itti_msg(NULL);
}
} else {
LOG_A(GNB_APP, "[SS-VT_TIMER] TASK_VT_TIMER port disabled at gNB \n");
sleep(10);
}
return NULL;
}
/*
* 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 <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include "hashtable.h"
#include "intertask_interface.h"
#include "SidlCommon.h"
#ifndef SS_GNB_VT_TIMER_TASK_H_
#define SS_GNB_VT_TIMER_TASK_H_
void *ss_gNB_vt_timer_process_itti_msg(void *);
void *ss_gNB_vt_timer_task(void *arg);
int nr_vt_timer_push_msg(struct TimingInfo_Type* at, int32_t slotOffset,task_id_t task_id,instance_t instance, MessageDef *msg_p);
void nr_vt_add_slot(struct TimingInfo_Type* at, int offset);
typedef struct vt_timer_elm_s {
task_id_t task_id;
instance_t instance;
void *msg; ///< Optional argument that will be passed when timer expires
} vt_timer_elm_t ;
#endif
\ No newline at end of file
...@@ -140,7 +140,9 @@ void ss_vtp_send_tinfo( ...@@ -140,7 +140,9 @@ void ss_vtp_send_tinfo(
virtualTime.TimingInfo.Slot.v.SlotOffset.d = (enum SlotOffset_Type_Sel) (tinfo->mu + 1); virtualTime.TimingInfo.Slot.v.SlotOffset.d = (enum SlotOffset_Type_Sel) (tinfo->mu + 1);
switch(virtualTime.TimingInfo.Slot.v.SlotOffset.d) { switch(virtualTime.TimingInfo.Slot.v.SlotOffset.d) {
case SlotOffset_Type_Numerology0: break; case SlotOffset_Type_Numerology0:
virtualTime.TimingInfo.Slot.v.SlotOffset.v.Numerology0 = true;
break;
case SlotOffset_Type_Numerology1: case SlotOffset_Type_Numerology1:
virtualTime.TimingInfo.Slot.v.SlotOffset.v.Numerology1 = tinfo->slot; virtualTime.TimingInfo.Slot.v.SlotOffset.v.Numerology1 = tinfo->slot;
break; break;
...@@ -158,15 +160,14 @@ void ss_vtp_send_tinfo( ...@@ -158,15 +160,14 @@ void ss_vtp_send_tinfo(
break;; break;;
} }
virtualTime.TimingInfo.SFN.d = true; virtualTime.TimingInfo.SFN.d = SystemFrameNumberInfo_Type_Number;
virtualTime.TimingInfo.SFN.v.Number = tinfo->sfn; virtualTime.TimingInfo.SFN.v.Number = tinfo->sfn;
virtualTime.TimingInfo.Subframe.d = true; virtualTime.TimingInfo.Subframe.d = SubFrameInfo_Type_Number;
virtualTime.TimingInfo.Subframe.v.Number = tinfo->sf; virtualTime.TimingInfo.Subframe.v.Number = tinfo->sf;
/** TODO: Always filling HSFN as 0, need to check this */ virtualTime.TimingInfo.HSFN.d = SystemFrameNumberInfo_Type_Number;
virtualTime.TimingInfo.HSFN.d = false; virtualTime.TimingInfo.HSFN.v.Number = tinfo->hsfn;
virtualTime.TimingInfo.HSFN.v.Number = 0;
if (((tinfo->sfn % 32) == 0) && (tinfo->sf == 0) && (tinfo->slot == 0)) if (((tinfo->sfn % 32) == 0) && (tinfo->sf == 0) && (tinfo->slot == 0))
{ {
...@@ -367,22 +368,15 @@ uint8_t ss_gNB_vtp_process_itti_msg(void) ...@@ -367,22 +368,15 @@ uint8_t ss_gNB_vtp_process_itti_msg(void)
{ {
switch (ITTI_MSG_ID(received_msg)) switch (ITTI_MSG_ID(received_msg))
{ {
case SS_UPD_TIM_INFO:
{
ss_set_timinfo_t tinfo;
tinfo.sf = SS_UPD_TIM_INFO(received_msg).sf;
tinfo.sfn = SS_UPD_TIM_INFO(received_msg).sfn;
if (SS_context.vtp_enabled == 1) {
ss_vtp_send_tinfo(TASK_VTP, &tinfo);
}
}; break;
case SS_NRUPD_TIM_INFO: case SS_NRUPD_TIM_INFO:
{ {
ss_set_timinfo_t tinfo; ss_set_timinfo_t tinfo;
tinfo.slot = SS_NRUPD_TIM_INFO(received_msg).slot % 2; tinfo.mu = SS_context.mu;
tinfo.mu = 1; uint8_t slotsPerSubFrame = 1<<tinfo.mu;
tinfo.sf = SS_NRUPD_TIM_INFO(received_msg).slot / 2; tinfo.slot = SS_NRUPD_TIM_INFO(received_msg).slot % slotsPerSubFrame;
tinfo.sf = SS_NRUPD_TIM_INFO(received_msg).slot /slotsPerSubFrame;
tinfo.sfn = SS_NRUPD_TIM_INFO(received_msg).sfn; tinfo.sfn = SS_NRUPD_TIM_INFO(received_msg).sfn;
tinfo.hsfn = SS_context.hsfn;
if (SS_context.vtp_enabled == 1) { if (SS_context.vtp_enabled == 1) {
ss_vtp_send_tinfo(TASK_VTP, &tinfo); ss_vtp_send_tinfo(TASK_VTP, &tinfo);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment