Merge remote-tracking branch 'origin/develop' into enhancement-ltem
This commit is contained in:
@@ -64,6 +64,16 @@
|
||||
# define MAX_MODULES NB_MODULES_MAX
|
||||
|
||||
#ifndef UE_EXPANSION
|
||||
// TODO:L2 FAPI simulator.
|
||||
// UESIM_EXPANSION is used to be same value of MAX_MOBILES_PER_ENB
|
||||
// in eNB and UE.
|
||||
// now , if we use --mu option in UE, compiling error will occur.
|
||||
// This problem will be fixed in the future.
|
||||
# ifdef UESIM_EXPANSION
|
||||
# define MAX_MOBILES_PER_ENB 256
|
||||
# define MAX_MOBILES_PER_ENB_NB_IoT 256
|
||||
# define MAX_eNB 2
|
||||
# else
|
||||
# ifdef LARGE_SCALE
|
||||
# define MAX_MOBILES_PER_ENB 128
|
||||
# define MAX_MOBILES_PER_ENB_NB_IoT 128
|
||||
@@ -73,6 +83,7 @@
|
||||
# define MAX_MOBILES_PER_ENB_NB_IoT 16
|
||||
# define MAX_eNB 2
|
||||
# endif
|
||||
#endif
|
||||
#else
|
||||
# define MAX_MOBILES_PER_ENB 256
|
||||
# define MAX_MOBILES_PER_ENB_NB_IoT 256
|
||||
|
||||
@@ -25,18 +25,11 @@ TASK_DEF(TASK_TIMER, TASK_PRIORITY_MAX, 10)
|
||||
// Other possible tasks in the process
|
||||
|
||||
// Common tasks:
|
||||
/// Layer 2 and Layer 1 task supporting all the synchronous processing
|
||||
TASK_DEF(TASK_L2L1, TASK_PRIORITY_MAX_LEAST, 200)
|
||||
|
||||
/// Bearers Manager task
|
||||
TASK_DEF(TASK_BM, TASK_PRIORITY_MED, 200)
|
||||
|
||||
// eNodeB tasks and sub-tasks:
|
||||
//// Layer 2 and Layer 1 sub-tasks
|
||||
SUB_TASK_DEF(TASK_L2L1, TASK_PHY_ENB, 200)
|
||||
SUB_TASK_DEF(TASK_L2L1, TASK_MAC_ENB, 200)
|
||||
SUB_TASK_DEF(TASK_L2L1, TASK_RLC_ENB, 200)
|
||||
SUB_TASK_DEF(TASK_L2L1, TASK_PDCP_ENB, 200)
|
||||
|
||||
/// Radio Resource Control task
|
||||
TASK_DEF(TASK_RRC_ENB, TASK_PRIORITY_MED, 200)
|
||||
@@ -63,11 +56,6 @@ TASK_DEF(TASK_ENB_APP, TASK_PRIORITY_MED, 200)
|
||||
TASK_DEF(TASK_FLEXRAN_AGENT, TASK_PRIORITY_MED, 200)
|
||||
|
||||
// UE tasks and sub-tasks:
|
||||
//// Layer 2 and Layer 1 sub-tasks
|
||||
SUB_TASK_DEF(TASK_L2L1, TASK_PHY_UE, 200)
|
||||
SUB_TASK_DEF(TASK_L2L1, TASK_MAC_UE, 200)
|
||||
SUB_TASK_DEF(TASK_L2L1, TASK_RLC_UE, 200)
|
||||
SUB_TASK_DEF(TASK_L2L1, TASK_PDCP_UE, 200)
|
||||
|
||||
/// Radio Resource Control task
|
||||
TASK_DEF(TASK_RRC_UE, TASK_PRIORITY_MED, 200)
|
||||
|
||||
@@ -375,14 +375,16 @@ void flexran_update_TA(mid_t mod_id, mid_t ue_id, uint8_t cc_id)
|
||||
ue_sched_ctl->ta_timer--;
|
||||
ue_sched_ctl->ta_update = 0; // don't trigger a timing advance command
|
||||
}
|
||||
*/
|
||||
#warning "Implement flexran_update_TA() in RAN API"
|
||||
*/
|
||||
}
|
||||
|
||||
/* TODO needs to be revised, looks suspicious: why do we need UE stats? */
|
||||
int flexran_get_MAC_CE_bitmap_TA(mid_t mod_id, mid_t ue_id, uint8_t cc_id)
|
||||
{
|
||||
/*
|
||||
#warning "Implement flexran_get_MAC_CE_bitmap_TA() in RAN API"
|
||||
*/
|
||||
if (!phy_is_present(mod_id, cc_id)) return 0;
|
||||
|
||||
/* UE_stats can not be null, they are an array in RC
|
||||
@@ -476,7 +478,9 @@ int flexran_get_harq(mid_t mod_id,
|
||||
/* *status = 0; */
|
||||
/* } */
|
||||
/*return *round;*/
|
||||
/*
|
||||
#warning "Implement flexran_get_harq() in RAN API"
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1342,7 +1342,7 @@ schedule_RA(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP)
|
||||
|
||||
if (ra->state == MSG2)
|
||||
generate_Msg2(module_idP, CC_id, frameP, subframeP, ra);
|
||||
else if (ra->state == MSG4 && ra->Msg4_frame == frameP && ra->Msg4_subframe == subframeP )
|
||||
else if (ra->state == MSG4 && ra->Msg4_frame == frameP && ra->Msg4_subframe == subframeP )
|
||||
generate_Msg4(module_idP, CC_id, frameP, subframeP, ra);
|
||||
else if (ra->state == WAITMSG4ACK)
|
||||
check_Msg4_retransmission(module_idP, CC_id, frameP,
|
||||
|
||||
@@ -594,6 +594,7 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id,
|
||||
LTE_eNB_UE_stats *eNB_UE_stats2 = NULL;
|
||||
UE_sched_ctrl *ue_sched_ctl1, *ue_sched_ctl2;
|
||||
#endif
|
||||
memset(rballoc_sub[0],0,(MAX_NUM_CCs)*(N_RBG_MAX)*sizeof(unsigned char));
|
||||
memset(min_rb_unit,0,sizeof(min_rb_unit));
|
||||
|
||||
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
|
||||
|
||||
@@ -61,6 +61,7 @@ extern uint16_t frame_cnt;
|
||||
#include "SCHED/sched_common.h"
|
||||
|
||||
extern RAN_CONTEXT_t RC;
|
||||
extern uint8_t nfapi_mode;
|
||||
|
||||
int choose(int n, int k)
|
||||
{
|
||||
@@ -1286,6 +1287,7 @@ fill_nfapi_ulsch_harq_information(module_id_t module_
|
||||
*/
|
||||
#endif
|
||||
harq_information->harq_information_rel10.delta_offset_harq = puschConfigDedicated->betaOffset_ACK_Index;
|
||||
harq_information->harq_information_rel10.tl.tag = NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL10_TAG;
|
||||
AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->pucch_ConfigDedicated != NULL,
|
||||
"pucch_ConfigDedicated is null!\n");
|
||||
if ((UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->pucch_ConfigDedicated->tdd_AckNackFeedbackMode != NULL)
|
||||
@@ -3633,9 +3635,19 @@ extract_harq(module_id_t mod_idP, int CC_idP, int UE_id,
|
||||
AssertFatal(num_ack_nak == 1,
|
||||
"num_ack_nak %d > 1 for 1 CC and single-layer transmission frame:%d subframe:%d\n",
|
||||
num_ack_nak,frameP,subframeP);
|
||||
AssertFatal(sched_ctl->round[CC_idP][harq_pid] < 8,
|
||||
"Got ACK/NAK for inactive harq_pid %d for UE %d/%x\n",
|
||||
harq_pid, UE_id, rnti);
|
||||
|
||||
// In case of nFAPI, sometimes timing of eNB and UE become different.
|
||||
// So if nfapi_mode == 2(VNF) , this function don't check assertion to avoid process exit.
|
||||
if (nfapi_mode != 2){
|
||||
AssertFatal(sched_ctl->round[CC_idP][harq_pid] < 8,
|
||||
"Got ACK/NAK for inactive harq_pid %d for UE %d/%x\n",
|
||||
harq_pid, UE_id, rnti);
|
||||
} else {
|
||||
if(sched_ctl->round[CC_idP][harq_pid] == 8){
|
||||
LOG_E(MAC,"Got ACK/NAK for inactive harq_pid %d for UE %d/%x\n",harq_pid, UE_id, rnti);
|
||||
return;
|
||||
}
|
||||
}
|
||||
AssertFatal(pdu[0] == 1 || pdu[0] == 2
|
||||
|| pdu[0] == 4,
|
||||
"Received ACK/NAK %d which is not 1 or 2 for harq_pid %d from UE %d/%x\n",
|
||||
|
||||
@@ -64,7 +64,8 @@ extern eNB_DLSCH_INFO eNB_dlsch_info[NUMBER_OF_eNB_MAX][MAX_NUM_CCs][MAX_MOBILES
|
||||
extern unsigned char NB_INST;
|
||||
#endif
|
||||
extern unsigned char NB_eNB_INST;
|
||||
extern unsigned char NB_UE_INST;
|
||||
extern uint16_t NB_UE_INST;
|
||||
extern uint16_t NB_THREAD_INST;
|
||||
extern unsigned char NB_RN_INST;
|
||||
extern unsigned short NODE_ID[1];
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ const uint8_t cqi2fmt2x_agg[MAX_SUPPORTED_BW][CQI_VALUE_RANGE] = {
|
||||
|
||||
uint32_t RRC_CONNECTION_FLAG;
|
||||
|
||||
UE_MAC_INST *UE_mac_inst; //[NB_MODULE_MAX];
|
||||
UE_MAC_INST *UE_mac_inst = NULL; //[NB_MODULE_MAX];
|
||||
MAC_RLC_XFACE *Mac_rlc_xface;
|
||||
|
||||
/// Primary component carrier index of eNB
|
||||
@@ -109,7 +109,8 @@ eNB_DLSCH_INFO eNB_dlsch_info[NUMBER_OF_eNB_MAX][MAX_NUM_CCs][MAX_MOBILES_PER_EN
|
||||
|
||||
#ifdef OPENAIR2
|
||||
unsigned char NB_eNB_INST = 0;
|
||||
unsigned char NB_UE_INST = 0;
|
||||
uint16_t NB_UE_INST = 0;
|
||||
uint16_t NB_THREAD_INST = 0;
|
||||
unsigned char NB_RN_INST = 0;
|
||||
unsigned char NB_INST = 0;
|
||||
#endif
|
||||
|
||||
@@ -43,7 +43,8 @@
|
||||
|
||||
|
||||
#include "common/ran_context.h"
|
||||
|
||||
extern FILL_UL_INFO_MUTEX_t fill_ul_mutex;
|
||||
extern uint8_t nfapi_mode;
|
||||
extern void openair_rrc_top_init_ue( int eMBMS_active, char* uecap_xer, uint8_t cba_group_active, uint8_t HO_active);
|
||||
|
||||
void dl_phy_sync_success(module_id_t module_idP, frame_t frameP, unsigned char eNB_index, uint8_t first_sync) //init as MR
|
||||
@@ -103,6 +104,15 @@ mac_top_init_ue(int eMBMS_active, char *uecap_xer,
|
||||
UE_mac_inst = NULL;
|
||||
}
|
||||
|
||||
// mutex below are used for multiple UE's L2 FAPI simulation.
|
||||
if (nfapi_mode == 3){
|
||||
pthread_mutex_init(&fill_ul_mutex.rx_mutex,NULL);
|
||||
pthread_mutex_init(&fill_ul_mutex.crc_mutex,NULL);
|
||||
pthread_mutex_init(&fill_ul_mutex.sr_mutex,NULL);
|
||||
pthread_mutex_init(&fill_ul_mutex.harq_mutex,NULL);
|
||||
pthread_mutex_init(&fill_ul_mutex.cqi_mutex,NULL);
|
||||
pthread_mutex_init(&fill_ul_mutex.rach_mutex,NULL);
|
||||
}
|
||||
|
||||
LOG_I(MAC, "[MAIN] calling RRC\n");
|
||||
openair_rrc_top_init_ue(eMBMS_active, uecap_xer, cba_group_active,
|
||||
|
||||
@@ -69,6 +69,8 @@
|
||||
extern UL_IND_t *UL_INFO;
|
||||
|
||||
extern uint8_t nfapi_mode;
|
||||
extern int next_ra_frame;
|
||||
extern module_id_t next_Mod_id;
|
||||
|
||||
/*
|
||||
*
|
||||
@@ -2530,44 +2532,50 @@ ue_scheduler(const module_id_t module_idP,
|
||||
UE_mac_inst[module_idP].crnti, txFrameP,
|
||||
txSubframeP, eNB_indexP);
|
||||
#if defined(ENABLE_ITTI)
|
||||
if(module_idP == 0){
|
||||
do {
|
||||
// Checks if a message has been sent to MAC sub-task
|
||||
itti_poll_msg(TASK_MAC_UE, &msg_p);
|
||||
|
||||
do {
|
||||
// Checks if a message has been sent to MAC sub-task
|
||||
itti_poll_msg(TASK_MAC_UE, &msg_p);
|
||||
if (msg_p != NULL) {
|
||||
|
||||
if (msg_p != NULL) {
|
||||
switch (ITTI_MSG_ID(msg_p)) {
|
||||
case RRC_MAC_CCCH_DATA_REQ:
|
||||
LOG_I(MAC,
|
||||
"Received %s from %s: instance %d, frameP %d, eNB_index %d\n",
|
||||
ITTI_MSG_NAME(msg_p), ITTI_MSG_ORIGIN_NAME(msg_p), ITTI_MSG_INSTANCE(msg_p),
|
||||
RRC_MAC_CCCH_DATA_REQ(msg_p).frame,
|
||||
RRC_MAC_CCCH_DATA_REQ(msg_p).enb_index);
|
||||
|
||||
switch (ITTI_MSG_ID(msg_p)) {
|
||||
case RRC_MAC_CCCH_DATA_REQ:
|
||||
LOG_I(MAC,
|
||||
"Received %s from %s: instance %d, frameP %d, eNB_index %d\n",
|
||||
ITTI_MSG_NAME(msg_p), ITTI_MSG_ORIGIN_NAME(msg_p), ITTI_MSG_INSTANCE(msg_p),
|
||||
RRC_MAC_CCCH_DATA_REQ(msg_p).frame,
|
||||
RRC_MAC_CCCH_DATA_REQ(msg_p).enb_index);
|
||||
|
||||
// TODO process CCCH data req.
|
||||
break;
|
||||
// TODO process CCCH data req.
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
LOG_E(MAC, "Received unexpected message %s\n", ITTI_MSG_NAME(msg_p));
|
||||
break;
|
||||
default:
|
||||
LOG_E(MAC, "Received unexpected message %s\n", ITTI_MSG_NAME(msg_p));
|
||||
break;
|
||||
}
|
||||
|
||||
result = itti_free(ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
|
||||
AssertFatal(result == EXIT_SUCCESS,
|
||||
"Failed to free memory (%d)!\n", result);
|
||||
}
|
||||
|
||||
result = itti_free(ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
|
||||
AssertFatal(result == EXIT_SUCCESS,
|
||||
"Failed to free memory (%d)!\n", result);
|
||||
}
|
||||
}
|
||||
}
|
||||
while (msg_p != NULL);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
//Mac_rlc_xface->frameP=frameP;
|
||||
//Rrc_xface->Frame_index=Mac_rlc_xface->frameP;
|
||||
//if (subframe%5 == 0)
|
||||
//LG#ifdef EXMIMO
|
||||
pdcp_run(&ctxt);
|
||||
|
||||
// data to/from NETLINK is treated in pdcp_run.
|
||||
// one socket is used in multiple UE's L2 FAPI simulator and
|
||||
// only first UE need to do this.
|
||||
if(module_idP == 0){
|
||||
pdcp_run(&ctxt);
|
||||
}
|
||||
//#endif
|
||||
UE_mac_inst[module_idP].txFrame = txFrameP;
|
||||
UE_mac_inst[module_idP].txSubframe = txSubframeP;
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
#include "platform_constants.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
#include "msc.h"
|
||||
|
||||
#include "targets/COMMON/openairinterface5g_limits.h"
|
||||
#if defined(ENABLE_SECURITY)
|
||||
# include "UTIL/OSA/osa_defs.h"
|
||||
#endif
|
||||
@@ -64,9 +64,12 @@
|
||||
#endif
|
||||
|
||||
extern int otg_enabled;
|
||||
|
||||
#if defined(ENABLE_USE_MME)
|
||||
extern uint8_t nfapi_mode;
|
||||
#endif
|
||||
#include "common/ran_context.h"
|
||||
extern RAN_CONTEXT_t RC;
|
||||
hash_table_t *pdcp_coll_p = NULL;
|
||||
|
||||
#ifdef MBMS_MULTICAST_OUT
|
||||
# include <sys/types.h>
|
||||
@@ -798,12 +801,21 @@ pdcp_data_ind(
|
||||
* for the UE compiled in noS1 mode, we need 0
|
||||
* TODO: be sure of this
|
||||
*/
|
||||
((pdcp_data_ind_header_t*) new_sdu_p->data)->inst = 1;
|
||||
if (nfapi_mode == 3) {
|
||||
#ifdef UESIM_EXPANSION
|
||||
((pdcp_data_ind_header_t*) new_sdu_p->data)->inst = 0;
|
||||
#else
|
||||
((pdcp_data_ind_header_t*) new_sdu_p->data)->inst = ctxt_pP->module_id;
|
||||
#endif
|
||||
} else {
|
||||
((pdcp_data_ind_header_t*) new_sdu_p->data)->inst = 1;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
((pdcp_data_ind_header_t*) new_sdu_p->data)->rb_id = rb_id + (ctxt_pP->module_id * LTE_maxDRB);
|
||||
((pdcp_data_ind_header_t*) new_sdu_p->data)->inst = ctxt_pP->module_id;
|
||||
}
|
||||
|
||||
// new_sdu_p->data->inst is set again in UE case so move to above.
|
||||
//Panos: Commented this out because it cancels the assignment in #if defined(ENABLE_USE_MME) case
|
||||
//((pdcp_data_ind_header_t*) new_sdu_p->data)->inst = ctxt_pP->module_id;
|
||||
|
||||
@@ -2021,7 +2033,7 @@ void pdcp_layer_init(void)
|
||||
* Initialize SDU list
|
||||
*/
|
||||
list_init(&pdcp_sdu_list, NULL);
|
||||
pdcp_coll_p = hashtable_create ((LTE_maxDRB + 2) * 16, NULL, pdcp_free);
|
||||
pdcp_coll_p = hashtable_create ((LTE_maxDRB + 2) * NUMBER_OF_UE_MAX, NULL, pdcp_free);
|
||||
AssertFatal(pdcp_coll_p != NULL, "UNRECOVERABLE error, PDCP hashtable_create failed");
|
||||
|
||||
for (instance = 0; instance < MAX_MOBILES_PER_ENB; instance++) {
|
||||
|
||||
@@ -542,7 +542,7 @@ sdu_size_t pdcp_input_sdu_remaining_size_to_read;
|
||||
(((hash_key_t)(sESSION_ID)) << 37) | \
|
||||
(((hash_key_t)(0x0000000000000001)) << 63))
|
||||
|
||||
hash_table_t *pdcp_coll_p;
|
||||
extern hash_table_t *pdcp_coll_p;
|
||||
|
||||
#endif
|
||||
/*@}*/
|
||||
|
||||
@@ -82,10 +82,13 @@ extern struct msghdr nas_msg_tx;
|
||||
extern struct msghdr nas_msg_rx;
|
||||
|
||||
unsigned char pdcp_read_state_g = 0;
|
||||
extern uint8_t nfapi_mode;
|
||||
#ifdef UESIM_EXPANSION
|
||||
extern uint16_t inst_pdcp_list[NUMBER_OF_UE_MAX];
|
||||
#endif
|
||||
#endif
|
||||
|
||||
extern Packet_OTG_List_t *otg_pdcp_buffer;
|
||||
|
||||
#if defined(LINK_ENB_PDCP_TO_GTPV1U)
|
||||
# include "gtpv1u_eNB_task.h"
|
||||
# include "gtpv1u_eNB_defs.h"
|
||||
@@ -168,7 +171,12 @@ int pdcp_fifo_flush_sdus(const protocol_ctxt_t* const ctxt_pP)
|
||||
((pdcp_data_ind_header_t*) sdu_p->data)->inst,
|
||||
((pdcp_data_ind_header_t *) sdu_p->data)->data_size);
|
||||
#else
|
||||
//((pdcp_data_ind_header_t *)(sdu_p->data))->inst = 0;
|
||||
// Raphael: was suppressed by Raymond --> should be suppressed?
|
||||
// value of sdu_p->data->inst is set in pdcp_data_ind
|
||||
// it's necessary to set 1 in case of UE with S1.
|
||||
//if (ctxt_pP->enb_flag){
|
||||
// ((pdcp_data_ind_header_t *)(sdu_p->data))->inst = 0;
|
||||
//}
|
||||
#endif
|
||||
|
||||
#if defined(LINK_ENB_PDCP_TO_GTPV1U)
|
||||
@@ -927,7 +935,15 @@ int pdcp_fifo_read_input_sdus (const protocol_ctxt_t* const ctxt_pP)
|
||||
rab_id = pdcp_read_header_g.rb_id % LTE_maxDRB;
|
||||
ctxt.rnti = pdcp_eNB_UE_instance_to_rnti[pdcp_read_header_g.rb_id / LTE_maxDRB];
|
||||
} else {
|
||||
ctxt.module_id = 0;
|
||||
if (nfapi_mode == 3) {
|
||||
#ifdef UESIM_EXPANSION
|
||||
ctxt.module_id = inst_pdcp_list[pdcp_read_header_g.inst];
|
||||
#else
|
||||
ctxt.module_id = pdcp_read_header_g.inst;
|
||||
#endif
|
||||
} else {
|
||||
ctxt.module_id = 0;
|
||||
}
|
||||
rab_id = pdcp_read_header_g.rb_id % LTE_maxDRB;
|
||||
ctxt.rnti = pdcp_UE_UE_module_id_to_rnti[ctxt.module_id];
|
||||
}
|
||||
@@ -1072,7 +1088,22 @@ int pdcp_fifo_read_input_sdus (const protocol_ctxt_t* const ctxt_pP)
|
||||
pdcp_read_header_g.rb_id,
|
||||
rab_id,
|
||||
pdcp_read_header_g.data_size);
|
||||
|
||||
if(nfapi_mode == 3){
|
||||
pdcp_data_req(
|
||||
&ctxt,
|
||||
SRB_FLAG_NO,
|
||||
rab_id,
|
||||
RLC_MUI_UNDEFINED,
|
||||
RLC_SDU_CONFIRM_NO,
|
||||
pdcp_read_header_g.data_size,
|
||||
(unsigned char *)NLMSG_DATA(nas_nlh_rx),
|
||||
PDCP_TRANSMISSION_MODE_DATA
|
||||
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
|
||||
,NULL
|
||||
,NULL
|
||||
#endif
|
||||
);
|
||||
}else{
|
||||
pdcp_data_req(
|
||||
&ctxt,
|
||||
SRB_FLAG_NO,
|
||||
@@ -1087,6 +1118,7 @@ int pdcp_fifo_read_input_sdus (const protocol_ctxt_t* const ctxt_pP)
|
||||
,&pdcp_read_header_g.destinationL2Id
|
||||
#endif
|
||||
);
|
||||
}
|
||||
} else {
|
||||
MSC_LOG_RX_DISCARDED_MESSAGE(
|
||||
(ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
|
||||
@@ -1130,7 +1162,22 @@ int pdcp_fifo_read_input_sdus (const protocol_ctxt_t* const ctxt_pP)
|
||||
pdcp_read_header_g.rb_id,
|
||||
DEFAULT_RAB_ID,
|
||||
pdcp_read_header_g.data_size);
|
||||
|
||||
if(nfapi_mode == 3){
|
||||
pdcp_data_req (
|
||||
&ctxt,
|
||||
SRB_FLAG_NO,
|
||||
DEFAULT_RAB_ID,
|
||||
RLC_MUI_UNDEFINED,
|
||||
RLC_SDU_CONFIRM_NO,
|
||||
pdcp_read_header_g.data_size,
|
||||
(unsigned char *)NLMSG_DATA(nas_nlh_rx),
|
||||
PDCP_TRANSMISSION_MODE_DATA
|
||||
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
|
||||
,NULL
|
||||
,NULL
|
||||
#endif
|
||||
);
|
||||
}else{
|
||||
pdcp_data_req (
|
||||
&ctxt,
|
||||
SRB_FLAG_NO,
|
||||
@@ -1145,6 +1192,7 @@ int pdcp_fifo_read_input_sdus (const protocol_ctxt_t* const ctxt_pP)
|
||||
,&pdcp_read_header_g.destinationL2Id
|
||||
#endif
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -23,9 +23,7 @@
|
||||
#define RLC_AM_REASSEMBLY_C 1
|
||||
#include "platform_types.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
#if ENABLE_ITTI
|
||||
# include "intertask_interface.h"
|
||||
#endif
|
||||
|
||||
#include "assertions.h"
|
||||
#include "rlc.h"
|
||||
#include "rlc_am.h"
|
||||
@@ -37,19 +35,17 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
inline void
|
||||
rlc_am_clear_rx_sdu (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t * const rlc_pP)
|
||||
{
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rlc_am_entity_t *const rlc_pP) {
|
||||
rlc_pP->output_sdu_size_to_write = 0;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_reassembly (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t * const rlc_pP,
|
||||
uint8_t * src_pP,
|
||||
const int32_t lengthP)
|
||||
{
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rlc_am_entity_t *const rlc_pP,
|
||||
uint8_t *src_pP,
|
||||
const int32_t lengthP) {
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PAYLOAD] reassembly() %d bytes\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
lengthP);
|
||||
@@ -57,6 +53,7 @@ rlc_am_reassembly (
|
||||
if (rlc_pP->output_sdu_in_construction == NULL) {
|
||||
rlc_pP->output_sdu_in_construction = get_free_mem_block (RLC_SDU_MAX_SIZE, __func__);
|
||||
rlc_pP->output_sdu_size_to_write = 0;
|
||||
|
||||
//assert(rlc_pP->output_sdu_in_construction != NULL);
|
||||
if(rlc_pP->output_sdu_in_construction == NULL) {
|
||||
LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PAYLOAD] output_sdu_in_construction is NULL\n",
|
||||
@@ -66,7 +63,6 @@ rlc_am_reassembly (
|
||||
}
|
||||
|
||||
if (rlc_pP->output_sdu_in_construction != NULL) {
|
||||
|
||||
// check if no overflow in size
|
||||
if ((rlc_pP->output_sdu_size_to_write + lengthP) <= RLC_SDU_MAX_SIZE) {
|
||||
memcpy (&rlc_pP->output_sdu_in_construction->data[rlc_pP->output_sdu_size_to_write], src_pP, lengthP);
|
||||
@@ -93,18 +89,8 @@ rlc_am_reassembly (
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_send_sdu (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t * const rlc_pP)
|
||||
{
|
||||
# if TRACE_RLC_AM_PDU
|
||||
char message_string[7000];
|
||||
size_t message_string_size = 0;
|
||||
#if ENABLE_ITTI
|
||||
MessageDef *msg_p;
|
||||
#endif
|
||||
int octet_index, index;
|
||||
#endif
|
||||
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rlc_am_entity_t *const rlc_pP) {
|
||||
if ((rlc_pP->output_sdu_in_construction)) {
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND_SDU] %d bytes sdu %p\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
@@ -120,73 +106,62 @@ rlc_am_send_sdu (
|
||||
rlc_pP->output_sdu_size_to_write,
|
||||
rlc_pP->output_sdu_in_construction);
|
||||
#else
|
||||
# if TRACE_RLC_AM_PDU
|
||||
message_string_size += sprintf(&message_string[message_string_size], "Bearer : %u\n", rlc_pP->rb_id);
|
||||
message_string_size += sprintf(&message_string[message_string_size], "SDU size : %u\n", rlc_pP->output_sdu_size_to_write);
|
||||
|
||||
message_string_size += sprintf(&message_string[message_string_size], "\nPayload : \n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], "------+-------------------------------------------------|\n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], " | 0 1 2 3 4 5 6 7 8 9 a b c d e f |\n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], "------+-------------------------------------------------|\n");
|
||||
if ( LOG_DEBUGFLAG(DEBUG_RLC)) {
|
||||
char message_string[7000];
|
||||
size_t message_string_size = 0;
|
||||
int octet_index, index;
|
||||
message_string_size += sprintf(&message_string[message_string_size], "Bearer : %u\n", rlc_pP->rb_id);
|
||||
message_string_size += sprintf(&message_string[message_string_size], "SDU size : %u\n", rlc_pP->output_sdu_size_to_write);
|
||||
message_string_size += sprintf(&message_string[message_string_size], "\nPayload : \n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], "------+-------------------------------------------------|\n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], " | 0 1 2 3 4 5 6 7 8 9 a b c d e f |\n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], "------+-------------------------------------------------|\n");
|
||||
|
||||
for (octet_index = 0; octet_index < rlc_pP->output_sdu_size_to_write; octet_index++) {
|
||||
if ((octet_index % 16) == 0) {
|
||||
if (octet_index != 0) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], " |\n");
|
||||
for (octet_index = 0; octet_index < rlc_pP->output_sdu_size_to_write; octet_index++) {
|
||||
if ((octet_index % 16) == 0) {
|
||||
if (octet_index != 0) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], " |\n");
|
||||
}
|
||||
|
||||
message_string_size += sprintf(&message_string[message_string_size], " %04d |", octet_index);
|
||||
}
|
||||
|
||||
message_string_size += sprintf(&message_string[message_string_size], " %04d |", octet_index);
|
||||
/*
|
||||
* Print every single octet in hexadecimal form
|
||||
*/
|
||||
message_string_size += sprintf(&message_string[message_string_size],
|
||||
" %02x",
|
||||
rlc_pP->output_sdu_in_construction->data[octet_index]);
|
||||
/*
|
||||
* Align newline and pipes according to the octets in groups of 2
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Print every single octet in hexadecimal form
|
||||
*/
|
||||
message_string_size += sprintf(&message_string[message_string_size],
|
||||
" %02x",
|
||||
rlc_pP->output_sdu_in_construction->data[octet_index]);
|
||||
/*
|
||||
* Align newline and pipes according to the octets in groups of 2
|
||||
* Append enough spaces and put final pipe
|
||||
*/
|
||||
for (index = octet_index; index < 16; ++index) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], " ");
|
||||
}
|
||||
|
||||
message_string_size += sprintf(&message_string[message_string_size], " |\n");
|
||||
LOG_T(RLC, "%s", message_string);
|
||||
}
|
||||
|
||||
/*
|
||||
* Append enough spaces and put final pipe
|
||||
*/
|
||||
for (index = octet_index; index < 16; ++index) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], " ");
|
||||
}
|
||||
|
||||
message_string_size += sprintf(&message_string[message_string_size], " |\n");
|
||||
|
||||
|
||||
|
||||
# if ENABLE_ITTI
|
||||
msg_p = itti_alloc_new_message_sized (ctxt_pP->enb_flag > 0 ? TASK_RLC_ENB:TASK_RLC_UE ,
|
||||
RLC_AM_SDU_IND,
|
||||
message_string_size + sizeof (IttiMsgText));
|
||||
msg_p->ittiMsg.rlc_am_sdu_ind.size = message_string_size;
|
||||
memcpy(&msg_p->ittiMsg.rlc_am_sdu_ind.text, message_string, message_string_size);
|
||||
|
||||
itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->instance, msg_p);
|
||||
|
||||
# else
|
||||
LOG_T(RLC, "%s", message_string);
|
||||
# endif
|
||||
# endif
|
||||
#if !ENABLE_ITTI
|
||||
RLC_AM_MUTEX_UNLOCK(&rlc_pP->lock_input_sdus);
|
||||
#endif
|
||||
MSC_LOG_TX_MESSAGE(
|
||||
(ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_ENB:MSC_RLC_UE,
|
||||
(ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
|
||||
(const char*)(rlc_pP->output_sdu_in_construction->data),
|
||||
(const char *)(rlc_pP->output_sdu_in_construction->data),
|
||||
rlc_pP->output_sdu_size_to_write,
|
||||
MSC_AS_TIME_FMT" "PROTOCOL_RLC_AM_MSC_FMT" DATA-IND size %u",
|
||||
MSC_AS_TIME_ARGS(ctxt_pP),
|
||||
PROTOCOL_RLC_AM_MSC_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->output_sdu_size_to_write
|
||||
);
|
||||
|
||||
rlc_data_ind (ctxt_pP,
|
||||
BOOL_NOT(rlc_pP->is_data_plane),
|
||||
MBMS_FLAG_NO,
|
||||
@@ -203,16 +178,16 @@ rlc_am_send_sdu (
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
//msg("[RLC_AM][MOD %d] Freeing mem_block ...\n", rlc_pP->module_id);
|
||||
//free_mem_block (rlc_pP->output_sdu_in_construction, __func__);
|
||||
//Assertion(eNB)_PRAN_DesignDocument_annex No.764
|
||||
LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT" SEND SDU REQUESTED %d bytes\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->output_sdu_size_to_write);
|
||||
/*
|
||||
AssertFatal(3==4,
|
||||
PROTOCOL_RLC_AM_CTXT_FMT" SEND SDU REQUESTED %d bytes",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->output_sdu_size_to_write);
|
||||
*/
|
||||
//Assertion(eNB)_PRAN_DesignDocument_annex No.764
|
||||
LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT" SEND SDU REQUESTED %d bytes\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->output_sdu_size_to_write);
|
||||
/*
|
||||
AssertFatal(3==4,
|
||||
PROTOCOL_RLC_AM_CTXT_FMT" SEND SDU REQUESTED %d bytes",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->output_sdu_size_to_write);
|
||||
*/
|
||||
}
|
||||
|
||||
rlc_pP->output_sdu_size_to_write = 0;
|
||||
@@ -221,191 +196,189 @@ rlc_am_send_sdu (
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_reassemble_pdu(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t * const rlc_pP,
|
||||
mem_block_t * const tb_pP,
|
||||
boolean_t free_rlc_pdu)
|
||||
{
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rlc_am_entity_t *const rlc_pP,
|
||||
mem_block_t *const tb_pP,
|
||||
boolean_t free_rlc_pdu) {
|
||||
int i,j;
|
||||
|
||||
rlc_am_pdu_info_t* pdu_info = &((rlc_am_rx_pdu_management_t*)(tb_pP->data))->pdu_info;
|
||||
rlc_am_pdu_info_t *pdu_info = &((rlc_am_rx_pdu_management_t *)(tb_pP->data))->pdu_info;
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PDU] TRY REASSEMBLY PDU SN=%03d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
pdu_info->sn);
|
||||
#if TRACE_RLC_AM_RX_DECODE
|
||||
rlc_am_display_data_pdu_infos(ctxt_pP, rlc_pP, pdu_info);
|
||||
#endif
|
||||
|
||||
if ( LOG_DEBUGFLAG(DEBUG_RLC)) {
|
||||
rlc_am_display_data_pdu_infos(ctxt_pP, rlc_pP, pdu_info);
|
||||
}
|
||||
|
||||
if (pdu_info->e == RLC_E_FIXED_PART_DATA_FIELD_FOLLOW) {
|
||||
switch (pdu_info->fi) {
|
||||
case RLC_FI_1ST_BYTE_DATA_IS_1ST_BYTE_SDU_LAST_BYTE_DATA_IS_LAST_BYTE_SDU:
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PDU] TRY REASSEMBLY PDU NO E_LI FI=11 (00)\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
// one complete SDU
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP); // may be not necessary
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, pdu_info->payload, pdu_info->payload_size);
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP); // may be not necessary
|
||||
//rlc_pP->reassembly_missing_sn_detected = 0;
|
||||
break;
|
||||
case RLC_FI_1ST_BYTE_DATA_IS_1ST_BYTE_SDU_LAST_BYTE_DATA_IS_LAST_BYTE_SDU:
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PDU] TRY REASSEMBLY PDU NO E_LI FI=11 (00)\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
// one complete SDU
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP); // may be not necessary
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, pdu_info->payload, pdu_info->payload_size);
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP); // may be not necessary
|
||||
//rlc_pP->reassembly_missing_sn_detected = 0;
|
||||
break;
|
||||
|
||||
case RLC_FI_1ST_BYTE_DATA_IS_1ST_BYTE_SDU_LAST_BYTE_DATA_IS_NOT_LAST_BYTE_SDU:
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PDU] TRY REASSEMBLY PDU NO E_LI FI=10 (01)\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
// one beginning segment of SDU in PDU
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP); // may be not necessary
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP,pdu_info->payload, pdu_info->payload_size);
|
||||
//rlc_pP->reassembly_missing_sn_detected = 0;
|
||||
break;
|
||||
case RLC_FI_1ST_BYTE_DATA_IS_1ST_BYTE_SDU_LAST_BYTE_DATA_IS_NOT_LAST_BYTE_SDU:
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PDU] TRY REASSEMBLY PDU NO E_LI FI=10 (01)\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
// one beginning segment of SDU in PDU
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP); // may be not necessary
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP,pdu_info->payload, pdu_info->payload_size);
|
||||
//rlc_pP->reassembly_missing_sn_detected = 0;
|
||||
break;
|
||||
|
||||
case RLC_FI_1ST_BYTE_DATA_IS_NOT_1ST_BYTE_SDU_LAST_BYTE_DATA_IS_LAST_BYTE_SDU:
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PDU] TRY REASSEMBLY PDU NO E_LI FI=01 (10)\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
// one last segment of SDU
|
||||
//if (rlc_pP->reassembly_missing_sn_detected == 0) {
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, pdu_info->payload, pdu_info->payload_size);
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP);
|
||||
//} // else { clear sdu already done
|
||||
//rlc_pP->reassembly_missing_sn_detected = 0;
|
||||
break;
|
||||
case RLC_FI_1ST_BYTE_DATA_IS_NOT_1ST_BYTE_SDU_LAST_BYTE_DATA_IS_LAST_BYTE_SDU:
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PDU] TRY REASSEMBLY PDU NO E_LI FI=01 (10)\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
// one last segment of SDU
|
||||
//if (rlc_pP->reassembly_missing_sn_detected == 0) {
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, pdu_info->payload, pdu_info->payload_size);
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP);
|
||||
//} // else { clear sdu already done
|
||||
//rlc_pP->reassembly_missing_sn_detected = 0;
|
||||
break;
|
||||
|
||||
case RLC_FI_1ST_BYTE_DATA_IS_NOT_1ST_BYTE_SDU_LAST_BYTE_DATA_IS_NOT_LAST_BYTE_SDU:
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PDU] TRY REASSEMBLY PDU NO E_LI FI=00 (11)\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
//if (rlc_pP->reassembly_missing_sn_detected == 0) {
|
||||
// one whole segment of SDU in PDU
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, pdu_info->payload, pdu_info->payload_size);
|
||||
//} else {
|
||||
// rlc_pP->reassembly_missing_sn_detected = 1; // not necessary but for readability of the code
|
||||
//}
|
||||
case RLC_FI_1ST_BYTE_DATA_IS_NOT_1ST_BYTE_SDU_LAST_BYTE_DATA_IS_NOT_LAST_BYTE_SDU:
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PDU] TRY REASSEMBLY PDU NO E_LI FI=00 (11)\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
//if (rlc_pP->reassembly_missing_sn_detected == 0) {
|
||||
// one whole segment of SDU in PDU
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, pdu_info->payload, pdu_info->payload_size);
|
||||
//} else {
|
||||
// rlc_pP->reassembly_missing_sn_detected = 1; // not necessary but for readability of the code
|
||||
//}
|
||||
break;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
//Assertion(eNB)_PRAN_DesignDocument_annex No.1428
|
||||
LOG_E(RLC, "RLC_E_FIXED_PART_DATA_FIELD_FOLLOW error pdu_info->fi[%d]\n", pdu_info->fi);
|
||||
// assert(0 != 0);
|
||||
default:
|
||||
//Assertion(eNB)_PRAN_DesignDocument_annex No.1428
|
||||
LOG_E(RLC, "RLC_E_FIXED_PART_DATA_FIELD_FOLLOW error pdu_info->fi[%d]\n", pdu_info->fi);
|
||||
// assert(0 != 0);
|
||||
}
|
||||
} else {
|
||||
switch (pdu_info->fi) {
|
||||
case RLC_FI_1ST_BYTE_DATA_IS_1ST_BYTE_SDU_LAST_BYTE_DATA_IS_LAST_BYTE_SDU:
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PDU] TRY REASSEMBLY PDU FI=11 (00) Li=",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
case RLC_FI_1ST_BYTE_DATA_IS_1ST_BYTE_SDU_LAST_BYTE_DATA_IS_LAST_BYTE_SDU:
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PDU] TRY REASSEMBLY PDU FI=11 (00) Li=",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
|
||||
for (i=0; i < pdu_info->num_li; i++) {
|
||||
LOG_D(RLC, "%d ",pdu_info->li_list[i]);
|
||||
}
|
||||
for (i=0; i < pdu_info->num_li; i++) {
|
||||
LOG_D(RLC, "%d ",pdu_info->li_list[i]);
|
||||
}
|
||||
|
||||
LOG_D(RLC, "\n");
|
||||
//msg(" remaining size %d\n",size);
|
||||
// N complete SDUs
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP);
|
||||
j = 0;
|
||||
|
||||
for (i = 0; i < pdu_info->num_li; i++) {
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, &pdu_info->payload[j], pdu_info->li_list[i]);
|
||||
LOG_D(RLC, "\n");
|
||||
//msg(" remaining size %d\n",size);
|
||||
// N complete SDUs
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP);
|
||||
j = j + pdu_info->li_list[i];
|
||||
}
|
||||
j = 0;
|
||||
|
||||
if (pdu_info->hidden_size > 0) { // normally should always be > 0 but just for help debug
|
||||
// data is already ok, done by last loop above
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, &pdu_info->payload[j], pdu_info->hidden_size);
|
||||
for (i = 0; i < pdu_info->num_li; i++) {
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, &pdu_info->payload[j], pdu_info->li_list[i]);
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP);
|
||||
j = j + pdu_info->li_list[i];
|
||||
}
|
||||
|
||||
if (pdu_info->hidden_size > 0) { // normally should always be > 0 but just for help debug
|
||||
// data is already ok, done by last loop above
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, &pdu_info->payload[j], pdu_info->hidden_size);
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP);
|
||||
}
|
||||
|
||||
//rlc_pP->reassembly_missing_sn_detected = 0;
|
||||
break;
|
||||
|
||||
case RLC_FI_1ST_BYTE_DATA_IS_1ST_BYTE_SDU_LAST_BYTE_DATA_IS_NOT_LAST_BYTE_SDU:
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PDU] TRY REASSEMBLY PDU FI=10 (01) Li=",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
|
||||
for (i=0; i < pdu_info->num_li; i++) {
|
||||
LOG_D(RLC, "%d ",pdu_info->li_list[i]);
|
||||
}
|
||||
|
||||
LOG_D(RLC, "\n");
|
||||
//msg(" remaining size %d\n",size);
|
||||
// N complete SDUs + one segment of SDU in PDU
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP);
|
||||
}
|
||||
j = 0;
|
||||
|
||||
//rlc_pP->reassembly_missing_sn_detected = 0;
|
||||
break;
|
||||
for (i = 0; i < pdu_info->num_li; i++) {
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, &pdu_info->payload[j], pdu_info->li_list[i]);
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP);
|
||||
j = j + pdu_info->li_list[i];
|
||||
}
|
||||
|
||||
case RLC_FI_1ST_BYTE_DATA_IS_1ST_BYTE_SDU_LAST_BYTE_DATA_IS_NOT_LAST_BYTE_SDU:
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PDU] TRY REASSEMBLY PDU FI=10 (01) Li=",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
if (pdu_info->hidden_size > 0) { // normally should always be > 0 but just for help debug
|
||||
// data is already ok, done by last loop above
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, &pdu_info->payload[j], pdu_info->hidden_size);
|
||||
}
|
||||
|
||||
for (i=0; i < pdu_info->num_li; i++) {
|
||||
LOG_D(RLC, "%d ",pdu_info->li_list[i]);
|
||||
}
|
||||
//rlc_pP->reassembly_missing_sn_detected = 0;
|
||||
break;
|
||||
|
||||
LOG_D(RLC, "\n");
|
||||
//msg(" remaining size %d\n",size);
|
||||
// N complete SDUs + one segment of SDU in PDU
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP);
|
||||
j = 0;
|
||||
case RLC_FI_1ST_BYTE_DATA_IS_NOT_1ST_BYTE_SDU_LAST_BYTE_DATA_IS_LAST_BYTE_SDU:
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PDU] TRY REASSEMBLY PDU FI=01 (10) Li=",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
|
||||
for (i = 0; i < pdu_info->num_li; i++) {
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, &pdu_info->payload[j], pdu_info->li_list[i]);
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP);
|
||||
j = j + pdu_info->li_list[i];
|
||||
}
|
||||
for (i=0; i < pdu_info->num_li; i++) {
|
||||
LOG_D(RLC, "%d ",pdu_info->li_list[i]);
|
||||
}
|
||||
|
||||
if (pdu_info->hidden_size > 0) { // normally should always be > 0 but just for help debug
|
||||
// data is already ok, done by last loop above
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, &pdu_info->payload[j], pdu_info->hidden_size);
|
||||
}
|
||||
LOG_D(RLC, "\n");
|
||||
//msg(" remaining size %d\n",size);
|
||||
// one last segment of SDU + N complete SDUs in PDU
|
||||
j = 0;
|
||||
|
||||
//rlc_pP->reassembly_missing_sn_detected = 0;
|
||||
break;
|
||||
for (i = 0; i < pdu_info->num_li; i++) {
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, &pdu_info->payload[j], pdu_info->li_list[i]);
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP);
|
||||
j = j + pdu_info->li_list[i];
|
||||
}
|
||||
|
||||
case RLC_FI_1ST_BYTE_DATA_IS_NOT_1ST_BYTE_SDU_LAST_BYTE_DATA_IS_LAST_BYTE_SDU:
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PDU] TRY REASSEMBLY PDU FI=01 (10) Li=",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
if (pdu_info->hidden_size > 0) { // normally should always be > 0 but just for help debug
|
||||
// data is already ok, done by last loop above
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, &pdu_info->payload[j], pdu_info->hidden_size);
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP);
|
||||
}
|
||||
|
||||
for (i=0; i < pdu_info->num_li; i++) {
|
||||
LOG_D(RLC, "%d ",pdu_info->li_list[i]);
|
||||
}
|
||||
//rlc_pP->reassembly_missing_sn_detected = 0;
|
||||
break;
|
||||
|
||||
LOG_D(RLC, "\n");
|
||||
//msg(" remaining size %d\n",size);
|
||||
// one last segment of SDU + N complete SDUs in PDU
|
||||
j = 0;
|
||||
case RLC_FI_1ST_BYTE_DATA_IS_NOT_1ST_BYTE_SDU_LAST_BYTE_DATA_IS_NOT_LAST_BYTE_SDU:
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PDU] TRY REASSEMBLY PDU FI=00 (11) Li=",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
|
||||
for (i = 0; i < pdu_info->num_li; i++) {
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, &pdu_info->payload[j], pdu_info->li_list[i]);
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP);
|
||||
j = j + pdu_info->li_list[i];
|
||||
}
|
||||
for (i=0; i < pdu_info->num_li; i++) {
|
||||
LOG_D(RLC, "%d ",pdu_info->li_list[i]);
|
||||
}
|
||||
|
||||
if (pdu_info->hidden_size > 0) { // normally should always be > 0 but just for help debug
|
||||
// data is already ok, done by last loop above
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, &pdu_info->payload[j], pdu_info->hidden_size);
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP);
|
||||
}
|
||||
LOG_D(RLC, "\n");
|
||||
//msg(" remaining size %d\n",size);
|
||||
j = 0;
|
||||
|
||||
//rlc_pP->reassembly_missing_sn_detected = 0;
|
||||
break;
|
||||
for (i = 0; i < pdu_info->num_li; i++) {
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, &pdu_info->payload[j], pdu_info->li_list[i]);
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP);
|
||||
j = j + pdu_info->li_list[i];
|
||||
}
|
||||
|
||||
case RLC_FI_1ST_BYTE_DATA_IS_NOT_1ST_BYTE_SDU_LAST_BYTE_DATA_IS_NOT_LAST_BYTE_SDU:
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PDU] TRY REASSEMBLY PDU FI=00 (11) Li=",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
if (pdu_info->hidden_size > 0) { // normally should always be > 0 but just for help debug
|
||||
// data is already ok, done by last loop above
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, &pdu_info->payload[j], pdu_info->hidden_size);
|
||||
}
|
||||
|
||||
for (i=0; i < pdu_info->num_li; i++) {
|
||||
LOG_D(RLC, "%d ",pdu_info->li_list[i]);
|
||||
}
|
||||
//rlc_pP->reassembly_missing_sn_detected = 0;
|
||||
break;
|
||||
|
||||
LOG_D(RLC, "\n");
|
||||
//msg(" remaining size %d\n",size);
|
||||
j = 0;
|
||||
|
||||
for (i = 0; i < pdu_info->num_li; i++) {
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, &pdu_info->payload[j], pdu_info->li_list[i]);
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP);
|
||||
j = j + pdu_info->li_list[i];
|
||||
}
|
||||
|
||||
if (pdu_info->hidden_size > 0) { // normally should always be > 0 but just for help debug
|
||||
// data is already ok, done by last loop above
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, &pdu_info->payload[j], pdu_info->hidden_size);
|
||||
}
|
||||
|
||||
//rlc_pP->reassembly_missing_sn_detected = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
//Assertion(eNB)_PRAN_DesignDocument_annex No.1429
|
||||
LOG_E(RLC, "not RLC_E_FIXED_PART_DATA_FIELD_FOLLOW error pdu_info->fi[%d]\n", pdu_info->fi);
|
||||
// assert(1 != 1);
|
||||
default:
|
||||
//Assertion(eNB)_PRAN_DesignDocument_annex No.1429
|
||||
LOG_E(RLC, "not RLC_E_FIXED_PART_DATA_FIELD_FOLLOW error pdu_info->fi[%d]\n", pdu_info->fi);
|
||||
// assert(1 != 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (free_rlc_pdu) {
|
||||
free_mem_block(tb_pP, __func__);
|
||||
free_mem_block(tb_pP, __func__);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,59 +27,19 @@
|
||||
#include "platform_types.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
#if ENABLE_ITTI
|
||||
# include "intertask_interface.h"
|
||||
#include "intertask_interface.h"
|
||||
#endif
|
||||
#include "assertions.h"
|
||||
#include "list.h"
|
||||
#include "rlc_am.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
|
||||
# if ENABLE_ITTI
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_itti_display_status_ind_infos(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
const rlc_am_entity_t *const rlc_pP,
|
||||
const rlc_am_control_pdu_info_t *const pdu_info_pP)
|
||||
{
|
||||
char message_string[1000];
|
||||
size_t message_string_size = 0;
|
||||
MessageDef *msg_p;
|
||||
|
||||
int num_nack;
|
||||
|
||||
if (!pdu_info_pP->d_c) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], "Bearer : %u\n", rlc_pP->rb_id);
|
||||
message_string_size += sprintf(&message_string[message_string_size], "CONTROL PDU ACK SN %04d", pdu_info_pP->ack_sn);
|
||||
|
||||
for (num_nack = 0; num_nack < pdu_info_pP->num_nack; num_nack++) {
|
||||
if (pdu_info_pP->nack_list[num_nack].e2) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], "\n\tNACK SN %04d SO START %05d SO END %05d", pdu_info_pP->nack_list[num_nack].nack_sn,
|
||||
pdu_info_pP->nack_list[num_nack].so_start,
|
||||
pdu_info_pP->nack_list[num_nack].so_end);
|
||||
} else {
|
||||
message_string_size += sprintf(&message_string[message_string_size], "\n\tNACK SN %04d", pdu_info_pP->nack_list[num_nack].nack_sn);
|
||||
}
|
||||
}
|
||||
|
||||
message_string_size += sprintf(&message_string[message_string_size], "\n");
|
||||
|
||||
msg_p = itti_alloc_new_message_sized (ctxt_pP->enb_flag > 0 ? TASK_RLC_ENB:TASK_RLC_UE , RLC_AM_STATUS_PDU_IND, message_string_size + sizeof (IttiMsgText));
|
||||
msg_p->ittiMsg.rlc_am_status_pdu_ind.size = message_string_size;
|
||||
memcpy(&msg_p->ittiMsg.rlc_am_status_pdu_ind.text, message_string, message_string_size);
|
||||
|
||||
itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->instance, msg_p);
|
||||
}
|
||||
}
|
||||
|
||||
# endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
uint16_t rlc_am_read_bit_field(
|
||||
uint8_t** data_ppP,
|
||||
unsigned int* bit_pos_pP,
|
||||
const signed int bits_to_readP)
|
||||
{
|
||||
uint8_t **data_ppP,
|
||||
unsigned int *bit_pos_pP,
|
||||
const signed int bits_to_readP) {
|
||||
uint16_t value = 0;
|
||||
unsigned int bits_read = 0;
|
||||
signed int bits_to_read = bits_to_readP;
|
||||
@@ -113,11 +73,10 @@ uint16_t rlc_am_read_bit_field(
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_write8_bit_field(
|
||||
uint8_t** data_ppP,
|
||||
unsigned int* bit_pos_pP,
|
||||
uint8_t **data_ppP,
|
||||
unsigned int *bit_pos_pP,
|
||||
const signed int bits_to_writeP,
|
||||
const uint8_t valueP)
|
||||
{
|
||||
const uint8_t valueP) {
|
||||
unsigned int available_bits;
|
||||
signed int bits_to_write= bits_to_writeP;
|
||||
|
||||
@@ -148,11 +107,10 @@ rlc_am_write8_bit_field(
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_write16_bit_field(
|
||||
uint8_t** data_ppP,
|
||||
unsigned int* bit_pos_pP,
|
||||
uint8_t **data_ppP,
|
||||
unsigned int *bit_pos_pP,
|
||||
signed int bits_to_writeP,
|
||||
const uint16_t valueP)
|
||||
{
|
||||
const uint16_t valueP) {
|
||||
//assert(bits_to_writeP <= 16);
|
||||
if(bits_to_writeP > 16) {
|
||||
LOG_E(RLC, "bits_to_writeP error. %d\n", bits_to_writeP);
|
||||
@@ -168,15 +126,12 @@ rlc_am_write16_bit_field(
|
||||
//-----------------------------------------------------------------------------
|
||||
signed int
|
||||
rlc_am_get_control_pdu_infos(
|
||||
rlc_am_pdu_sn_10_t* const header_pP,
|
||||
sdu_size_t * const total_size_pP,
|
||||
rlc_am_control_pdu_info_t* const pdu_info_pP)
|
||||
{
|
||||
rlc_am_pdu_sn_10_t *const header_pP,
|
||||
sdu_size_t *const total_size_pP,
|
||||
rlc_am_control_pdu_info_t *const pdu_info_pP) {
|
||||
memset(pdu_info_pP, 0, sizeof (rlc_am_control_pdu_info_t));
|
||||
|
||||
pdu_info_pP->d_c = header_pP->b1 >> 7;
|
||||
|
||||
|
||||
if (!pdu_info_pP->d_c) {
|
||||
pdu_info_pP->cpt = (header_pP->b1 >> 4) & 0x07;
|
||||
|
||||
@@ -191,7 +146,7 @@ rlc_am_get_control_pdu_infos(
|
||||
if (pdu_info_pP->e1) {
|
||||
unsigned int nack_to_read = 1;
|
||||
unsigned int bit_pos = 7; // range from 0 (MSB/left) to 7 (LSB/right)
|
||||
uint8_t* byte_pos_p = &header_pP->b2;
|
||||
uint8_t *byte_pos_p = &header_pP->b2;
|
||||
|
||||
while (nack_to_read) {
|
||||
pdu_info_pP->nack_list[pdu_info_pP->num_nack].nack_sn = rlc_am_read_bit_field(&byte_pos_p, &bit_pos, 10);
|
||||
@@ -214,9 +169,11 @@ rlc_am_get_control_pdu_infos(
|
||||
if (!pdu_info_pP->nack_list[pdu_info_pP->num_nack - 1].e1) {
|
||||
nack_to_read = 0;
|
||||
*total_size_pP = *total_size_pP - (sdu_size_t)((uint64_t)byte_pos_p + (uint64_t)((bit_pos + 7)/8) - (uint64_t)header_pP);
|
||||
|
||||
if (*total_size_pP != 0) {
|
||||
LOG_E(RLC, "[RLC_AM_GET_CONTROL_PDU_INFOS][FIRST]header_pP->b1=%d,header_pP->b2=%d\n",header_pP->b1,header_pP->b2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -230,9 +187,11 @@ rlc_am_get_control_pdu_infos(
|
||||
} else {
|
||||
*total_size_pP = *total_size_pP - 2;
|
||||
}
|
||||
|
||||
if (*total_size_pP != 0) {
|
||||
LOG_E(RLC, "[RLC_AM_GET_CONTROL_PDU_INFOS][SECOND]header_pP->b1=%d,header_pP->b2=%d\n",header_pP->b1,header_pP->b2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
@@ -241,9 +200,8 @@ rlc_am_get_control_pdu_infos(
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_display_control_pdu_infos(
|
||||
const rlc_am_control_pdu_info_t* const pdu_info_pP
|
||||
)
|
||||
{
|
||||
const rlc_am_control_pdu_info_t *const pdu_info_pP
|
||||
) {
|
||||
int num_nack;
|
||||
|
||||
if (!pdu_info_pP->d_c) {
|
||||
@@ -267,25 +225,23 @@ rlc_am_display_control_pdu_infos(
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_receive_process_control_pdu(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rlc_am_entity_t *const rlc_pP,
|
||||
mem_block_t* const tb_pP,
|
||||
uint8_t** first_byte_ppP,
|
||||
sdu_size_t * const tb_size_in_bytes_pP)
|
||||
{
|
||||
rlc_am_pdu_sn_10_t *rlc_am_pdu_sn_10_p = (rlc_am_pdu_sn_10_t*)*first_byte_ppP;
|
||||
mem_block_t *const tb_pP,
|
||||
uint8_t **first_byte_ppP,
|
||||
sdu_size_t *const tb_size_in_bytes_pP) {
|
||||
rlc_am_pdu_sn_10_t *rlc_am_pdu_sn_10_p = (rlc_am_pdu_sn_10_t *)*first_byte_ppP;
|
||||
sdu_size_t initial_pdu_size = *tb_size_in_bytes_pP;
|
||||
rlc_sn_t ack_sn = RLC_AM_NEXT_SN(rlc_pP->vt_a);
|
||||
rlc_sn_t sn_cursor = rlc_pP->vt_a;
|
||||
rlc_sn_t vt_a_new = rlc_pP->vt_a;
|
||||
rlc_sn_t sn_data_cnf;
|
||||
rlc_sn_t vt_a_new = rlc_pP->vt_a;
|
||||
rlc_sn_t sn_data_cnf;
|
||||
rlc_sn_t nack_sn,prev_nack_sn;
|
||||
sdu_size_t data_cnf_so_stop = 0x7FFF;
|
||||
sdu_size_t data_cnf_so_stop = 0x7FFF;
|
||||
unsigned int nack_index;
|
||||
boolean_t status = TRUE;
|
||||
|
||||
if (rlc_am_get_control_pdu_infos(rlc_am_pdu_sn_10_p, tb_size_in_bytes_pP, &rlc_pP->control_pdu_info) >= 0) {
|
||||
|
||||
rlc_am_tx_buffer_display(ctxt_pP, rlc_pP, " TX BUFFER BEFORE PROCESS OF STATUS PDU");
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" RX CONTROL PDU VT(A) %04d VT(S) %04d POLL_SN %04d ACK_SN %04d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
@@ -294,7 +250,6 @@ rlc_am_receive_process_control_pdu(
|
||||
rlc_pP->poll_sn,
|
||||
rlc_pP->control_pdu_info.ack_sn);
|
||||
rlc_am_display_control_pdu_infos(&rlc_pP->control_pdu_info);
|
||||
|
||||
ack_sn = rlc_pP->control_pdu_info.ack_sn;
|
||||
// 5.2.1 Retransmission
|
||||
//
|
||||
@@ -326,8 +281,7 @@ rlc_am_receive_process_control_pdu(
|
||||
|
||||
/* Note : ackSn can be equal to current vtA only in case the status pdu contains a list of nack_sn with same value = vtA with SOStart/SOEnd */
|
||||
/* and meaning the report is not complete due to not enough ressources to fill all SOStart/SOEnd of this NACK_SN */
|
||||
if (RLC_AM_DIFF_SN(rlc_pP->vt_s,rlc_pP->vt_a) >= RLC_AM_DIFF_SN(ack_sn,rlc_pP->vt_a))
|
||||
{
|
||||
if (RLC_AM_DIFF_SN(rlc_pP->vt_s,rlc_pP->vt_a) >= RLC_AM_DIFF_SN(ack_sn,rlc_pP->vt_a)) {
|
||||
if (rlc_pP->control_pdu_info.num_nack == 0) {
|
||||
while (sn_cursor != ack_sn) {
|
||||
rlc_am_ack_pdu(ctxt_pP, rlc_pP, sn_cursor,TRUE);
|
||||
@@ -342,63 +296,56 @@ rlc_am_receive_process_control_pdu(
|
||||
prev_nack_sn = 0x3FFF;
|
||||
|
||||
while (sn_cursor != nack_sn) {
|
||||
rlc_am_ack_pdu(ctxt_pP, rlc_pP, sn_cursor,TRUE);
|
||||
sn_cursor = RLC_AM_NEXT_SN(sn_cursor);
|
||||
rlc_am_ack_pdu(ctxt_pP, rlc_pP, sn_cursor,TRUE);
|
||||
sn_cursor = RLC_AM_NEXT_SN(sn_cursor);
|
||||
}
|
||||
|
||||
vt_a_new = nack_sn;
|
||||
|
||||
// catch DataCfn
|
||||
rlc_am_tx_data_pdu_management_t *tx_data_pdu_buffer_p = &rlc_pP->tx_data_pdu_buffer[nack_sn % RLC_AM_WINDOW_SIZE];
|
||||
if (tx_data_pdu_buffer_p->retx_payload_size == tx_data_pdu_buffer_p->payload_size) {
|
||||
sn_data_cnf = RLC_AM_PREV_SN(nack_sn);
|
||||
}
|
||||
else if (tx_data_pdu_buffer_p->nack_so_start != 0) {
|
||||
sn_data_cnf = nack_sn;
|
||||
data_cnf_so_stop = tx_data_pdu_buffer_p->nack_so_start - 1;
|
||||
}
|
||||
else {
|
||||
sn_data_cnf = RLC_AM_PREV_SN(nack_sn);
|
||||
}
|
||||
|
||||
if (tx_data_pdu_buffer_p->retx_payload_size == tx_data_pdu_buffer_p->payload_size) {
|
||||
sn_data_cnf = RLC_AM_PREV_SN(nack_sn);
|
||||
} else if (tx_data_pdu_buffer_p->nack_so_start != 0) {
|
||||
sn_data_cnf = nack_sn;
|
||||
data_cnf_so_stop = tx_data_pdu_buffer_p->nack_so_start - 1;
|
||||
} else {
|
||||
sn_data_cnf = RLC_AM_PREV_SN(nack_sn);
|
||||
}
|
||||
|
||||
while ((sn_cursor != ack_sn) && (status)) {
|
||||
if (sn_cursor != nack_sn) {
|
||||
rlc_am_ack_pdu(ctxt_pP,
|
||||
rlc_pP,
|
||||
sn_cursor,
|
||||
FALSE);
|
||||
FALSE);
|
||||
} else {
|
||||
status = rlc_am_nack_pdu (ctxt_pP,
|
||||
rlc_pP,
|
||||
nack_sn,
|
||||
prev_nack_sn,
|
||||
rlc_pP->control_pdu_info.nack_list[nack_index].so_start,
|
||||
rlc_pP->control_pdu_info.nack_list[nack_index].so_end);
|
||||
|
||||
status = rlc_am_nack_pdu (ctxt_pP,
|
||||
rlc_pP,
|
||||
nack_sn,
|
||||
prev_nack_sn,
|
||||
rlc_pP->control_pdu_info.nack_list[nack_index].so_start,
|
||||
rlc_pP->control_pdu_info.nack_list[nack_index].so_end);
|
||||
nack_index = nack_index + 1;
|
||||
prev_nack_sn = nack_sn;
|
||||
|
||||
if (nack_index < rlc_pP->control_pdu_info.num_nack) {
|
||||
nack_sn = rlc_pP->control_pdu_info.nack_list[nack_index].nack_sn;
|
||||
}
|
||||
else if (nack_sn != ack_sn) {
|
||||
/* general case*/
|
||||
nack_sn = ack_sn;
|
||||
}
|
||||
else {
|
||||
/*specific case when the sender did not have enough TBS to fill all SOStart SOEnd for this NACK_SN */
|
||||
break;
|
||||
nack_sn = rlc_pP->control_pdu_info.nack_list[nack_index].nack_sn;
|
||||
} else if (nack_sn != ack_sn) {
|
||||
/* general case*/
|
||||
nack_sn = ack_sn;
|
||||
} else {
|
||||
/*specific case when the sender did not have enough TBS to fill all SOStart SOEnd for this NACK_SN */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (prev_nack_sn != nack_sn) {
|
||||
/* do not increment sn_cursor in case of several informations for the same nack_sn */
|
||||
sn_cursor = (sn_cursor + 1) & RLC_AM_SN_MASK;
|
||||
/* do not increment sn_cursor in case of several informations for the same nack_sn */
|
||||
sn_cursor = (sn_cursor + 1) & RLC_AM_SN_MASK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT" WARNING CONTROL PDU ACK SN %d OUT OF WINDOW vtA=%d vtS=%d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),ack_sn,rlc_pP->vt_a,rlc_pP->vt_s);
|
||||
@@ -413,61 +360,57 @@ rlc_am_receive_process_control_pdu(
|
||||
}
|
||||
|
||||
if (status) {
|
||||
/* Check for Stopping TpollReTx */
|
||||
if ((rlc_pP->poll_sn != RLC_SN_UNDEFINED) &&
|
||||
(RLC_AM_DIFF_SN(ack_sn,rlc_pP->vt_a) > RLC_AM_DIFF_SN(rlc_pP->poll_sn,rlc_pP->vt_a))) {
|
||||
rlc_am_stop_and_reset_timer_poll_retransmit(ctxt_pP, rlc_pP);
|
||||
rlc_pP->poll_sn = RLC_SN_UNDEFINED;
|
||||
/* Check for Stopping TpollReTx */
|
||||
if ((rlc_pP->poll_sn != RLC_SN_UNDEFINED) &&
|
||||
(RLC_AM_DIFF_SN(ack_sn,rlc_pP->vt_a) > RLC_AM_DIFF_SN(rlc_pP->poll_sn,rlc_pP->vt_a))) {
|
||||
rlc_am_stop_and_reset_timer_poll_retransmit(ctxt_pP, rlc_pP);
|
||||
rlc_pP->poll_sn = RLC_SN_UNDEFINED;
|
||||
}
|
||||
|
||||
//TODO : this part does not cover all cases of Data Cnf and move it at the end of Status PDU processing
|
||||
sn_cursor = rlc_pP->vt_a;
|
||||
|
||||
// Fix Issue 238 : check sn_data_cnf has been transmitted
|
||||
if ((rlc_pP->tx_data_pdu_buffer[sn_data_cnf % RLC_AM_WINDOW_SIZE].flags.transmitted) &&
|
||||
(rlc_pP->tx_data_pdu_buffer[sn_data_cnf % RLC_AM_WINDOW_SIZE].sn == sn_data_cnf)) {
|
||||
/* Handle all acked PDU up to and excluding sn_data_cnf */
|
||||
while (sn_cursor != sn_data_cnf) {
|
||||
rlc_am_pdu_sdu_data_cnf(ctxt_pP,rlc_pP,sn_cursor);
|
||||
sn_cursor = RLC_AM_NEXT_SN(sn_cursor);
|
||||
}
|
||||
|
||||
//TODO : this part does not cover all cases of Data Cnf and move it at the end of Status PDU processing
|
||||
sn_cursor = rlc_pP->vt_a;
|
||||
|
||||
// Fix Issue 238 : check sn_data_cnf has been transmitted
|
||||
if ((rlc_pP->tx_data_pdu_buffer[sn_data_cnf % RLC_AM_WINDOW_SIZE].flags.transmitted) &&
|
||||
(rlc_pP->tx_data_pdu_buffer[sn_data_cnf % RLC_AM_WINDOW_SIZE].sn == sn_data_cnf)) {
|
||||
/* Handle all acked PDU up to and excluding sn_data_cnf */
|
||||
while (sn_cursor != sn_data_cnf) {
|
||||
rlc_am_pdu_sdu_data_cnf(ctxt_pP,rlc_pP,sn_cursor);
|
||||
sn_cursor = RLC_AM_NEXT_SN(sn_cursor);
|
||||
}
|
||||
|
||||
// Handle last SN. TO DO : case of PDU partially ACKED with SDU to be data conf
|
||||
if (data_cnf_so_stop == 0x7FFF) {
|
||||
rlc_am_pdu_sdu_data_cnf(ctxt_pP,rlc_pP,sn_data_cnf);
|
||||
}
|
||||
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" RECEIVE STATUS PDU ACK_SN=%d NewvtA=%d OldvtA=%d SnDataCnf=%d DataCnfSOStop=%d vtS=%d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),ack_sn,vt_a_new,rlc_pP->vt_a,sn_data_cnf,data_cnf_so_stop,rlc_pP->vt_s);
|
||||
}
|
||||
else {
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" RECEIVE STATUS PDU WITH NO SDU CNF ACK_SN=%d NewvtA=%d OldvtA=%d vtS=%d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),ack_sn,vt_a_new,rlc_pP->vt_a,rlc_pP->vt_s);
|
||||
// Handle last SN. TO DO : case of PDU partially ACKED with SDU to be data conf
|
||||
if (data_cnf_so_stop == 0x7FFF) {
|
||||
rlc_am_pdu_sdu_data_cnf(ctxt_pP,rlc_pP,sn_data_cnf);
|
||||
}
|
||||
|
||||
/* Update vtA and vtMS */
|
||||
rlc_pP->vt_a = vt_a_new;
|
||||
rlc_pP->vt_ms = (rlc_pP->vt_a + RLC_AM_WINDOW_SIZE) & RLC_AM_SN_MASK;
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" RECEIVE STATUS PDU ACK_SN=%d NewvtA=%d OldvtA=%d SnDataCnf=%d DataCnfSOStop=%d vtS=%d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),ack_sn,vt_a_new,rlc_pP->vt_a,sn_data_cnf,data_cnf_so_stop,rlc_pP->vt_s);
|
||||
} else {
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" RECEIVE STATUS PDU WITH NO SDU CNF ACK_SN=%d NewvtA=%d OldvtA=%d vtS=%d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),ack_sn,vt_a_new,rlc_pP->vt_a,rlc_pP->vt_s);
|
||||
}
|
||||
|
||||
/* Update vtA and vtMS */
|
||||
rlc_pP->vt_a = vt_a_new;
|
||||
rlc_pP->vt_ms = (rlc_pP->vt_a + RLC_AM_WINDOW_SIZE) & RLC_AM_SN_MASK;
|
||||
}
|
||||
|
||||
*first_byte_ppP = (uint8_t*)((uint64_t)*first_byte_ppP + initial_pdu_size - *tb_size_in_bytes_pP);
|
||||
|
||||
*first_byte_ppP = (uint8_t *)((uint64_t)*first_byte_ppP + initial_pdu_size - *tb_size_in_bytes_pP);
|
||||
free_mem_block(tb_pP, __func__);
|
||||
rlc_am_tx_buffer_display(ctxt_pP, rlc_pP, NULL);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
int
|
||||
rlc_am_write_status_pdu(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rlc_am_entity_t *const rlc_pP,
|
||||
rlc_am_pdu_sn_10_t* const rlc_am_pdu_sn_10_pP,
|
||||
rlc_am_control_pdu_info_t* const pdu_info_pP)
|
||||
{
|
||||
rlc_am_pdu_sn_10_t *const rlc_am_pdu_sn_10_pP,
|
||||
rlc_am_control_pdu_info_t *const pdu_info_pP) {
|
||||
unsigned int bit_pos = 4; // range from 0 (MSB/left) to 7 (LSB/right)
|
||||
uint8_t* byte_pos_p = &rlc_am_pdu_sn_10_pP->b1;
|
||||
uint8_t *byte_pos_p = &rlc_am_pdu_sn_10_pP->b1;
|
||||
unsigned int index = 0;
|
||||
unsigned int num_bytes = 0;
|
||||
|
||||
rlc_am_write16_bit_field(&byte_pos_p, &bit_pos, 10, pdu_info_pP->ack_sn);
|
||||
|
||||
if (pdu_info_pP->num_nack > 0) {
|
||||
@@ -495,20 +438,17 @@ rlc_am_write_status_pdu(
|
||||
num_bytes += 1;
|
||||
}
|
||||
|
||||
#if TRACE_RLC_AM_STATUS_CREATION
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" WROTE STATUS PDU %d BYTES\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
num_bytes);
|
||||
#endif
|
||||
return num_bytes;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_send_status_pdu(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rlc_am_entity_t *const rlc_pP
|
||||
)
|
||||
{
|
||||
) {
|
||||
// When STATUS reporting has been triggered, the receiving side of an AM RLC entity shall:
|
||||
// - if t-StatusProhibit is not running:
|
||||
// - at the first transmission opportunity indicated by lower layer, construct a STATUS PDU and deliver it to lower layer;
|
||||
@@ -530,10 +470,9 @@ rlc_am_send_status_pdu(
|
||||
// - include in the STATUS PDU a set of NACK_SN, SOstart and SOend
|
||||
// - set the ACK_SN to the SN of the next not received RLC Data PDU which is not indicated as missing in the
|
||||
// resulting STATUS PDU.
|
||||
|
||||
signed int nb_bits_to_transmit = rlc_pP->nb_bytes_requested_by_mac << 3;
|
||||
// minimum header size in bits to be transmitted: D/C + CPT + ACK_SN + E1
|
||||
signed int nb_bits_transmitted = RLC_AM_PDU_D_C_BITS + RLC_AM_STATUS_PDU_CPT_LENGTH + RLC_AM_SN_BITS + RLC_AM_PDU_E_BITS;
|
||||
signed int nb_bits_transmitted = RLC_AM_PDU_D_C_BITS + RLC_AM_STATUS_PDU_CPT_LENGTH + RLC_AM_SN_BITS + RLC_AM_PDU_E_BITS;
|
||||
rlc_am_control_pdu_info_t control_pdu_info;
|
||||
rlc_am_pdu_info_t *pdu_info_cursor_p = NULL;
|
||||
rlc_sn_t sn_cursor = 0;
|
||||
@@ -543,325 +482,278 @@ rlc_am_send_status_pdu(
|
||||
int waited_so = 0;
|
||||
mem_block_t *tb_p = NULL;
|
||||
sdu_size_t pdu_size = 0;
|
||||
boolean_t status_report_completed = false;
|
||||
boolean_t segment_loop_end = false;
|
||||
|
||||
boolean_t status_report_completed = false;
|
||||
boolean_t segment_loop_end = false;
|
||||
memset(&control_pdu_info, 0, sizeof(rlc_am_control_pdu_info_t));
|
||||
|
||||
#if TRACE_RLC_AM_STATUS_CREATION
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] nb_bits_to_transmit %d (15 already allocated for header)\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
nb_bits_to_transmit);
|
||||
rlc_am_rx_list_display(rlc_pP, " DISPLAY BEFORE CONSTRUCTION OF STATUS REPORT");
|
||||
#endif
|
||||
|
||||
/* Handle no NACK first */
|
||||
if (rlc_pP->vr_r == rlc_pP->vr_ms) {
|
||||
|
||||
control_pdu_info.ack_sn = rlc_pP->vr_ms;
|
||||
status_report_completed = true;
|
||||
#if TRACE_RLC_AM_STATUS_CREATION
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d ALL ACK WITH ACK_SN %04d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
__LINE__,
|
||||
rlc_pP->vr_ms);
|
||||
#endif
|
||||
}
|
||||
else if ((cursor_p != NULL) && ((nb_bits_transmitted + RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1)) <= nb_bits_to_transmit)) {
|
||||
|
||||
pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info;
|
||||
control_pdu_info.ack_sn = rlc_pP->vr_ms;
|
||||
status_report_completed = true;
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d ALL ACK WITH ACK_SN %04d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
__LINE__,
|
||||
rlc_pP->vr_ms);
|
||||
} else if ((cursor_p != NULL) && ((nb_bits_transmitted + RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1)) <= nb_bits_to_transmit)) {
|
||||
pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t *)(cursor_p->data))->pdu_info;
|
||||
sn_cursor = pdu_info_cursor_p->sn;
|
||||
|
||||
/* Set E1 bit for the presence of first NACK_SN/E1/E2 */
|
||||
control_pdu_info.e1 = 1;
|
||||
|
||||
// 12 bits = size of NACK_SN field + E1, E2 bits
|
||||
// 42 bits = size of NACK_SN field + SO_START, SO_END fields, E1, E2 bits
|
||||
while ((!status_report_completed) && (RLC_AM_DIFF_SN(sn_nack,rlc_pP->vr_r) < RLC_AM_DIFF_SN(rlc_pP->vr_ms,rlc_pP->vr_r))
|
||||
&& (cursor_p != NULL) && (nb_bits_transmitted <= nb_bits_to_transmit)) {
|
||||
|
||||
pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info;
|
||||
&& (cursor_p != NULL) && (nb_bits_transmitted <= nb_bits_to_transmit)) {
|
||||
pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t *)(cursor_p->data))->pdu_info;
|
||||
sn_cursor = pdu_info_cursor_p->sn;
|
||||
all_segments_received = ((rlc_am_rx_pdu_management_t*)(cursor_p->data))->all_segments_received;
|
||||
all_segments_received = ((rlc_am_rx_pdu_management_t *)(cursor_p->data))->all_segments_received;
|
||||
|
||||
/* First fill NACK_SN with each missing PDU between current sn_nack and sn_cursor */
|
||||
while ((sn_nack != sn_cursor) && (RLC_AM_DIFF_SN(sn_nack,rlc_pP->vr_r) < RLC_AM_DIFF_SN(rlc_pP->vr_ms,rlc_pP->vr_r))) {
|
||||
if (nb_bits_transmitted + RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) <= nb_bits_to_transmit) {
|
||||
/* Fill NACK_SN infos */
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].nack_sn = sn_nack;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].so_start = 0;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].so_end = RLC_AM_STATUS_PDU_SO_END_ALL_BYTES;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].e2 = 0;
|
||||
/* Set E1 for next NACK_SN. The last one will be cleared */
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].e1 = 1;
|
||||
control_pdu_info.num_nack += 1;
|
||||
nb_bits_transmitted += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1));
|
||||
#if TRACE_RLC_AM_STATUS_CREATION
|
||||
if (nb_bits_transmitted + RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) <= nb_bits_to_transmit) {
|
||||
/* Fill NACK_SN infos */
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].nack_sn = sn_nack;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].so_start = 0;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].so_end = RLC_AM_STATUS_PDU_SO_END_ALL_BYTES;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].e2 = 0;
|
||||
/* Set E1 for next NACK_SN. The last one will be cleared */
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].e1 = 1;
|
||||
control_pdu_info.num_nack += 1;
|
||||
nb_bits_transmitted += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1));
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d PREPARE SENDING NACK %04d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
__LINE__,
|
||||
sn_nack);
|
||||
#endif
|
||||
sn_nack = RLC_AM_NEXT_SN(sn_nack);
|
||||
}
|
||||
else {
|
||||
/* Not enough UL TBS*/
|
||||
/* latest value of sn_nack shall be used as ACK_SN */
|
||||
control_pdu_info.ack_sn = sn_nack;
|
||||
status_report_completed = true;
|
||||
#if TRACE_RLC_AM_STATUS_CREATION
|
||||
sn_nack);
|
||||
sn_nack = RLC_AM_NEXT_SN(sn_nack);
|
||||
} else {
|
||||
/* Not enough UL TBS*/
|
||||
/* latest value of sn_nack shall be used as ACK_SN */
|
||||
control_pdu_info.ack_sn = sn_nack;
|
||||
status_report_completed = true;
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d NOT ENOUGH TBS STOP WITH ACK_SN %04d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
__LINE__,
|
||||
sn_nack);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
sn_nack);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sn_nack == rlc_pP->vr_ms) {
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Now process all Segments of sn_cursor if PDU not fully received */
|
||||
if ((!status_report_completed) && (all_segments_received == 0) && (sn_cursor != rlc_pP->vr_ms)) {
|
||||
//AssertFatal (sn_nack == sn_cursor, "RLC AM Tx Status PDU Data sn_nack=%d and sn_cursor=%d should be equal LcId=%d\n",sn_nack,sn_cursor, rlc_pP->channel_id);
|
||||
if(sn_nack != sn_cursor){
|
||||
LOG_E(RLC, "RLC AM Tx Status PDU Data sn_nack=%d and sn_cursor=%d should be equal LcId=%d\n",sn_nack,sn_cursor, rlc_pP->channel_id);
|
||||
}
|
||||
|
||||
/* First ensure there is enough TBS for at least 1 SOStart/SOEnd, else break */
|
||||
//AssertFatal (sn_nack == sn_cursor, "RLC AM Tx Status PDU Data sn_nack=%d and sn_cursor=%d should be equal LcId=%d\n",sn_nack,sn_cursor, rlc_pP->channel_id);
|
||||
if(sn_nack != sn_cursor) {
|
||||
LOG_E(RLC, "RLC AM Tx Status PDU Data sn_nack=%d and sn_cursor=%d should be equal LcId=%d\n",sn_nack,sn_cursor, rlc_pP->channel_id);
|
||||
}
|
||||
/* First ensure there is enough TBS for at least 1 SOStart/SOEnd, else break */
|
||||
else if ((nb_bits_transmitted + RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1)) <= nb_bits_to_transmit) {
|
||||
/* Init loop flags */
|
||||
/* Check lsf */
|
||||
segment_loop_end = (pdu_info_cursor_p->lsf == 1);
|
||||
/* Init loop flags */
|
||||
/* Check lsf */
|
||||
segment_loop_end = (pdu_info_cursor_p->lsf == 1);
|
||||
|
||||
/* Init first SO Start according to first segment */
|
||||
if (pdu_info_cursor_p->so) {
|
||||
/* Fill the first SO */
|
||||
/* Init first SO Start according to first segment */
|
||||
if (pdu_info_cursor_p->so) {
|
||||
/* Fill the first SO */
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].nack_sn = sn_cursor;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].so_start = 0;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].so_end = pdu_info_cursor_p->so - 1;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].e2 = 1;
|
||||
/* Set E1 for next NACK_SN. The last one will be cleared */
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].e1 = 1;
|
||||
control_pdu_info.num_nack += 1;
|
||||
nb_bits_transmitted += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1));
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d PREPARE SENDING NACK %04d SO START %05d SO END %05d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
__LINE__,
|
||||
sn_cursor,
|
||||
0,
|
||||
pdu_info_cursor_p->so - 1);
|
||||
waited_so = pdu_info_cursor_p->so + pdu_info_cursor_p->payload_size;
|
||||
} else {
|
||||
waited_so = pdu_info_cursor_p->payload_size;
|
||||
}
|
||||
|
||||
/* Go to next segment */
|
||||
cursor_p = cursor_p->next;
|
||||
|
||||
if (cursor_p != NULL) {
|
||||
pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t *)(cursor_p->data))->pdu_info;
|
||||
}
|
||||
|
||||
/* Find the first discontinuity and then fill SOStart/SOEnd */
|
||||
while (!segment_loop_end) {
|
||||
if ((cursor_p != NULL) && (pdu_info_cursor_p->sn == sn_cursor)) {
|
||||
/* PDU segment is for the same SN*/
|
||||
/* Check lsf */
|
||||
segment_loop_end = (pdu_info_cursor_p->lsf == 1);
|
||||
|
||||
if (waited_so < pdu_info_cursor_p->so) {
|
||||
/* SO is greater than previous received portion : gap identified to fill */
|
||||
if ((nb_bits_transmitted + RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1)) <= nb_bits_to_transmit) {
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].nack_sn = sn_cursor;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].so_start = 0;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].so_start = waited_so;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].so_end = pdu_info_cursor_p->so - 1;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].e2 = 1;
|
||||
/* Set E1 for next NACK_SN. The last one will be cleared */
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].e1 = 1;
|
||||
control_pdu_info.num_nack += 1;
|
||||
nb_bits_transmitted += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1));
|
||||
#if TRACE_RLC_AM_STATUS_CREATION
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d PREPARE SENDING NACK %04d SO START %05d SO END %05d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
__LINE__,
|
||||
sn_cursor,
|
||||
0,
|
||||
pdu_info_cursor_p->so - 1);
|
||||
#endif
|
||||
waited_so = pdu_info_cursor_p->so + pdu_info_cursor_p->payload_size;
|
||||
}
|
||||
else {
|
||||
waited_so = pdu_info_cursor_p->payload_size;
|
||||
}
|
||||
|
||||
/* Go to next segment */
|
||||
cursor_p = cursor_p->next;
|
||||
if (cursor_p != NULL)
|
||||
{
|
||||
pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info;
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d PREPARE SENDING NACK %04d SO START %05d SO END %05d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
__LINE__,
|
||||
sn_cursor,
|
||||
waited_so,
|
||||
pdu_info_cursor_p->so);
|
||||
} else {
|
||||
/* Not enough resources to set a SOStart/SEnd, then set ACK_SN to current NACK_SN and stop Status PDU build */
|
||||
control_pdu_info.ack_sn = sn_cursor;
|
||||
status_report_completed = true;
|
||||
segment_loop_end = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* contiguous segment: only update waited_so */
|
||||
/* Assuming so and payload_size updated according to duplication removal done at reception ... */
|
||||
waited_so += pdu_info_cursor_p->payload_size;
|
||||
}
|
||||
|
||||
/* Find the first discontinuity and then fill SOStart/SOEnd */
|
||||
while (!segment_loop_end) {
|
||||
if ((cursor_p != NULL) && (pdu_info_cursor_p->sn == sn_cursor)) {
|
||||
/* Go to next received PDU or PDU Segment */
|
||||
cursor_p = cursor_p->next;
|
||||
|
||||
/* PDU segment is for the same SN*/
|
||||
/* Check lsf */
|
||||
segment_loop_end = (pdu_info_cursor_p->lsf == 1);
|
||||
if (cursor_p != NULL) {
|
||||
pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t *)(cursor_p->data))->pdu_info;
|
||||
}
|
||||
} //end if (cursor_p != NULL) && (pdu_info_cursor_p->sn == sn_cursor)
|
||||
else {
|
||||
/* Previous PDU segment was the last one and did not have lsf indication : fill the latest gap */
|
||||
if ((nb_bits_transmitted + RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1)) <= nb_bits_to_transmit) {
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].nack_sn = sn_cursor;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].so_start = waited_so;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].so_end = RLC_AM_STATUS_PDU_SO_END_ALL_BYTES;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].e2 = 1;
|
||||
/* Set E1 for next NACK_SN. The last one will be cleared */
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].e1 = 1;
|
||||
control_pdu_info.num_nack += 1;
|
||||
nb_bits_transmitted += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1));
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d PREPARE SENDING LAST NACK %04d SO START %05d SO END %05d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
__LINE__,
|
||||
sn_cursor,
|
||||
waited_so,
|
||||
RLC_AM_STATUS_PDU_SO_END_ALL_BYTES);
|
||||
} else {
|
||||
/* Not enough resources to set a SOStart/SEnd, then set ACK_SN to current NACK_SN and stop Status PDU build */
|
||||
control_pdu_info.ack_sn = sn_cursor;
|
||||
status_report_completed = true;
|
||||
}
|
||||
|
||||
if (waited_so < pdu_info_cursor_p->so) {
|
||||
/* SO is greater than previous received portion : gap identified to fill */
|
||||
if ((nb_bits_transmitted + RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1)) <= nb_bits_to_transmit) {
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].nack_sn = sn_cursor;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].so_start = waited_so;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].so_end = pdu_info_cursor_p->so - 1;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].e2 = 1;
|
||||
/* Set E1 for next NACK_SN. The last one will be cleared */
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].e1 = 1;
|
||||
control_pdu_info.num_nack += 1;
|
||||
nb_bits_transmitted += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1));
|
||||
#if TRACE_RLC_AM_STATUS_CREATION
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d PREPARE SENDING NACK %04d SO START %05d SO END %05d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
__LINE__,
|
||||
sn_cursor,
|
||||
waited_so,
|
||||
pdu_info_cursor_p->so);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
/* Not enough resources to set a SOStart/SEnd, then set ACK_SN to current NACK_SN and stop Status PDU build */
|
||||
control_pdu_info.ack_sn = sn_cursor;
|
||||
status_report_completed = true;
|
||||
segment_loop_end = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* contiguous segment: only update waited_so */
|
||||
/* Assuming so and payload_size updated according to duplication removal done at reception ... */
|
||||
waited_so += pdu_info_cursor_p->payload_size;
|
||||
}
|
||||
|
||||
/* Go to next received PDU or PDU Segment */
|
||||
cursor_p = cursor_p->next;
|
||||
if (cursor_p != NULL)
|
||||
{
|
||||
pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info;
|
||||
}
|
||||
|
||||
} //end if (cursor_p != NULL) && (pdu_info_cursor_p->sn == sn_cursor)
|
||||
else {
|
||||
/* Previous PDU segment was the last one and did not have lsf indication : fill the latest gap */
|
||||
if ((nb_bits_transmitted + RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1)) <= nb_bits_to_transmit) {
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].nack_sn = sn_cursor;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].so_start = waited_so;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].so_end = RLC_AM_STATUS_PDU_SO_END_ALL_BYTES;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].e2 = 1;
|
||||
/* Set E1 for next NACK_SN. The last one will be cleared */
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].e1 = 1;
|
||||
control_pdu_info.num_nack += 1;
|
||||
nb_bits_transmitted += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1));
|
||||
#if TRACE_RLC_AM_STATUS_CREATION
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d PREPARE SENDING LAST NACK %04d SO START %05d SO END %05d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
__LINE__,
|
||||
sn_cursor,
|
||||
waited_so,
|
||||
RLC_AM_STATUS_PDU_SO_END_ALL_BYTES);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
/* Not enough resources to set a SOStart/SEnd, then set ACK_SN to current NACK_SN and stop Status PDU build */
|
||||
control_pdu_info.ack_sn = sn_cursor;
|
||||
status_report_completed = true;
|
||||
}
|
||||
|
||||
segment_loop_end = true;
|
||||
}
|
||||
} //end while (!segment_loop_end)
|
||||
} // end if enough resource for transmitting at least one SOStart/SOEnd
|
||||
else {
|
||||
/* Not enough UL TBS to set at least one SOStart/SOEnd */
|
||||
/* latest value of sn_nack shall be used as ACK_SN */
|
||||
control_pdu_info.ack_sn = sn_nack;
|
||||
status_report_completed = true;
|
||||
}
|
||||
segment_loop_end = true;
|
||||
}
|
||||
} //end while (!segment_loop_end)
|
||||
} // end if enough resource for transmitting at least one SOStart/SOEnd
|
||||
else {
|
||||
/* Not enough UL TBS to set at least one SOStart/SOEnd */
|
||||
/* latest value of sn_nack shall be used as ACK_SN */
|
||||
control_pdu_info.ack_sn = sn_nack;
|
||||
status_report_completed = true;
|
||||
}
|
||||
} // end while on all PDU segments of sn_cursor
|
||||
else {
|
||||
/* Go to next received PDU or PDU segment with different SN */
|
||||
do {
|
||||
cursor_p = cursor_p->next;
|
||||
} while ((cursor_p != NULL) && (((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info.sn == sn_cursor));
|
||||
/* Go to next received PDU or PDU segment with different SN */
|
||||
do {
|
||||
cursor_p = cursor_p->next;
|
||||
} while ((cursor_p != NULL) && (((rlc_am_rx_pdu_management_t *)(cursor_p->data))->pdu_info.sn == sn_cursor));
|
||||
}
|
||||
|
||||
/* Increment sn_nack except if sn_cursor = vrMS and if current SN was not fully received */
|
||||
if (RLC_AM_DIFF_SN(sn_cursor,rlc_pP->vr_r) < RLC_AM_DIFF_SN(rlc_pP->vr_ms,rlc_pP->vr_r)) {
|
||||
sn_nack = RLC_AM_NEXT_SN(sn_cursor);
|
||||
sn_nack = RLC_AM_NEXT_SN(sn_cursor);
|
||||
} else {
|
||||
sn_nack = rlc_pP->vr_ms;
|
||||
}
|
||||
else {
|
||||
sn_nack = rlc_pP->vr_ms;
|
||||
}
|
||||
|
||||
|
||||
} // End main while NACK_SN
|
||||
|
||||
/* Clear E1 of last nack_sn entry */
|
||||
// AssertFatal ((control_pdu_info.num_nack) || (all_segments_received == 0), "RLC AM Tx Status PDU Data Error no NACK_SN vrR=%d vrMS=%d lastSN_NACK=%d Completed=%d NbBytesAvailable=%d LcId=%d\n",
|
||||
// rlc_pP->vr_r,rlc_pP->vr_ms,sn_nack,status_report_completed,(nb_bits_to_transmit >> 3),rlc_pP->channel_id);
|
||||
if (!((control_pdu_info.num_nack) || (all_segments_received == 0))){
|
||||
LOG_E(RLC, "RLC AM Tx Status PDU Data Error no NACK_SN vrR=%d vrMS=%d lastSN_NACK=%d Completed=%d NbBytesAvailable=%d LcId=%d\n",
|
||||
rlc_pP->vr_r,rlc_pP->vr_ms,sn_nack,status_report_completed,(nb_bits_to_transmit >> 3),rlc_pP->channel_id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (control_pdu_info.num_nack) {
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack - 1].e1 = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Set ACK_SN unless it was set before */
|
||||
if (!status_report_completed){
|
||||
|
||||
control_pdu_info.ack_sn = sn_nack;
|
||||
// AssertFatal ((control_pdu_info.num_nack) || (all_segments_received == 0), "RLC AM Tx Status PDU Data Error no NACK_SN vrR=%d vrMS=%d lastSN_NACK=%d Completed=%d NbBytesAvailable=%d LcId=%d\n",
|
||||
// rlc_pP->vr_r,rlc_pP->vr_ms,sn_nack,status_report_completed,(nb_bits_to_transmit >> 3),rlc_pP->channel_id);
|
||||
if (!((control_pdu_info.num_nack) || (all_segments_received == 0))) {
|
||||
LOG_E(RLC, "RLC AM Tx Status PDU Data Error no NACK_SN vrR=%d vrMS=%d lastSN_NACK=%d Completed=%d NbBytesAvailable=%d LcId=%d\n",
|
||||
rlc_pP->vr_r,rlc_pP->vr_ms,sn_nack,status_report_completed,(nb_bits_to_transmit >> 3),rlc_pP->channel_id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (control_pdu_info.num_nack) {
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack - 1].e1 = 0;
|
||||
}
|
||||
|
||||
/* Set ACK_SN unless it was set before */
|
||||
if (!status_report_completed) {
|
||||
control_pdu_info.ack_sn = sn_nack;
|
||||
}
|
||||
} else {
|
||||
/* reception buffer empty or not enough TBS for filling at least 1 NACK_SN + E1 + E2 */
|
||||
/* reception buffer empty or not enough TBS for filling at least 1 NACK_SN + E1 + E2 */
|
||||
control_pdu_info.ack_sn = rlc_pP->vr_r;
|
||||
#if TRACE_RLC_AM_STATUS_CREATION
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d PREPARE SENDING ACK %04d = VR(R)\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
__LINE__,
|
||||
control_pdu_info.ack_sn);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//msg ("[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] nb_bits_to_transmit %d\n",
|
||||
// rlc_pP->module_id, rlc_pP->rb_id, ctxt_pP->frame,nb_bits_to_transmit);
|
||||
|
||||
#if TRACE_RLC_AM_STATUS_CREATION
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d PREPARE SENDING ACK %04d NUM NACK %d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
__LINE__,
|
||||
control_pdu_info.ack_sn,
|
||||
control_pdu_info.num_nack);
|
||||
#endif
|
||||
|
||||
|
||||
/* encode the control pdu */
|
||||
pdu_size = (nb_bits_transmitted + 7) >> 3;
|
||||
// AssertFatal (pdu_size <= rlc_pP->nb_bytes_requested_by_mac, "RLC AM Tx Status PDU Data size=%d bigger than remaining TBS=%d nb_bits_transmitted=%d LcId=%d\n",
|
||||
// pdu_size,rlc_pP->nb_bytes_requested_by_mac,nb_bits_transmitted, rlc_pP->channel_id);
|
||||
if(pdu_size > rlc_pP->nb_bytes_requested_by_mac){
|
||||
LOG_E(RLC, "RLC AM Tx Status PDU Data size=%d bigger than remaining TBS=%d nb_bits_transmitted=%d LcId=%d\n",
|
||||
pdu_size,rlc_pP->nb_bytes_requested_by_mac,nb_bits_transmitted, rlc_pP->channel_id);
|
||||
return;
|
||||
}
|
||||
|
||||
// AssertFatal (pdu_size <= rlc_pP->nb_bytes_requested_by_mac, "RLC AM Tx Status PDU Data size=%d bigger than remaining TBS=%d nb_bits_transmitted=%d LcId=%d\n",
|
||||
// pdu_size,rlc_pP->nb_bytes_requested_by_mac,nb_bits_transmitted, rlc_pP->channel_id);
|
||||
if(pdu_size > rlc_pP->nb_bytes_requested_by_mac) {
|
||||
LOG_E(RLC, "RLC AM Tx Status PDU Data size=%d bigger than remaining TBS=%d nb_bits_transmitted=%d LcId=%d\n",
|
||||
pdu_size,rlc_pP->nb_bytes_requested_by_mac,nb_bits_transmitted, rlc_pP->channel_id);
|
||||
return;
|
||||
}
|
||||
|
||||
#if TRACE_RLC_AM_STATUS_CREATION
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d forecast pdu_size %d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
__LINE__,
|
||||
pdu_size);
|
||||
#endif
|
||||
tb_p = get_free_mem_block(sizeof(struct mac_tb_req) + pdu_size, __func__);
|
||||
|
||||
if(tb_p == NULL) return;
|
||||
|
||||
memset(tb_p->data, 0, sizeof(struct mac_tb_req) + pdu_size);
|
||||
//estimation only ((struct mac_tb_req*)(tb_p->data))->tb_size = pdu_size;
|
||||
((struct mac_tb_req*)(tb_p->data))->data_ptr = (uint8_t*)&(tb_p->data[sizeof(struct mac_tb_req)]);
|
||||
|
||||
((struct mac_tb_req *)(tb_p->data))->data_ptr = (uint8_t *)&(tb_p->data[sizeof(struct mac_tb_req)]);
|
||||
// warning reuse of pdu_size
|
||||
// TODO : rlc_am_write_status_pdu should be rewritten as not very tested ...
|
||||
pdu_size = rlc_am_write_status_pdu(ctxt_pP, rlc_pP,(rlc_am_pdu_sn_10_t*)(((struct mac_tb_req*)(tb_p->data))->data_ptr), &control_pdu_info);
|
||||
((struct mac_tb_req*)(tb_p->data))->tb_size = pdu_size;
|
||||
pdu_size = rlc_am_write_status_pdu(ctxt_pP, rlc_pP,(rlc_am_pdu_sn_10_t *)(((struct mac_tb_req *)(tb_p->data))->data_ptr), &control_pdu_info);
|
||||
((struct mac_tb_req *)(tb_p->data))->tb_size = pdu_size;
|
||||
//assert((((struct mac_tb_req*)(tb_p->data))->tb_size) < 3000);
|
||||
|
||||
#if TRACE_RLC_AM_STATUS_CREATION
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] SEND STATUS PDU SIZE %d, rlc_pP->nb_bytes_requested_by_mac %d, nb_bits_to_transmit>>3 %d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
pdu_size,
|
||||
rlc_pP->nb_bytes_requested_by_mac,
|
||||
nb_bits_to_transmit >> 3);
|
||||
#endif
|
||||
|
||||
// AssertFatal (pdu_size == ((nb_bits_transmitted + 7) >> 3), "RLC AM Tx Status PDU Data encoding size=%d different than expected=%d LcId=%d\n",
|
||||
// pdu_size,((nb_bits_transmitted + 7) >> 3), rlc_pP->channel_id);
|
||||
if(pdu_size != ((nb_bits_transmitted + 7) >> 3)){
|
||||
LOG_E(RLC, "RLC AM Tx Status PDU Data encoding size=%d different than expected=%d LcId=%d\n",
|
||||
pdu_size,((nb_bits_transmitted + 7) >> 3), rlc_pP->channel_id);
|
||||
pdu_size = 0;
|
||||
return;
|
||||
}
|
||||
// AssertFatal (pdu_size == ((nb_bits_transmitted + 7) >> 3), "RLC AM Tx Status PDU Data encoding size=%d different than expected=%d LcId=%d\n",
|
||||
// pdu_size,((nb_bits_transmitted + 7) >> 3), rlc_pP->channel_id);
|
||||
if(pdu_size != ((nb_bits_transmitted + 7) >> 3)) {
|
||||
LOG_E(RLC, "RLC AM Tx Status PDU Data encoding size=%d different than expected=%d LcId=%d\n",
|
||||
pdu_size,((nb_bits_transmitted + 7) >> 3), rlc_pP->channel_id);
|
||||
pdu_size = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// remaining bytes to transmit for RLC (retrans pdus and new data pdus)
|
||||
rlc_pP->nb_bytes_requested_by_mac = rlc_pP->nb_bytes_requested_by_mac - pdu_size;
|
||||
@@ -869,7 +761,6 @@ rlc_am_send_status_pdu(
|
||||
list_add_head(tb_p, &rlc_pP->control_pdu_list);
|
||||
rlc_pP->stat_tx_control_pdu += 1;
|
||||
rlc_pP->stat_tx_control_bytes += pdu_size;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+321
-347
@@ -34,23 +34,23 @@
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "UTIL/OCG/OCG_vars.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
|
||||
#include "targets/COMMON/openairinterface5g_limits.h"
|
||||
#include "assertions.h"
|
||||
|
||||
extern boolean_t pdcp_data_ind(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const MBMS_flag_t MBMS_flagP,
|
||||
const rb_id_t rb_idP,
|
||||
const sdu_size_t sdu_buffer_sizeP,
|
||||
mem_block_t* const sdu_buffer_pP);
|
||||
mem_block_t *const sdu_buffer_pP);
|
||||
|
||||
#define DEBUG_RLC_PDCP_INTERFACE 1
|
||||
//#define TRACE_RLC_PAYLOAD 1
|
||||
#define DEBUG_RLC_DATA_REQ 1
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void rlc_util_print_hex_octets(comp_name_t componentP, unsigned char* dataP, const signed long sizeP)
|
||||
void rlc_util_print_hex_octets(comp_name_t componentP, unsigned char *dataP, const signed long sizeP)
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
unsigned long octet_index = 0;
|
||||
@@ -59,9 +59,6 @@ void rlc_util_print_hex_octets(comp_name_t componentP, unsigned char* dataP, con
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
LOG_T(componentP, "+-----+-------------------------------------------------+\n");
|
||||
LOG_T(componentP, "| | 0 1 2 3 4 5 6 7 8 9 a b c d e f |\n");
|
||||
LOG_T(componentP, "+-----+-------------------------------------------------+\n");
|
||||
@@ -98,38 +95,37 @@ void rlc_util_print_hex_octets(comp_name_t componentP, unsigned char* dataP, con
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
rlc_op_status_t rlc_stat_req (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const rb_id_t rb_idP,
|
||||
unsigned int* stat_rlc_mode,
|
||||
unsigned int* stat_tx_pdcp_sdu,
|
||||
unsigned int* stat_tx_pdcp_bytes,
|
||||
unsigned int* stat_tx_pdcp_sdu_discarded,
|
||||
unsigned int* stat_tx_pdcp_bytes_discarded,
|
||||
unsigned int* stat_tx_data_pdu,
|
||||
unsigned int* stat_tx_data_bytes,
|
||||
unsigned int* stat_tx_retransmit_pdu_by_status,
|
||||
unsigned int* stat_tx_retransmit_bytes_by_status,
|
||||
unsigned int* stat_tx_retransmit_pdu,
|
||||
unsigned int* stat_tx_retransmit_bytes,
|
||||
unsigned int* stat_tx_control_pdu,
|
||||
unsigned int* stat_tx_control_bytes,
|
||||
unsigned int* stat_rx_pdcp_sdu,
|
||||
unsigned int* stat_rx_pdcp_bytes,
|
||||
unsigned int* stat_rx_data_pdus_duplicate,
|
||||
unsigned int* stat_rx_data_bytes_duplicate,
|
||||
unsigned int* stat_rx_data_pdu,
|
||||
unsigned int* stat_rx_data_bytes,
|
||||
unsigned int* stat_rx_data_pdu_dropped,
|
||||
unsigned int* stat_rx_data_bytes_dropped,
|
||||
unsigned int* stat_rx_data_pdu_out_of_window,
|
||||
unsigned int* stat_rx_data_bytes_out_of_window,
|
||||
unsigned int* stat_rx_control_pdu,
|
||||
unsigned int* stat_rx_control_bytes,
|
||||
unsigned int* stat_timer_reordering_timed_out,
|
||||
unsigned int* stat_timer_poll_retransmit_timed_out,
|
||||
unsigned int* stat_timer_status_prohibit_timed_out)
|
||||
{
|
||||
unsigned int *stat_rlc_mode,
|
||||
unsigned int *stat_tx_pdcp_sdu,
|
||||
unsigned int *stat_tx_pdcp_bytes,
|
||||
unsigned int *stat_tx_pdcp_sdu_discarded,
|
||||
unsigned int *stat_tx_pdcp_bytes_discarded,
|
||||
unsigned int *stat_tx_data_pdu,
|
||||
unsigned int *stat_tx_data_bytes,
|
||||
unsigned int *stat_tx_retransmit_pdu_by_status,
|
||||
unsigned int *stat_tx_retransmit_bytes_by_status,
|
||||
unsigned int *stat_tx_retransmit_pdu,
|
||||
unsigned int *stat_tx_retransmit_bytes,
|
||||
unsigned int *stat_tx_control_pdu,
|
||||
unsigned int *stat_tx_control_bytes,
|
||||
unsigned int *stat_rx_pdcp_sdu,
|
||||
unsigned int *stat_rx_pdcp_bytes,
|
||||
unsigned int *stat_rx_data_pdus_duplicate,
|
||||
unsigned int *stat_rx_data_bytes_duplicate,
|
||||
unsigned int *stat_rx_data_pdu,
|
||||
unsigned int *stat_rx_data_bytes,
|
||||
unsigned int *stat_rx_data_pdu_dropped,
|
||||
unsigned int *stat_rx_data_bytes_dropped,
|
||||
unsigned int *stat_rx_data_pdu_out_of_window,
|
||||
unsigned int *stat_rx_data_bytes_out_of_window,
|
||||
unsigned int *stat_rx_control_pdu,
|
||||
unsigned int *stat_rx_control_bytes,
|
||||
unsigned int *stat_timer_reordering_timed_out,
|
||||
unsigned int *stat_timer_poll_retransmit_timed_out,
|
||||
unsigned int *stat_timer_status_prohibit_timed_out) {
|
||||
//-----------------------------------------------------------------------------
|
||||
rlc_mode_t rlc_mode = RLC_MODE_NONE;
|
||||
rlc_union_t *rlc_union_p = NULL;
|
||||
@@ -137,182 +133,183 @@ rlc_op_status_t rlc_stat_req (
|
||||
hashtable_rc_t h_rc;
|
||||
|
||||
//AssertFatal (rb_idP < NB_RB_MAX, "RB id is too high (%u/%d)!\n", rb_idP, NB_RB_MAX);
|
||||
if(rb_idP >= NB_RB_MAX){
|
||||
LOG_E(RLC, "RB id is too high (%u/%d)!\n", rb_idP, NB_RB_MAX);
|
||||
return RLC_OP_STATUS_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
if(rb_idP >= NB_RB_MAX) {
|
||||
LOG_E(RLC, "RB id is too high (%u/%d)!\n", rb_idP, NB_RB_MAX);
|
||||
return RLC_OP_STATUS_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
key = RLC_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
|
||||
h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);
|
||||
h_rc = hashtable_get(rlc_coll_p, key, (void **)&rlc_union_p);
|
||||
|
||||
if (h_rc == HASH_TABLE_OK) {
|
||||
rlc_mode = rlc_union_p->mode;
|
||||
}
|
||||
|
||||
*stat_rlc_mode = rlc_mode;
|
||||
|
||||
switch (rlc_mode) {
|
||||
case RLC_MODE_NONE:
|
||||
*stat_tx_pdcp_sdu = 0;
|
||||
*stat_tx_pdcp_bytes = 0;
|
||||
*stat_tx_pdcp_sdu_discarded = 0;
|
||||
*stat_tx_pdcp_bytes_discarded = 0;
|
||||
*stat_tx_data_pdu = 0;
|
||||
*stat_tx_data_bytes = 0;
|
||||
*stat_tx_retransmit_pdu_by_status = 0;
|
||||
*stat_tx_retransmit_bytes_by_status = 0;
|
||||
*stat_tx_retransmit_pdu = 0;
|
||||
*stat_tx_retransmit_bytes = 0;
|
||||
*stat_tx_control_pdu = 0;
|
||||
*stat_tx_control_bytes = 0;
|
||||
*stat_rx_pdcp_sdu = 0;
|
||||
*stat_rx_pdcp_bytes = 0;
|
||||
*stat_rx_data_pdus_duplicate = 0;
|
||||
*stat_rx_data_bytes_duplicate = 0;
|
||||
*stat_rx_data_pdu = 0;
|
||||
*stat_rx_data_bytes = 0;
|
||||
*stat_rx_data_pdu_dropped = 0;
|
||||
*stat_rx_data_bytes_dropped = 0;
|
||||
*stat_rx_data_pdu_out_of_window = 0;
|
||||
*stat_rx_data_bytes_out_of_window = 0;
|
||||
*stat_rx_control_pdu = 0;
|
||||
*stat_rx_control_bytes = 0;
|
||||
*stat_timer_reordering_timed_out = 0;
|
||||
*stat_timer_poll_retransmit_timed_out = 0;
|
||||
*stat_timer_status_prohibit_timed_out = 0;
|
||||
return RLC_OP_STATUS_BAD_PARAMETER;
|
||||
break;
|
||||
case RLC_MODE_NONE:
|
||||
*stat_tx_pdcp_sdu = 0;
|
||||
*stat_tx_pdcp_bytes = 0;
|
||||
*stat_tx_pdcp_sdu_discarded = 0;
|
||||
*stat_tx_pdcp_bytes_discarded = 0;
|
||||
*stat_tx_data_pdu = 0;
|
||||
*stat_tx_data_bytes = 0;
|
||||
*stat_tx_retransmit_pdu_by_status = 0;
|
||||
*stat_tx_retransmit_bytes_by_status = 0;
|
||||
*stat_tx_retransmit_pdu = 0;
|
||||
*stat_tx_retransmit_bytes = 0;
|
||||
*stat_tx_control_pdu = 0;
|
||||
*stat_tx_control_bytes = 0;
|
||||
*stat_rx_pdcp_sdu = 0;
|
||||
*stat_rx_pdcp_bytes = 0;
|
||||
*stat_rx_data_pdus_duplicate = 0;
|
||||
*stat_rx_data_bytes_duplicate = 0;
|
||||
*stat_rx_data_pdu = 0;
|
||||
*stat_rx_data_bytes = 0;
|
||||
*stat_rx_data_pdu_dropped = 0;
|
||||
*stat_rx_data_bytes_dropped = 0;
|
||||
*stat_rx_data_pdu_out_of_window = 0;
|
||||
*stat_rx_data_bytes_out_of_window = 0;
|
||||
*stat_rx_control_pdu = 0;
|
||||
*stat_rx_control_bytes = 0;
|
||||
*stat_timer_reordering_timed_out = 0;
|
||||
*stat_timer_poll_retransmit_timed_out = 0;
|
||||
*stat_timer_status_prohibit_timed_out = 0;
|
||||
return RLC_OP_STATUS_BAD_PARAMETER;
|
||||
break;
|
||||
|
||||
case RLC_MODE_AM:
|
||||
rlc_am_stat_req(ctxt_pP,
|
||||
&rlc_union_p->rlc.am,
|
||||
stat_tx_pdcp_sdu,
|
||||
stat_tx_pdcp_bytes,
|
||||
stat_tx_pdcp_sdu_discarded,
|
||||
stat_tx_pdcp_bytes_discarded,
|
||||
stat_tx_data_pdu,
|
||||
stat_tx_data_bytes,
|
||||
stat_tx_retransmit_pdu_by_status,
|
||||
stat_tx_retransmit_bytes_by_status,
|
||||
stat_tx_retransmit_pdu,
|
||||
stat_tx_retransmit_bytes,
|
||||
stat_tx_control_pdu,
|
||||
stat_tx_control_bytes,
|
||||
stat_rx_pdcp_sdu,
|
||||
stat_rx_pdcp_bytes,
|
||||
stat_rx_data_pdus_duplicate,
|
||||
stat_rx_data_bytes_duplicate,
|
||||
stat_rx_data_pdu,
|
||||
stat_rx_data_bytes,
|
||||
stat_rx_data_pdu_dropped,
|
||||
stat_rx_data_bytes_dropped,
|
||||
stat_rx_data_pdu_out_of_window,
|
||||
stat_rx_data_bytes_out_of_window,
|
||||
stat_rx_control_pdu,
|
||||
stat_rx_control_bytes,
|
||||
stat_timer_reordering_timed_out,
|
||||
stat_timer_poll_retransmit_timed_out,
|
||||
stat_timer_status_prohibit_timed_out);
|
||||
return RLC_OP_STATUS_OK;
|
||||
break;
|
||||
case RLC_MODE_AM:
|
||||
rlc_am_stat_req(ctxt_pP,
|
||||
&rlc_union_p->rlc.am,
|
||||
stat_tx_pdcp_sdu,
|
||||
stat_tx_pdcp_bytes,
|
||||
stat_tx_pdcp_sdu_discarded,
|
||||
stat_tx_pdcp_bytes_discarded,
|
||||
stat_tx_data_pdu,
|
||||
stat_tx_data_bytes,
|
||||
stat_tx_retransmit_pdu_by_status,
|
||||
stat_tx_retransmit_bytes_by_status,
|
||||
stat_tx_retransmit_pdu,
|
||||
stat_tx_retransmit_bytes,
|
||||
stat_tx_control_pdu,
|
||||
stat_tx_control_bytes,
|
||||
stat_rx_pdcp_sdu,
|
||||
stat_rx_pdcp_bytes,
|
||||
stat_rx_data_pdus_duplicate,
|
||||
stat_rx_data_bytes_duplicate,
|
||||
stat_rx_data_pdu,
|
||||
stat_rx_data_bytes,
|
||||
stat_rx_data_pdu_dropped,
|
||||
stat_rx_data_bytes_dropped,
|
||||
stat_rx_data_pdu_out_of_window,
|
||||
stat_rx_data_bytes_out_of_window,
|
||||
stat_rx_control_pdu,
|
||||
stat_rx_control_bytes,
|
||||
stat_timer_reordering_timed_out,
|
||||
stat_timer_poll_retransmit_timed_out,
|
||||
stat_timer_status_prohibit_timed_out);
|
||||
return RLC_OP_STATUS_OK;
|
||||
break;
|
||||
|
||||
case RLC_MODE_UM:
|
||||
*stat_tx_retransmit_pdu_by_status = 0;
|
||||
*stat_tx_retransmit_bytes_by_status = 0;
|
||||
*stat_tx_retransmit_pdu = 0;
|
||||
*stat_tx_retransmit_bytes = 0;
|
||||
*stat_tx_control_pdu = 0;
|
||||
*stat_tx_control_bytes = 0;
|
||||
*stat_rx_data_pdu_dropped = 0;
|
||||
*stat_rx_data_bytes_dropped = 0;
|
||||
*stat_rx_data_pdu_out_of_window = 0;
|
||||
*stat_rx_data_bytes_out_of_window = 0;
|
||||
*stat_timer_poll_retransmit_timed_out = 0;
|
||||
*stat_timer_status_prohibit_timed_out = 0;
|
||||
rlc_um_stat_req (&rlc_union_p->rlc.um,
|
||||
stat_tx_pdcp_sdu,
|
||||
stat_tx_pdcp_bytes,
|
||||
stat_tx_pdcp_sdu_discarded,
|
||||
stat_tx_pdcp_bytes_discarded,
|
||||
stat_tx_data_pdu,
|
||||
stat_tx_data_bytes,
|
||||
stat_rx_pdcp_sdu,
|
||||
stat_rx_pdcp_bytes,
|
||||
stat_rx_data_pdus_duplicate,
|
||||
stat_rx_data_bytes_duplicate,
|
||||
stat_rx_data_pdu,
|
||||
stat_rx_data_bytes,
|
||||
stat_rx_data_pdu_dropped,
|
||||
stat_rx_data_bytes_dropped,
|
||||
stat_rx_data_pdu_out_of_window,
|
||||
stat_rx_data_bytes_out_of_window,
|
||||
stat_timer_reordering_timed_out);
|
||||
return RLC_OP_STATUS_OK;
|
||||
break;
|
||||
case RLC_MODE_UM:
|
||||
*stat_tx_retransmit_pdu_by_status = 0;
|
||||
*stat_tx_retransmit_bytes_by_status = 0;
|
||||
*stat_tx_retransmit_pdu = 0;
|
||||
*stat_tx_retransmit_bytes = 0;
|
||||
*stat_tx_control_pdu = 0;
|
||||
*stat_tx_control_bytes = 0;
|
||||
*stat_rx_data_pdu_dropped = 0;
|
||||
*stat_rx_data_bytes_dropped = 0;
|
||||
*stat_rx_data_pdu_out_of_window = 0;
|
||||
*stat_rx_data_bytes_out_of_window = 0;
|
||||
*stat_timer_poll_retransmit_timed_out = 0;
|
||||
*stat_timer_status_prohibit_timed_out = 0;
|
||||
rlc_um_stat_req (&rlc_union_p->rlc.um,
|
||||
stat_tx_pdcp_sdu,
|
||||
stat_tx_pdcp_bytes,
|
||||
stat_tx_pdcp_sdu_discarded,
|
||||
stat_tx_pdcp_bytes_discarded,
|
||||
stat_tx_data_pdu,
|
||||
stat_tx_data_bytes,
|
||||
stat_rx_pdcp_sdu,
|
||||
stat_rx_pdcp_bytes,
|
||||
stat_rx_data_pdus_duplicate,
|
||||
stat_rx_data_bytes_duplicate,
|
||||
stat_rx_data_pdu,
|
||||
stat_rx_data_bytes,
|
||||
stat_rx_data_pdu_dropped,
|
||||
stat_rx_data_bytes_dropped,
|
||||
stat_rx_data_pdu_out_of_window,
|
||||
stat_rx_data_bytes_out_of_window,
|
||||
stat_timer_reordering_timed_out);
|
||||
return RLC_OP_STATUS_OK;
|
||||
break;
|
||||
|
||||
case RLC_MODE_TM:
|
||||
*stat_tx_pdcp_sdu = 0;
|
||||
*stat_tx_pdcp_bytes = 0;
|
||||
*stat_tx_pdcp_sdu_discarded = 0;
|
||||
*stat_tx_pdcp_bytes_discarded = 0;
|
||||
*stat_tx_data_pdu = 0;
|
||||
*stat_tx_data_bytes = 0;
|
||||
*stat_tx_retransmit_pdu_by_status = 0;
|
||||
*stat_tx_retransmit_bytes_by_status = 0;
|
||||
*stat_tx_retransmit_pdu = 0;
|
||||
*stat_tx_retransmit_bytes = 0;
|
||||
*stat_tx_control_pdu = 0;
|
||||
*stat_tx_control_bytes = 0;
|
||||
*stat_rx_pdcp_sdu = 0;
|
||||
*stat_rx_pdcp_bytes = 0;
|
||||
*stat_rx_data_pdus_duplicate = 0;
|
||||
*stat_rx_data_bytes_duplicate = 0;
|
||||
*stat_rx_data_pdu = 0;
|
||||
*stat_rx_data_bytes = 0;
|
||||
*stat_rx_data_pdu_dropped = 0;
|
||||
*stat_rx_data_bytes_dropped = 0;
|
||||
*stat_rx_data_pdu_out_of_window = 0;
|
||||
*stat_rx_data_bytes_out_of_window = 0;
|
||||
*stat_rx_control_pdu = 0;
|
||||
*stat_rx_control_bytes = 0;
|
||||
*stat_timer_reordering_timed_out = 0;
|
||||
*stat_timer_poll_retransmit_timed_out = 0;
|
||||
*stat_timer_status_prohibit_timed_out = 0;
|
||||
return RLC_OP_STATUS_BAD_PARAMETER;
|
||||
break;
|
||||
case RLC_MODE_TM:
|
||||
*stat_tx_pdcp_sdu = 0;
|
||||
*stat_tx_pdcp_bytes = 0;
|
||||
*stat_tx_pdcp_sdu_discarded = 0;
|
||||
*stat_tx_pdcp_bytes_discarded = 0;
|
||||
*stat_tx_data_pdu = 0;
|
||||
*stat_tx_data_bytes = 0;
|
||||
*stat_tx_retransmit_pdu_by_status = 0;
|
||||
*stat_tx_retransmit_bytes_by_status = 0;
|
||||
*stat_tx_retransmit_pdu = 0;
|
||||
*stat_tx_retransmit_bytes = 0;
|
||||
*stat_tx_control_pdu = 0;
|
||||
*stat_tx_control_bytes = 0;
|
||||
*stat_rx_pdcp_sdu = 0;
|
||||
*stat_rx_pdcp_bytes = 0;
|
||||
*stat_rx_data_pdus_duplicate = 0;
|
||||
*stat_rx_data_bytes_duplicate = 0;
|
||||
*stat_rx_data_pdu = 0;
|
||||
*stat_rx_data_bytes = 0;
|
||||
*stat_rx_data_pdu_dropped = 0;
|
||||
*stat_rx_data_bytes_dropped = 0;
|
||||
*stat_rx_data_pdu_out_of_window = 0;
|
||||
*stat_rx_data_bytes_out_of_window = 0;
|
||||
*stat_rx_control_pdu = 0;
|
||||
*stat_rx_control_bytes = 0;
|
||||
*stat_timer_reordering_timed_out = 0;
|
||||
*stat_timer_poll_retransmit_timed_out = 0;
|
||||
*stat_timer_status_prohibit_timed_out = 0;
|
||||
return RLC_OP_STATUS_BAD_PARAMETER;
|
||||
break;
|
||||
|
||||
default:
|
||||
*stat_tx_pdcp_sdu = 0;
|
||||
*stat_tx_pdcp_bytes = 0;
|
||||
*stat_tx_pdcp_sdu_discarded = 0;
|
||||
*stat_tx_pdcp_bytes_discarded = 0;
|
||||
*stat_tx_data_pdu = 0;
|
||||
*stat_tx_data_bytes = 0;
|
||||
*stat_tx_retransmit_pdu_by_status = 0;
|
||||
*stat_tx_retransmit_bytes_by_status = 0;
|
||||
*stat_tx_retransmit_pdu = 0;
|
||||
*stat_tx_retransmit_bytes = 0;
|
||||
*stat_tx_control_pdu = 0;
|
||||
*stat_tx_control_bytes = 0;
|
||||
*stat_rx_pdcp_sdu = 0;
|
||||
*stat_rx_pdcp_bytes = 0;
|
||||
*stat_rx_data_pdus_duplicate = 0;
|
||||
*stat_rx_data_bytes_duplicate = 0;
|
||||
*stat_rx_data_pdu = 0;
|
||||
*stat_rx_data_bytes = 0;
|
||||
*stat_rx_data_pdu_dropped = 0;
|
||||
*stat_rx_data_bytes_dropped = 0;
|
||||
*stat_rx_data_pdu_out_of_window = 0;
|
||||
*stat_rx_data_bytes_out_of_window = 0;
|
||||
*stat_rx_control_pdu = 0;
|
||||
*stat_rx_control_bytes = 0;
|
||||
|
||||
*stat_timer_poll_retransmit_timed_out = 0;
|
||||
*stat_timer_status_prohibit_timed_out = 0;
|
||||
return RLC_OP_STATUS_BAD_PARAMETER;
|
||||
default:
|
||||
*stat_tx_pdcp_sdu = 0;
|
||||
*stat_tx_pdcp_bytes = 0;
|
||||
*stat_tx_pdcp_sdu_discarded = 0;
|
||||
*stat_tx_pdcp_bytes_discarded = 0;
|
||||
*stat_tx_data_pdu = 0;
|
||||
*stat_tx_data_bytes = 0;
|
||||
*stat_tx_retransmit_pdu_by_status = 0;
|
||||
*stat_tx_retransmit_bytes_by_status = 0;
|
||||
*stat_tx_retransmit_pdu = 0;
|
||||
*stat_tx_retransmit_bytes = 0;
|
||||
*stat_tx_control_pdu = 0;
|
||||
*stat_tx_control_bytes = 0;
|
||||
*stat_rx_pdcp_sdu = 0;
|
||||
*stat_rx_pdcp_bytes = 0;
|
||||
*stat_rx_data_pdus_duplicate = 0;
|
||||
*stat_rx_data_bytes_duplicate = 0;
|
||||
*stat_rx_data_pdu = 0;
|
||||
*stat_rx_data_bytes = 0;
|
||||
*stat_rx_data_pdu_dropped = 0;
|
||||
*stat_rx_data_bytes_dropped = 0;
|
||||
*stat_rx_data_pdu_out_of_window = 0;
|
||||
*stat_rx_data_bytes_out_of_window = 0;
|
||||
*stat_rx_control_pdu = 0;
|
||||
*stat_rx_control_bytes = 0;
|
||||
*stat_timer_poll_retransmit_timed_out = 0;
|
||||
*stat_timer_status_prohibit_timed_out = 0;
|
||||
return RLC_OP_STATUS_BAD_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
rlc_op_status_t rlc_data_req (const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_op_status_t rlc_data_req (const protocol_ctxt_t *const ctxt_pP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const MBMS_flag_t MBMS_flagP,
|
||||
const rb_id_t rb_idP,
|
||||
@@ -321,18 +318,16 @@ rlc_op_status_t rlc_data_req (const protocol_ctxt_t* const ctxt_pP,
|
||||
sdu_size_t sdu_sizeP,
|
||||
mem_block_t *sdu_pP
|
||||
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
|
||||
,const uint32_t * const sourceL2Id
|
||||
,const uint32_t * const destinationL2Id
|
||||
,const uint32_t *const sourceL2Id
|
||||
,const uint32_t *const destinationL2Id
|
||||
#endif
|
||||
)
|
||||
{
|
||||
) {
|
||||
//-----------------------------------------------------------------------------
|
||||
mem_block_t *new_sdu_p = NULL;
|
||||
rlc_mode_t rlc_mode = RLC_MODE_NONE;
|
||||
rlc_union_t *rlc_union_p = NULL;
|
||||
hash_key_t key = HASHTABLE_NOT_A_KEY_VALUE;
|
||||
hashtable_rc_t h_rc;
|
||||
|
||||
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
|
||||
rlc_mbms_id_t *mbms_id_p = NULL;
|
||||
logical_chan_id_t log_ch_id = 0;
|
||||
@@ -351,32 +346,33 @@ rlc_op_status_t rlc_data_req (const protocol_ctxt_t* const ctxt_pP,
|
||||
#else
|
||||
AssertFatal(MBMS_flagP == 0, "MBMS_flagP %u", MBMS_flagP);
|
||||
#endif
|
||||
|
||||
#if T_TRACER
|
||||
|
||||
if (ctxt_pP->enb_flag)
|
||||
T(T_ENB_RLC_DL, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->rnti), T_INT(rb_idP), T_INT(sdu_sizeP));
|
||||
|
||||
#endif
|
||||
|
||||
if (MBMS_flagP) {
|
||||
//AssertFatal (rb_idP < NB_RB_MBMS_MAX, "RB id is too high (%u/%d)!\n", rb_idP, NB_RB_MBMS_MAX);
|
||||
if(rb_idP >= NB_RB_MBMS_MAX){
|
||||
LOG_E(RLC, "RB id is too high (%u/%d)!\n", rb_idP, NB_RB_MBMS_MAX);
|
||||
return RLC_OP_STATUS_BAD_PARAMETER;
|
||||
}
|
||||
if(rb_idP >= NB_RB_MBMS_MAX) {
|
||||
LOG_E(RLC, "RB id is too high (%u/%d)!\n", rb_idP, NB_RB_MBMS_MAX);
|
||||
return RLC_OP_STATUS_BAD_PARAMETER;
|
||||
}
|
||||
} else {
|
||||
//AssertFatal (rb_idP < NB_RB_MAX, "RB id is too high (%u/%d)!\n", rb_idP, NB_RB_MAX);
|
||||
if(rb_idP >= NB_RB_MAX){
|
||||
LOG_E(RLC, "RB id is too high (%u/%d)!\n", rb_idP, NB_RB_MAX);
|
||||
return RLC_OP_STATUS_BAD_PARAMETER;
|
||||
}
|
||||
if(rb_idP >= NB_RB_MAX) {
|
||||
LOG_E(RLC, "RB id is too high (%u/%d)!\n", rb_idP, NB_RB_MAX);
|
||||
return RLC_OP_STATUS_BAD_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
//DevAssert(sdu_pP != NULL);
|
||||
if(sdu_pP == NULL){
|
||||
LOG_E(RLC, "sdu_pP == NULL\n");
|
||||
return RLC_OP_STATUS_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
if(sdu_pP == NULL) {
|
||||
LOG_E(RLC, "sdu_pP == NULL\n");
|
||||
return RLC_OP_STATUS_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
//DevCheck(sdu_sizeP > 0, sdu_sizeP, 0, 0);
|
||||
if(sdu_sizeP <= 0) {
|
||||
LOG_E(RLC, "sdu_sizeP %d, file %s, line %d\n", sdu_sizeP, __FILE__ ,__LINE__);
|
||||
@@ -386,9 +382,7 @@ rlc_op_status_t rlc_data_req (const protocol_ctxt_t* const ctxt_pP,
|
||||
#if (LTE_RRC_VERSION < MAKE_VERSION(10, 0, 0))
|
||||
DevCheck(MBMS_flagP == 0, MBMS_flagP, 0, 0);
|
||||
#endif
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RLC_DATA_REQ,VCD_FUNCTION_IN);
|
||||
|
||||
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
|
||||
|
||||
if (MBMS_flagP == TRUE) {
|
||||
@@ -402,31 +396,31 @@ rlc_op_status_t rlc_data_req (const protocol_ctxt_t* const ctxt_pP,
|
||||
|
||||
key = RLC_COLL_KEY_MBMS_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, mbms_id_p->service_id, mbms_id_p->session_id);
|
||||
}
|
||||
if (sourceL2Id && destinationL2Id){
|
||||
LOG_I (RLC, "RLC_COLL_KEY_VALUE: ctxt_pP->module_id: %d, ctxt_pP->rnti: %d, ctxt_pP->enb_flag: %d, rb_idP:%d, srb_flagP: %d \n \n", ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
|
||||
key = RLC_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
|
||||
|
||||
//Thinh's line originally uncommented
|
||||
//key = RLC_COLL_KEY_SOURCE_DEST_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, *sourceL2Id, *destinationL2Id, srb_flagP);
|
||||
|
||||
|
||||
//key_lcid = RLC_COLL_KEY_LCID_SOURCE_DEST_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, chan_idP, *sourceL2Id, *destinationL2Id, srb_flagP);
|
||||
if (sourceL2Id && destinationL2Id) {
|
||||
LOG_D (RLC, "RLC_COLL_KEY_VALUE: ctxt_pP->module_id: %d, ctxt_pP->rnti: %d, ctxt_pP->enb_flag: %d, rb_idP:%d, srb_flagP: %d \n \n", ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP,
|
||||
srb_flagP);
|
||||
key = RLC_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
|
||||
//Thinh's line originally uncommented
|
||||
//key = RLC_COLL_KEY_SOURCE_DEST_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, *sourceL2Id, *destinationL2Id, srb_flagP);
|
||||
//key_lcid = RLC_COLL_KEY_LCID_SOURCE_DEST_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, chan_idP, *sourceL2Id, *destinationL2Id, srb_flagP);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
LOG_I (RLC, "RLC_COLL_KEY_VALUE: ctxt_pP->module_id: %d, ctxt_pP->rnti: %d, ctxt_pP->enb_flag: %d, rb_idP:%d, srb_flagP: %d \n \n", ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
|
||||
LOG_D (RLC, "RLC_COLL_KEY_VALUE: ctxt_pP->module_id: %d, ctxt_pP->rnti: %d, ctxt_pP->enb_flag: %d, rb_idP:%d, srb_flagP: %d \n \n", ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP,
|
||||
srb_flagP);
|
||||
key = RLC_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
|
||||
}
|
||||
|
||||
h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);
|
||||
h_rc = hashtable_get(rlc_coll_p, key, (void **)&rlc_union_p);
|
||||
|
||||
if (h_rc == HASH_TABLE_OK) {
|
||||
rlc_mode = rlc_union_p->mode;
|
||||
} else {
|
||||
rlc_mode = RLC_MODE_NONE;
|
||||
//AssertFatal (0 , "RLC not configured key %ju\n", key);
|
||||
LOG_E(RLC, "not configured key %lu\n", key);
|
||||
return RLC_OP_STATUS_OUT_OF_RESSOURCES;
|
||||
LOG_E(RLC, "not configured key %lu\n", key);
|
||||
return RLC_OP_STATUS_OUT_OF_RESSOURCES;
|
||||
}
|
||||
|
||||
if (MBMS_flagP == 0) {
|
||||
@@ -434,111 +428,105 @@ rlc_op_status_t rlc_data_req (const protocol_ctxt_t* const ctxt_pP,
|
||||
PROTOCOL_CTXT_ARGS(ctxt_pP),
|
||||
rb_idP);
|
||||
#if defined(TRACE_RLC_PAYLOAD)
|
||||
rlc_util_print_hex_octets(RLC, (unsigned char*)sdu_pP->data, sdu_sizeP);
|
||||
rlc_util_print_hex_octets(RLC, (unsigned char *)sdu_pP->data, sdu_sizeP);
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_RLC_DATA_REQ
|
||||
LOG_D(RLC,"RLC_TYPE : %d\n", rlc_mode);
|
||||
#endif
|
||||
|
||||
switch (rlc_mode) {
|
||||
case RLC_MODE_NONE:
|
||||
free_mem_block(sdu_pP, __func__);
|
||||
LOG_E(RLC, PROTOCOL_CTXT_FMT" Received RLC_MODE_NONE as rlc_type for rb_id %u\n",
|
||||
PROTOCOL_CTXT_ARGS(ctxt_pP),
|
||||
rb_idP);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RLC_DATA_REQ,VCD_FUNCTION_OUT);
|
||||
return RLC_OP_STATUS_BAD_PARAMETER;
|
||||
case RLC_MODE_NONE:
|
||||
free_mem_block(sdu_pP, __func__);
|
||||
LOG_E(RLC, PROTOCOL_CTXT_FMT" Received RLC_MODE_NONE as rlc_type for rb_id %u\n",
|
||||
PROTOCOL_CTXT_ARGS(ctxt_pP),
|
||||
rb_idP);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RLC_DATA_REQ,VCD_FUNCTION_OUT);
|
||||
return RLC_OP_STATUS_BAD_PARAMETER;
|
||||
|
||||
case RLC_MODE_AM:
|
||||
case RLC_MODE_AM:
|
||||
#ifdef DEBUG_RLC_DATA_REQ
|
||||
LOG_D(RLC,"RLC_MODE_AM\n");
|
||||
LOG_D(RLC,"RLC_MODE_AM\n");
|
||||
#endif
|
||||
new_sdu_p = get_free_mem_block (sdu_sizeP + sizeof (struct rlc_am_data_req_alloc), __func__);
|
||||
new_sdu_p = get_free_mem_block (sdu_sizeP + sizeof (struct rlc_am_data_req_alloc), __func__);
|
||||
|
||||
if (new_sdu_p != NULL) {
|
||||
// PROCESS OF COMPRESSION HERE:
|
||||
memset (new_sdu_p->data, 0, sizeof (struct rlc_am_data_req_alloc));
|
||||
memcpy (&new_sdu_p->data[sizeof (struct rlc_am_data_req_alloc)], &sdu_pP->data[0], sdu_sizeP);
|
||||
if (new_sdu_p != NULL) {
|
||||
// PROCESS OF COMPRESSION HERE:
|
||||
memset (new_sdu_p->data, 0, sizeof (struct rlc_am_data_req_alloc));
|
||||
memcpy (&new_sdu_p->data[sizeof (struct rlc_am_data_req_alloc)], &sdu_pP->data[0], sdu_sizeP);
|
||||
((struct rlc_am_data_req *) (new_sdu_p->data))->data_size = sdu_sizeP;
|
||||
((struct rlc_am_data_req *) (new_sdu_p->data))->conf = confirmP;
|
||||
((struct rlc_am_data_req *) (new_sdu_p->data))->mui = muiP;
|
||||
((struct rlc_am_data_req *) (new_sdu_p->data))->data_offset = sizeof (struct rlc_am_data_req_alloc);
|
||||
free_mem_block(sdu_pP, __func__);
|
||||
rlc_am_data_req(ctxt_pP, &rlc_union_p->rlc.am, new_sdu_p);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RLC_DATA_REQ,VCD_FUNCTION_OUT);
|
||||
return RLC_OP_STATUS_OK;
|
||||
} else {
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RLC_DATA_REQ,VCD_FUNCTION_OUT);
|
||||
free_mem_block(sdu_pP, __func__);
|
||||
return RLC_OP_STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
((struct rlc_am_data_req *) (new_sdu_p->data))->data_size = sdu_sizeP;
|
||||
((struct rlc_am_data_req *) (new_sdu_p->data))->conf = confirmP;
|
||||
((struct rlc_am_data_req *) (new_sdu_p->data))->mui = muiP;
|
||||
((struct rlc_am_data_req *) (new_sdu_p->data))->data_offset = sizeof (struct rlc_am_data_req_alloc);
|
||||
break;
|
||||
|
||||
case RLC_MODE_UM:
|
||||
|
||||
/* TODO: this is a hack, needs better solution. Let's not use too
|
||||
* much memory and store at maximum 5 millions bytes.
|
||||
*/
|
||||
/* look for HACK_RLC_UM_LIMIT for others places related to the hack. Please do not remove this comment. */
|
||||
if (rlc_um_get_buffer_occupancy(&rlc_union_p->rlc.um) > 5000000) {
|
||||
free_mem_block(sdu_pP, __func__);
|
||||
return RLC_OP_STATUS_OUT_OF_RESSOURCES;
|
||||
}
|
||||
|
||||
new_sdu_p = get_free_mem_block (sdu_sizeP + sizeof (struct rlc_um_data_req_alloc), __func__);
|
||||
|
||||
if (new_sdu_p != NULL) {
|
||||
// PROCESS OF COMPRESSION HERE:
|
||||
memset (new_sdu_p->data, 0, sizeof (struct rlc_um_data_req_alloc));
|
||||
memcpy (&new_sdu_p->data[sizeof (struct rlc_um_data_req_alloc)], &sdu_pP->data[0], sdu_sizeP);
|
||||
((struct rlc_um_data_req *) (new_sdu_p->data))->data_size = sdu_sizeP;
|
||||
((struct rlc_um_data_req *) (new_sdu_p->data))->data_offset = sizeof (struct rlc_um_data_req_alloc);
|
||||
free_mem_block(sdu_pP, __func__);
|
||||
rlc_um_data_req(ctxt_pP, &rlc_union_p->rlc.um, new_sdu_p);
|
||||
//free_mem_block(new_sdu, __func__);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RLC_DATA_REQ,VCD_FUNCTION_OUT);
|
||||
return RLC_OP_STATUS_OK;
|
||||
} else {
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RLC_DATA_REQ,VCD_FUNCTION_OUT);
|
||||
free_mem_block(sdu_pP, __func__);
|
||||
return RLC_OP_STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case RLC_MODE_TM:
|
||||
new_sdu_p = get_free_mem_block (sdu_sizeP + sizeof (struct rlc_tm_data_req_alloc), __func__);
|
||||
|
||||
if (new_sdu_p != NULL) {
|
||||
// PROCESS OF COMPRESSION HERE:
|
||||
memset (new_sdu_p->data, 0, sizeof (struct rlc_tm_data_req_alloc));
|
||||
memcpy (&new_sdu_p->data[sizeof (struct rlc_tm_data_req_alloc)], &sdu_pP->data[0], sdu_sizeP);
|
||||
((struct rlc_tm_data_req *) (new_sdu_p->data))->data_size = sdu_sizeP;
|
||||
((struct rlc_tm_data_req *) (new_sdu_p->data))->data_offset = sizeof (struct rlc_tm_data_req_alloc);
|
||||
free_mem_block(sdu_pP, __func__);
|
||||
rlc_tm_data_req(ctxt_pP, &rlc_union_p->rlc.tm, new_sdu_p);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RLC_DATA_REQ,VCD_FUNCTION_OUT);
|
||||
return RLC_OP_STATUS_OK;
|
||||
} else {
|
||||
//handle_event(ERROR,"FILE %s FONCTION rlc_data_req() LINE %s : out of memory\n", __FILE__, __LINE__);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RLC_DATA_REQ,VCD_FUNCTION_OUT);
|
||||
free_mem_block(sdu_pP, __func__);
|
||||
return RLC_OP_STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
free_mem_block(sdu_pP, __func__);
|
||||
rlc_am_data_req(ctxt_pP, &rlc_union_p->rlc.am, new_sdu_p);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RLC_DATA_REQ,VCD_FUNCTION_OUT);
|
||||
return RLC_OP_STATUS_OK;
|
||||
} else {
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RLC_DATA_REQ,VCD_FUNCTION_OUT);
|
||||
free_mem_block(sdu_pP, __func__);
|
||||
return RLC_OP_STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case RLC_MODE_UM:
|
||||
/* TODO: this is a hack, needs better solution. Let's not use too
|
||||
* much memory and store at maximum 5 millions bytes.
|
||||
*/
|
||||
/* look for HACK_RLC_UM_LIMIT for others places related to the hack. Please do not remove this comment. */
|
||||
if (rlc_um_get_buffer_occupancy(&rlc_union_p->rlc.um) > 5000000) {
|
||||
free_mem_block(sdu_pP, __func__);
|
||||
return RLC_OP_STATUS_OUT_OF_RESSOURCES;
|
||||
}
|
||||
|
||||
new_sdu_p = get_free_mem_block (sdu_sizeP + sizeof (struct rlc_um_data_req_alloc), __func__);
|
||||
|
||||
if (new_sdu_p != NULL) {
|
||||
// PROCESS OF COMPRESSION HERE:
|
||||
memset (new_sdu_p->data, 0, sizeof (struct rlc_um_data_req_alloc));
|
||||
memcpy (&new_sdu_p->data[sizeof (struct rlc_um_data_req_alloc)], &sdu_pP->data[0], sdu_sizeP);
|
||||
|
||||
((struct rlc_um_data_req *) (new_sdu_p->data))->data_size = sdu_sizeP;
|
||||
((struct rlc_um_data_req *) (new_sdu_p->data))->data_offset = sizeof (struct rlc_um_data_req_alloc);
|
||||
free_mem_block(sdu_pP, __func__);
|
||||
|
||||
rlc_um_data_req(ctxt_pP, &rlc_union_p->rlc.um, new_sdu_p);
|
||||
|
||||
//free_mem_block(new_sdu, __func__);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RLC_DATA_REQ,VCD_FUNCTION_OUT);
|
||||
return RLC_OP_STATUS_OK;
|
||||
} else {
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RLC_DATA_REQ,VCD_FUNCTION_OUT);
|
||||
free_mem_block(sdu_pP, __func__);
|
||||
return RLC_OP_STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case RLC_MODE_TM:
|
||||
new_sdu_p = get_free_mem_block (sdu_sizeP + sizeof (struct rlc_tm_data_req_alloc), __func__);
|
||||
|
||||
if (new_sdu_p != NULL) {
|
||||
// PROCESS OF COMPRESSION HERE:
|
||||
memset (new_sdu_p->data, 0, sizeof (struct rlc_tm_data_req_alloc));
|
||||
memcpy (&new_sdu_p->data[sizeof (struct rlc_tm_data_req_alloc)], &sdu_pP->data[0], sdu_sizeP);
|
||||
|
||||
((struct rlc_tm_data_req *) (new_sdu_p->data))->data_size = sdu_sizeP;
|
||||
((struct rlc_tm_data_req *) (new_sdu_p->data))->data_offset = sizeof (struct rlc_tm_data_req_alloc);
|
||||
free_mem_block(sdu_pP, __func__);
|
||||
rlc_tm_data_req(ctxt_pP, &rlc_union_p->rlc.tm, new_sdu_p);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RLC_DATA_REQ,VCD_FUNCTION_OUT);
|
||||
return RLC_OP_STATUS_OK;
|
||||
} else {
|
||||
//handle_event(ERROR,"FILE %s FONCTION rlc_data_req() LINE %s : out of memory\n", __FILE__, __LINE__);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RLC_DATA_REQ,VCD_FUNCTION_OUT);
|
||||
free_mem_block(sdu_pP, __func__);
|
||||
return RLC_OP_STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
free_mem_block(sdu_pP, __func__);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RLC_DATA_REQ,VCD_FUNCTION_OUT);
|
||||
return RLC_OP_STATUS_INTERNAL_ERROR;
|
||||
|
||||
}
|
||||
|
||||
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
|
||||
@@ -557,7 +545,6 @@ rlc_op_status_t rlc_data_req (const protocol_ctxt_t* const ctxt_pP,
|
||||
((struct rlc_um_data_req *) (new_sdu_p->data))->data_offset = sizeof (struct rlc_um_data_req_alloc);
|
||||
free_mem_block(sdu_pP, __func__);
|
||||
rlc_um_data_req(ctxt_pP, &rlc_union_p->rlc.um, new_sdu_p);
|
||||
|
||||
//free_mem_block(new_sdu, __func__);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RLC_DATA_REQ,VCD_FUNCTION_OUT);
|
||||
return RLC_OP_STATUS_OK;
|
||||
@@ -578,8 +565,7 @@ rlc_op_status_t rlc_data_req (const protocol_ctxt_t* const ctxt_pP,
|
||||
|
||||
#else
|
||||
}
|
||||
else /* MBMS_flag != 0 */
|
||||
{
|
||||
else { /* MBMS_flag != 0 */
|
||||
free_mem_block(sdu_pP, __func__);
|
||||
LOG_E(RLC, "MBMS_flag != 0 while Rel10/Rel14 is not defined...\n");
|
||||
//handle_event(ERROR,"FILE %s FONCTION rlc_data_req() LINE %s : parameter module_id out of bounds :%d\n", __FILE__, __LINE__, module_idP);
|
||||
@@ -592,32 +578,27 @@ rlc_op_status_t rlc_data_req (const protocol_ctxt_t* const ctxt_pP,
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void rlc_data_ind (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const MBMS_flag_t MBMS_flagP,
|
||||
const rb_id_t rb_idP,
|
||||
const sdu_size_t sdu_sizeP,
|
||||
mem_block_t *sdu_pP)
|
||||
{
|
||||
mem_block_t *sdu_pP) {
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#if defined(TRACE_RLC_PAYLOAD)
|
||||
LOG_D(RLC, PROTOCOL_CTXT_FMT"[%s %u] Display of rlc_data_ind: size %u\n",
|
||||
PROTOCOL_CTXT_ARGS(ctxt_pP),
|
||||
(srb_flagP) ? "SRB" : "DRB",
|
||||
rb_idP,
|
||||
sdu_sizeP);
|
||||
|
||||
rlc_util_print_hex_octets(RLC, (unsigned char*)sdu_pP->data, sdu_sizeP);
|
||||
rlc_util_print_hex_octets(RLC, (unsigned char *)sdu_pP->data, sdu_sizeP);
|
||||
#endif
|
||||
|
||||
#if T_TRACER
|
||||
|
||||
if (ctxt_pP->enb_flag)
|
||||
T(T_ENB_RLC_UL, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->rnti), T_INT(rb_idP), T_INT(sdu_sizeP));
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
pdcp_data_ind (
|
||||
ctxt_pP,
|
||||
srb_flagP,
|
||||
@@ -627,14 +608,12 @@ void rlc_data_ind (
|
||||
sdu_pP);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void rlc_data_conf (const protocol_ctxt_t* const ctxt_pP,
|
||||
void rlc_data_conf (const protocol_ctxt_t *const ctxt_pP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const rb_id_t rb_idP,
|
||||
const mui_t muiP,
|
||||
const rlc_tx_status_t statusP)
|
||||
{
|
||||
const rlc_tx_status_t statusP) {
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
if (srb_flagP) {
|
||||
if (rlc_rrc_data_conf != NULL) {
|
||||
rlc_rrc_data_conf (ctxt_pP, rb_idP , muiP, statusP);
|
||||
@@ -643,20 +622,17 @@ void rlc_data_conf (const protocol_ctxt_t* const ctxt_pP,
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
int
|
||||
rlc_module_init (void)
|
||||
{
|
||||
rlc_module_init (void) {
|
||||
//-----------------------------------------------------------------------------
|
||||
int k;
|
||||
module_id_t module_id1;
|
||||
|
||||
/* for no gcc warnings */
|
||||
(void)k;
|
||||
|
||||
LOG_D(RLC, "MODULE INIT\n");
|
||||
rlc_rrc_data_ind = NULL;
|
||||
rlc_rrc_data_conf = NULL;
|
||||
rlc_coll_p = hashtable_create ((LTE_maxDRB + 2) * NUMBER_OF_UE_MAX, NULL, rb_free_rlc_union);
|
||||
|
||||
rlc_coll_p = hashtable_create ((LTE_maxDRB + 2) * 16, NULL, rb_free_rlc_union);
|
||||
//AssertFatal(rlc_coll_p != NULL, "UNRECOVERABLE error, RLC hashtable_create failed");
|
||||
if(rlc_coll_p == NULL) {
|
||||
LOG_E(RLC, "UNRECOVERABLE error, RLC hashtable_create failed\n");
|
||||
@@ -694,7 +670,6 @@ rlc_module_init (void)
|
||||
}
|
||||
|
||||
pool_buffer_init();
|
||||
|
||||
return(0);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -706,8 +681,7 @@ rlc_module_cleanup (void)
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_layer_init (void)
|
||||
{
|
||||
rlc_layer_init (void) {
|
||||
//-----------------------------------------------------------------------------
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -64,6 +64,8 @@
|
||||
#include "rrc_nas_primitives.h"
|
||||
#include "COMMON/platform_types.h"
|
||||
|
||||
#define MAKE_VERSION(a,b,c) ((a)*256+(b)*16+(c))
|
||||
|
||||
struct rb_entity {
|
||||
nasRadioBearerId_t rab_id;
|
||||
nasSapId_t sapi;
|
||||
@@ -160,6 +162,10 @@ typedef struct pdcp_data_req_header_s {
|
||||
sdu_size_t data_size;
|
||||
signed int inst;
|
||||
ip_traffic_type_t traffic_type;
|
||||
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
|
||||
uint32_t sourceL2Id;
|
||||
uint32_t destinationL2Id;
|
||||
#endif
|
||||
} pdcp_data_req_header_t;
|
||||
|
||||
typedef struct pdcp_data_ind_header_s {
|
||||
@@ -167,6 +173,10 @@ typedef struct pdcp_data_ind_header_s {
|
||||
sdu_size_t data_size;
|
||||
signed int inst;
|
||||
ip_traffic_type_t dummy_traffic_type;
|
||||
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
|
||||
uint32_t sourceL2Id;
|
||||
uint32_t destinationL2Id;
|
||||
#endif
|
||||
} pdcp_data_ind_header_t;
|
||||
|
||||
extern struct net_device *nasdev[NB_INSTANCES_MAX];
|
||||
|
||||
@@ -304,7 +304,16 @@ ue_ip_common_ip2wireless(
|
||||
if (dst_addr) {
|
||||
printk("[UE_IP_DRV][%s] Dest %d.%d.%d.%d\n",__FUNCTION__, dst_addr[0],dst_addr[1],dst_addr[2],dst_addr[3]);
|
||||
}
|
||||
|
||||
// modify inst by IP address for the U-Plane of multiple UEs while L2 fapi simulator start
|
||||
#ifdef UESIM_EXPANSION
|
||||
if ((src_addr[3] - 2)> instP) {
|
||||
pdcph.inst = src_addr[3] - 2;
|
||||
printk("[UE_IP_DRV] change INST from %d to %d\n",instP, pdcph.inst);
|
||||
instP = src_addr[3] - 2;
|
||||
priv_p=netdev_priv(ue_ip_dev[instP]);
|
||||
}
|
||||
#endif
|
||||
// modify inst by IP address for the U-Plane of multiple UEs while L2 fapi simulator end
|
||||
//get Ipv4 address and pass to PCDP header
|
||||
printk("[UE_IP_DRV] source Id: 0x%08x\n",pdcph.sourceL2Id );
|
||||
printk("[UE_IP_DRV] destinationL2Id Id: 0x%08x\n",pdcph.destinationL2Id );
|
||||
|
||||
@@ -394,7 +394,7 @@ int init_module (void)
|
||||
|
||||
for (inst=0; inst<UE_IP_NB_INSTANCES_MAX; inst++) {
|
||||
printk("[UE_IP_DRV][%s] begin init instance %d\n", __FUNCTION__,inst);
|
||||
sprintf(devicename,"oip%d",inst);
|
||||
sprintf(devicename,"oip%d",inst+1);
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
|
||||
ue_ip_dev[inst] = alloc_netdev(sizeof(ue_ip_priv_t),devicename, ue_ip_init);
|
||||
#else
|
||||
|
||||
@@ -128,6 +128,17 @@ typedef struct IF_Module_s{
|
||||
pthread_mutex_t if_mutex;
|
||||
}IF_Module_t;
|
||||
|
||||
// These mutex is used for multiple UEs L2 FAPI simulator.
|
||||
// Each UEs set these value in UL and UL_INFO is shared in all UE's thread.
|
||||
typedef struct {
|
||||
pthread_mutex_t rx_mutex;
|
||||
pthread_mutex_t crc_mutex;
|
||||
pthread_mutex_t sr_mutex;
|
||||
pthread_mutex_t harq_mutex;
|
||||
pthread_mutex_t cqi_mutex;
|
||||
pthread_mutex_t rach_mutex;
|
||||
}FILL_UL_INFO_MUTEX_t;
|
||||
|
||||
/*Initial */
|
||||
IF_Module_t *IF_Module_init(int Mod_id);
|
||||
void IF_Module_kill(int Mod_id);
|
||||
|
||||
@@ -25,7 +25,11 @@ extern int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind);
|
||||
void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port);
|
||||
|
||||
|
||||
|
||||
UL_IND_t *UL_INFO = NULL;
|
||||
nfapi_tx_request_pdu_t* tx_request_pdu_list = NULL;
|
||||
nfapi_dl_config_request_t* dl_config_req = NULL;
|
||||
nfapi_ul_config_request_t* ul_config_req = NULL;
|
||||
nfapi_hi_dci0_request_t* hi_dci0_req = NULL;
|
||||
|
||||
//extern uint8_t nfapi_pnf;
|
||||
//UL_IND_t *UL_INFO;
|
||||
@@ -47,7 +51,9 @@ void fill_rx_indication_UE_MAC(module_id_t Mod_id,int frame,int subframe, UL_IND
|
||||
int timing_advance_update;
|
||||
|
||||
|
||||
pthread_mutex_lock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
|
||||
// pthread_mutex_lock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
|
||||
// change for mutiple UE's simulation.
|
||||
pthread_mutex_lock(&fill_ul_mutex.rx_mutex);
|
||||
|
||||
|
||||
UL_INFO->rx_ind.sfn_sf = frame<<4| subframe;
|
||||
@@ -65,7 +71,11 @@ void fill_rx_indication_UE_MAC(module_id_t Mod_id,int frame,int subframe, UL_IND
|
||||
//pdu->rx_indication_rel8.length = eNB->ulsch[UE_id]->harq_processes[harq_pid]->TBS>>3;
|
||||
pdu->rx_indication_rel8.length = buflen;
|
||||
pdu->rx_indication_rel8.offset = 1; // DJP - I dont understand - but broken unless 1 ???? 0; // filled in at the end of the UL_INFO formation
|
||||
pdu->data = ulsch_buffer;
|
||||
|
||||
// ulsch_buffer is necessary to keep its value.
|
||||
//pdu->data = ulsch_buffer;
|
||||
pdu->data = malloc(buflen);
|
||||
memcpy(pdu->data,ulsch_buffer,buflen);
|
||||
// estimate timing advance for MAC
|
||||
//sync_pos = lte_est_timing_advance_pusch(eNB,UE_id);
|
||||
timing_advance_update = 0; // Don't know what to put here
|
||||
@@ -80,7 +90,9 @@ void fill_rx_indication_UE_MAC(module_id_t Mod_id,int frame,int subframe, UL_IND
|
||||
|
||||
UL_INFO->rx_ind.rx_indication_body.number_of_pdus++;
|
||||
UL_INFO->rx_ind.sfn_sf = frame<<4 | subframe;
|
||||
pthread_mutex_unlock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
|
||||
// pthread_mutex_unlock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
|
||||
// change for mutiple UE's simulation.
|
||||
pthread_mutex_unlock(&fill_ul_mutex.rx_mutex);
|
||||
|
||||
|
||||
}
|
||||
@@ -88,7 +100,9 @@ void fill_rx_indication_UE_MAC(module_id_t Mod_id,int frame,int subframe, UL_IND
|
||||
void fill_sr_indication_UE_MAC(int Mod_id,int frame,int subframe, UL_IND_t *UL_INFO, uint16_t rnti) {
|
||||
|
||||
|
||||
pthread_mutex_lock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
|
||||
// change for mutiple UE's simulation.
|
||||
//pthread_mutex_lock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
|
||||
pthread_mutex_lock(&fill_ul_mutex.sr_mutex);
|
||||
|
||||
nfapi_sr_indication_t *sr_ind = &UL_INFO->sr_ind;
|
||||
nfapi_sr_indication_body_t *sr_ind_body = &sr_ind->sr_indication_body;
|
||||
@@ -122,13 +136,17 @@ void fill_sr_indication_UE_MAC(int Mod_id,int frame,int subframe, UL_IND_t *UL_I
|
||||
|
||||
//UL_INFO->rx_ind.rx_indication_body.number_of_pdus++;
|
||||
sr_ind_body->number_of_srs++;
|
||||
pthread_mutex_unlock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
|
||||
// change for mutiple UE's simulation.
|
||||
// pthread_mutex_unlock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
|
||||
pthread_mutex_unlock(&fill_ul_mutex.sr_mutex);
|
||||
}
|
||||
|
||||
|
||||
void fill_crc_indication_UE_MAC(int Mod_id,int frame,int subframe, UL_IND_t *UL_INFO, uint8_t crc_flag, int index, uint16_t rnti) {
|
||||
|
||||
pthread_mutex_lock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
|
||||
// change for mutiple UE's simulation.
|
||||
//pthread_mutex_lock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
|
||||
pthread_mutex_lock(&fill_ul_mutex.crc_mutex);
|
||||
|
||||
// REMEMBER HAVE EXCHANGED THE FOLLOWING TWO LINES HERE!
|
||||
nfapi_crc_indication_pdu_t *pdu = &UL_INFO->crc_ind.crc_indication_body.crc_pdu_list[UL_INFO->crc_ind.crc_indication_body.number_of_crcs];
|
||||
@@ -151,14 +169,21 @@ void fill_crc_indication_UE_MAC(int Mod_id,int frame,int subframe, UL_IND_t *UL_
|
||||
|
||||
LOG_D(PHY, "%s() rnti:%04x pdus:%d\n", __FUNCTION__, pdu->rx_ue_information.rnti, UL_INFO->crc_ind.crc_indication_body.number_of_crcs);
|
||||
|
||||
pthread_mutex_unlock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
|
||||
// change for mutiple UE's simulation.
|
||||
// pthread_mutex_unlock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
|
||||
pthread_mutex_unlock(&fill_ul_mutex.crc_mutex);
|
||||
}
|
||||
|
||||
void fill_rach_indication_UE_MAC(int Mod_id,int frame,int subframe, UL_IND_t *UL_INFO, uint8_t ra_PreambleIndex, uint16_t ra_RNTI) {
|
||||
|
||||
LOG_D(MAC, "fill_rach_indication_UE_MAC 1 \n");
|
||||
pthread_mutex_lock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
|
||||
UL_INFO = (UL_IND_t*)malloc(sizeof(UL_IND_t));
|
||||
|
||||
// change for mutiple UE's simulation.
|
||||
// pthread_mutex_lock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
|
||||
pthread_mutex_lock(&fill_ul_mutex.rach_mutex);
|
||||
|
||||
// memory allocation and free memory of UL_INFO are done in UE_phy_stub_single_thread_rxn_txnp4.
|
||||
// UL_INFO = (UL_IND_t*)malloc(sizeof(UL_IND_t));
|
||||
|
||||
UL_INFO->rach_ind.rach_indication_body.number_of_preambles = 1;
|
||||
|
||||
@@ -195,16 +220,22 @@ void fill_rach_indication_UE_MAC(int Mod_id,int frame,int subframe, UL_IND_t *UL
|
||||
// with that branch.
|
||||
oai_nfapi_rach_ind(&UL_INFO->rach_ind);
|
||||
free(UL_INFO->rach_ind.rach_indication_body.preamble_list);
|
||||
free(UL_INFO);
|
||||
|
||||
// memory allocation and free memory of UL_INFO are done in UE_phy_stub_single_thread_rxn_txnp4.
|
||||
//free(UL_INFO);
|
||||
|
||||
//}
|
||||
pthread_mutex_unlock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
|
||||
// change for mutiple UE's simulation.
|
||||
// pthread_mutex_unlock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
|
||||
pthread_mutex_unlock(&fill_ul_mutex.rach_mutex);
|
||||
|
||||
}
|
||||
|
||||
void fill_ulsch_cqi_indication_UE_MAC(int Mod_id, uint16_t frame,uint8_t subframe, UL_IND_t *UL_INFO, uint16_t rnti) {
|
||||
|
||||
pthread_mutex_lock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
|
||||
// change for mutiple UE's simulation.
|
||||
//pthread_mutex_lock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
|
||||
pthread_mutex_lock(&fill_ul_mutex.cqi_mutex);
|
||||
nfapi_cqi_indication_pdu_t *pdu = &UL_INFO->cqi_ind.cqi_pdu_list[UL_INFO->cqi_ind.number_of_cqis];
|
||||
nfapi_cqi_indication_raw_pdu_t *raw_pdu = &UL_INFO->cqi_ind.cqi_raw_pdu_list[UL_INFO->cqi_ind.number_of_cqis];
|
||||
|
||||
@@ -233,14 +264,18 @@ void fill_ulsch_cqi_indication_UE_MAC(int Mod_id, uint16_t frame,uint8_t subfram
|
||||
|
||||
|
||||
UL_INFO->cqi_ind.number_of_cqis++;
|
||||
pthread_mutex_unlock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
|
||||
|
||||
// change for mutiple UE's simulation.
|
||||
//pthread_mutex_unlock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
|
||||
pthread_mutex_unlock(&fill_ul_mutex.cqi_mutex);
|
||||
}
|
||||
|
||||
void fill_ulsch_harq_indication_UE_MAC(int Mod_id, int frame,int subframe, UL_IND_t *UL_INFO, nfapi_ul_config_ulsch_harq_information *harq_information, uint16_t rnti)
|
||||
{
|
||||
|
||||
pthread_mutex_lock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
|
||||
// change for mutiple UE's simulation.
|
||||
//pthread_mutex_lock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
|
||||
pthread_mutex_lock(&fill_ul_mutex.harq_mutex);
|
||||
|
||||
nfapi_harq_indication_pdu_t *pdu = &UL_INFO->harq_ind.harq_indication_body.harq_pdu_list[UL_INFO->harq_ind.harq_indication_body.number_of_harqs];
|
||||
int i;
|
||||
|
||||
@@ -271,8 +306,9 @@ void fill_ulsch_harq_indication_UE_MAC(int Mod_id, int frame,int subframe, UL_IN
|
||||
}
|
||||
|
||||
UL_INFO->harq_ind.harq_indication_body.number_of_harqs++;
|
||||
pthread_mutex_unlock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
|
||||
}
|
||||
// change for mutiple UE's simulation.
|
||||
//pthread_mutex_unlock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
|
||||
pthread_mutex_unlock(&fill_ul_mutex.harq_mutex);}
|
||||
|
||||
|
||||
void fill_uci_harq_indication_UE_MAC(int Mod_id,
|
||||
@@ -285,7 +321,10 @@ void fill_uci_harq_indication_UE_MAC(int Mod_id,
|
||||
uint16_t tdd_multiplexing_mask*/) {
|
||||
|
||||
|
||||
pthread_mutex_lock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
|
||||
// change for mutiple UE's simulation.
|
||||
//pthread_mutex_lock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
|
||||
pthread_mutex_lock(&fill_ul_mutex.harq_mutex);
|
||||
|
||||
nfapi_harq_indication_t *ind = &UL_INFO->harq_ind;
|
||||
nfapi_harq_indication_body_t *body = &ind->harq_indication_body;
|
||||
nfapi_harq_indication_pdu_t *pdu = &body->harq_pdu_list[UL_INFO->harq_ind.harq_indication_body.number_of_harqs];
|
||||
@@ -311,6 +350,7 @@ void fill_uci_harq_indication_UE_MAC(int Mod_id,
|
||||
else if (SNRtimes10 > 635) pdu->ul_cqi_information.ul_cqi=255;
|
||||
else pdu->ul_cqi_information.ul_cqi=(640+SNRtimes10)/5;
|
||||
pdu->ul_cqi_information.channel = 0;
|
||||
if(harq_information->harq_information_rel9_fdd.tl.tag == NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL9_FDD_TAG){
|
||||
if ((harq_information->harq_information_rel9_fdd.ack_nack_mode == 0) &&
|
||||
(harq_information->harq_information_rel9_fdd.harq_size == 1)) {
|
||||
|
||||
@@ -332,12 +372,31 @@ void fill_uci_harq_indication_UE_MAC(int Mod_id,
|
||||
pdu->harq_indication_fdd_rel13.harq_tb_n[1] = 1; // Assuming always an ACK (No NACK or DTX)
|
||||
|
||||
}
|
||||
else AssertFatal(1==0,"only format 1a/b for now, received \n");
|
||||
}else if(harq_information->harq_information_rel10_tdd.tl.tag == NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL10_TDD_TAG ){
|
||||
if ((harq_information->harq_information_rel10_tdd.ack_nack_mode == 0) &&
|
||||
(harq_information->harq_information_rel10_tdd.harq_size == 1)) {
|
||||
pdu->harq_indication_tdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_TDD_REL13_TAG;
|
||||
pdu->harq_indication_tdd_rel13.mode = 0;
|
||||
pdu->harq_indication_tdd_rel13.number_of_ack_nack = 1;
|
||||
pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = 1;
|
||||
|
||||
} else if ((harq_information->harq_information_rel10_tdd.ack_nack_mode == 1) &&
|
||||
(harq_information->harq_information_rel10_tdd.harq_size == 2)) {
|
||||
pdu->harq_indication_tdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_TDD_REL13_TAG;
|
||||
pdu->harq_indication_tdd_rel13.mode = 0;
|
||||
pdu->harq_indication_tdd_rel13.number_of_ack_nack = 1;
|
||||
pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = 1;
|
||||
pdu->harq_indication_tdd_rel13.harq_data[1].bundling.value_0 = 1;
|
||||
|
||||
}
|
||||
} else AssertFatal(1==0,"only format 1a/b for now, received \n");
|
||||
|
||||
|
||||
UL_INFO->harq_ind.harq_indication_body.number_of_harqs++;
|
||||
LOG_D(PHY,"Incremented eNB->UL_INFO.harq_ind.number_of_harqs:%d\n", UL_INFO->harq_ind.harq_indication_body.number_of_harqs);
|
||||
pthread_mutex_unlock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
|
||||
// change for mutiple UE's simulation.
|
||||
//pthread_mutex_unlock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
|
||||
pthread_mutex_unlock(&fill_ul_mutex.harq_mutex);
|
||||
|
||||
}
|
||||
|
||||
@@ -622,7 +681,8 @@ int dl_config_req_UE_MAC(nfapi_dl_config_request_t* req, module_id_t Mod_id) //,
|
||||
//if(tx_request_pdu_list[dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index].segments[0].segment_data!= NULL && tx_request_pdu_list[dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index].segments[0].segment_length >0){
|
||||
*/
|
||||
|
||||
if(dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index <= tx_req_num_elems -1){
|
||||
// to avoid unexpected error , add check pdu_index is more than 0.
|
||||
if((dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index >= 0) &&(dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index <= tx_req_num_elems -1)){
|
||||
//if(tx_request_pdu_list + dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index!= NULL){
|
||||
|
||||
LOG_E(MAC, "dl_config_req_UE_MAC 2 Received data: sfn/sf:%d PDU[%d] size:%d, TX_PDU index: %d, tx_req_num_elems: %d \n", NFAPI_SFNSF2DEC(req->sfn_sf), i, dl_config_pdu_list[i].pdu_size, dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index, tx_req_num_elems);
|
||||
|
||||
@@ -17,19 +17,23 @@
|
||||
//#include "openair1/PHY/defs.h"
|
||||
//#include "openair1/PHY/LTE_TRANSPORT/defs.h"
|
||||
|
||||
UL_IND_t *UL_INFO;
|
||||
|
||||
nfapi_tx_request_pdu_t* tx_request_pdu_list;
|
||||
// this mutex is used to set multiple UE's UL value in L2 FAPI simulator.
|
||||
FILL_UL_INFO_MUTEX_t fill_ul_mutex;
|
||||
//below 2 difinitions move to phy_stub_UE.c to add initialization when difinition.
|
||||
extern UL_IND_t *UL_INFO;
|
||||
extern nfapi_tx_request_pdu_t* tx_request_pdu_list;
|
||||
// New
|
||||
/// Pointers to config_request types. Used from nfapi callback functions.
|
||||
nfapi_dl_config_request_t* dl_config_req;
|
||||
nfapi_ul_config_request_t* ul_config_req;
|
||||
nfapi_hi_dci0_request_t* hi_dci0_req;
|
||||
//below 3 difinitions move to phy_stub_UE.c to add initialization when difinition.
|
||||
extern nfapi_dl_config_request_t* dl_config_req;
|
||||
extern nfapi_ul_config_request_t* ul_config_req;
|
||||
extern nfapi_hi_dci0_request_t* hi_dci0_req;
|
||||
|
||||
int tx_req_num_elems;
|
||||
|
||||
int next_ra_frame;
|
||||
module_id_t next_Mod_id;
|
||||
//below 2 difinitions move to lte-ue.c to add initialization when difinition.
|
||||
//int next_ra_frame;
|
||||
//module_id_t next_Mod_id;
|
||||
eth_params_t stub_eth_params;
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+2809
-3332
File diff suppressed because it is too large
Load Diff
@@ -5587,37 +5587,6 @@ rrc_eNB_decode_ccch(
|
||||
0,
|
||||
0);
|
||||
|
||||
/*
|
||||
#if defined(ENABLE_ITTI)
|
||||
# if defined(DISABLE_ITTI_XER_PRINT)
|
||||
{
|
||||
MessageDef *message_p;
|
||||
|
||||
message_p = itti_alloc_new_message(TASK_RRC_ENB, RRC_UL_CCCH_MESSAGE);
|
||||
memcpy(&message_p->ittiMsg, (void *)ul_ccch_msg, sizeof(RrcUlCcchMessage));
|
||||
|
||||
itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->instance, message_p);
|
||||
}
|
||||
# else
|
||||
{
|
||||
char message_string[10000];
|
||||
size_t message_string_size;
|
||||
|
||||
if ((message_string_size =
|
||||
xer_sprint(message_string, sizeof(message_string), &asn_DEF_LTE_UL_CCCH_Message, (void *)ul_ccch_msg)) > 0) {
|
||||
MessageDef *msg_p;
|
||||
|
||||
msg_p = itti_alloc_new_message_sized(TASK_RRC_ENB, RRC_UL_CCCH, message_string_size + sizeof(IttiMsgText));
|
||||
msg_p->ittiMsg.rrc_ul_ccch.size = message_string_size;
|
||||
memcpy(&msg_p->ittiMsg.rrc_ul_ccch.text, message_string, message_string_size);
|
||||
|
||||
itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->instance, msg_p);
|
||||
}
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
*/
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
LOG_T(RRC, "%x.", ((uint8_t *) & ul_ccch_msg)[i]);
|
||||
}
|
||||
@@ -6105,12 +6074,8 @@ rrc_eNB_decode_dcch(
|
||||
LTE_UL_DCCH_Message_t *ul_dcch_msg = NULL; //&uldcchmsg;
|
||||
int i;
|
||||
struct rrc_eNB_ue_context_s *ue_context_p = NULL;
|
||||
#if defined(ENABLE_ITTI)
|
||||
# if defined(ENABLE_USE_MME)
|
||||
MessageDef *msg_delete_tunnels_p = NULL;
|
||||
uint8_t xid;
|
||||
#endif
|
||||
#endif
|
||||
int dedicated_DRB=0;
|
||||
T(T_ENB_RRC_UL_DCCH_DATA_IN, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
|
||||
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||
|
||||
@@ -51,7 +51,7 @@ extern LTE_LogicalChannelConfig_t SRB2_logicalChannelConfig_defaultValue;
|
||||
extern unsigned char NB_INST;
|
||||
#endif
|
||||
extern unsigned char NB_eNB_INST;
|
||||
extern unsigned char NB_UE_INST;
|
||||
extern uint16_t NB_UE_INST;
|
||||
extern unsigned short NODE_ID[1];
|
||||
#endif
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
UE_PF_PO_t UE_PF_PO[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB];
|
||||
pthread_mutex_t ue_pf_po_mutex;
|
||||
UE_RRC_INST *UE_rrc_inst;
|
||||
UE_RRC_INST *UE_rrc_inst = NULL;
|
||||
#include "LAYER2/MAC/mac_extern.h"
|
||||
#define MAX_U32 0xFFFFFFFF
|
||||
|
||||
|
||||
+43
-22
@@ -33,26 +33,23 @@ This header file must be included */
|
||||
#define OPT_H_
|
||||
|
||||
#ifndef sys_include
|
||||
#define sys_include
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#define sys_include
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#endif
|
||||
#ifndef project_include
|
||||
#define project_include
|
||||
#include "common/utils/LOG/log_if.h"
|
||||
// #include "UTIL/LOG/log_extern.h"
|
||||
//#include "PHY/defs.h"
|
||||
//#include "PHY/extern.h"
|
||||
#include "PHY/impl_defs_lte.h"
|
||||
#define project_include
|
||||
#include "common/utils/LOG/log_if.h"
|
||||
#include "PHY/impl_defs_lte.h"
|
||||
#endif
|
||||
|
||||
#define PACKET_MAC_LTE_DEFAULT_UDP_PORT (9999)
|
||||
@@ -65,6 +62,32 @@ typedef guint8 gboolean;
|
||||
#include "packet-mac-lte.h"
|
||||
#include "mac_pcap.h"
|
||||
|
||||
/* OPT parameters definitions */
|
||||
#define OPT_CONFIGPREFIX "opt"
|
||||
|
||||
#define CONFIG_HLP_TYPEMON "Type of L2 monitoring messages: none,pcap,wireshark \n"
|
||||
#define CONFIG_HLP_L2MONIP "ip address for wireshark messages \n"
|
||||
#define CONFIG_HLP_L2MONPATH "file path for pcap messages on localhost \n"
|
||||
/*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* command line parameters for LOG utility */
|
||||
/* optname helpstr paramflags XXXptr defXXXval type numelt */
|
||||
/*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
#define OPT_PARAMS_DESC { \
|
||||
{"type" , CONFIG_HLP_TYPEMON, 0, strptr:&in_type, defstrval:"none", TYPE_STRING, 0}, \
|
||||
{"ip" , CONFIG_HLP_L2MONIP, 0, strptr:&in_ip, defstrval:"127.0.0.1", TYPE_STRING, 0}, \
|
||||
{"path" , CONFIG_HLP_L2MONPATH, 0, strptr:&in_path, defstrval:"/tmp/oai_opt.pcap", TYPE_STRING, 0}, \
|
||||
}
|
||||
|
||||
#define OPTTYPE_IDX 0
|
||||
/* check function for opt parameters */
|
||||
#define OPTTYPE_OKSTRINGS {"none","pcap","wireshark"}
|
||||
#define OPTTYPE_VALUES {OPT_NONE,OPT_PCAP,OPT_WIRESHARK}
|
||||
#define OPTPARAMS_CHECK_DESC { \
|
||||
{ .s3a= { config_checkstr_assign_integer, OPTTYPE_OKSTRINGS,OPTTYPE_VALUES ,3}} ,\
|
||||
{ .s5= {NULL }} , \
|
||||
{ .s5= {NULL }} , \
|
||||
}
|
||||
|
||||
#ifdef OCP_FRAMEWORK
|
||||
#include <enums.h>
|
||||
#else
|
||||
@@ -82,9 +105,7 @@ typedef enum radio_type_e {
|
||||
RADIO_TYPE_MAX
|
||||
} radio_type_t;
|
||||
|
||||
extern trace_mode_t opt_type;
|
||||
extern char in_ip[40];
|
||||
extern char in_path[FILENAME_MAX];
|
||||
|
||||
|
||||
/**
|
||||
* function def
|
||||
@@ -94,7 +115,7 @@ void trace_pdu(int direction, uint8_t *pdu_buffer, unsigned int pdu_buffer_size,
|
||||
int ueid, int rntiType, int rnti, uint16_t sysFrame, uint8_t subframe,
|
||||
int oob_event, int oob_event_value);
|
||||
|
||||
int init_opt(char *path, char *ip);
|
||||
int init_opt(void);
|
||||
|
||||
void terminate_opt(void);
|
||||
|
||||
|
||||
+143
-159
@@ -90,7 +90,7 @@ what about the implementation
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "common/config/config_userapi.h"
|
||||
#include "opt.h"
|
||||
|
||||
int opt_enabled=0;
|
||||
@@ -98,8 +98,8 @@ int opt_enabled=0;
|
||||
//static unsigned char g_PDUBuffer[1600];
|
||||
//static unsigned int g_PDUOffset;
|
||||
|
||||
char in_ip[40];
|
||||
char in_path[FILENAME_MAX];
|
||||
static char *in_ip;
|
||||
static char *in_path;
|
||||
FILE *file_fd = NULL;
|
||||
pcap_hdr_t file_header = {
|
||||
0xa1b2c3d4, /* magic number */
|
||||
@@ -133,17 +133,15 @@ static void SendFrame(guint8 radioType, guint8 direction, guint8 rntiType,
|
||||
static int MAC_LTE_PCAP_WritePDU(MAC_Context_Info_t *context,
|
||||
const unsigned char *PDU, unsigned int length);
|
||||
|
||||
static void *opt_listener_thread(void *arg)
|
||||
{
|
||||
static void *opt_listener_thread(void *arg) {
|
||||
ssize_t ret;
|
||||
struct sockaddr_in from_address;
|
||||
socklen_t socklen = sizeof(from_address);
|
||||
|
||||
memset(&from_address, 0, sizeof(from_address));
|
||||
|
||||
while(1) {
|
||||
/* Simply drop packets */
|
||||
ret = recvfrom(opt_listener.sd, NULL, 0, 0, (struct sockaddr*)&from_address,
|
||||
ret = recvfrom(opt_listener.sd, NULL, 0, 0, (struct sockaddr *)&from_address,
|
||||
&socklen);
|
||||
|
||||
if (ret == 0) {
|
||||
@@ -165,17 +163,13 @@ static void *opt_listener_thread(void *arg)
|
||||
}
|
||||
|
||||
static
|
||||
int opt_create_listener_socket(char *ip_address, uint16_t port)
|
||||
{
|
||||
int opt_create_listener_socket(char *ip_address, uint16_t port) {
|
||||
/* Create an UDP socket and listen on it.
|
||||
* Silently discard PDU received.
|
||||
*/
|
||||
|
||||
int sd = -1;
|
||||
int ret = -1;
|
||||
|
||||
memset(&opt_listener, 0, sizeof(opt_listener_t));
|
||||
|
||||
sd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
|
||||
if (sd < 0) {
|
||||
@@ -190,8 +184,7 @@ int opt_create_listener_socket(char *ip_address, uint16_t port)
|
||||
/* Listening only on provided IP address */
|
||||
opt_listener.address.sin_addr.s_addr = inet_addr(ip_address);
|
||||
opt_listener.address.sin_port = htons(port);
|
||||
|
||||
ret = bind(opt_listener.sd, (struct sockaddr*) &opt_listener.address, sizeof(opt_listener.address));
|
||||
ret = bind(opt_listener.sd, (struct sockaddr *) &opt_listener.address, sizeof(opt_listener.address));
|
||||
|
||||
if (ret != 0) {
|
||||
LOG_E(OPT, "Failed to bind socket to (%s:%u): %s\n",
|
||||
@@ -231,49 +224,39 @@ static void SendFrame(guint8 radioType, guint8 direction, guint8 rntiType,
|
||||
guint16 rnti, guint16 ueid, guint16 sfnSf,
|
||||
guint8 isPredefinedData, guint8 retx, guint8 crcStatus,
|
||||
guint8 oob_event, guint8 oob_event_value,
|
||||
uint8_t *pdu_buffer, unsigned int pdu_buffer_size)
|
||||
{
|
||||
uint8_t *pdu_buffer, unsigned int pdu_buffer_size) {
|
||||
unsigned char frameBuffer[9000];
|
||||
unsigned int frameOffset;
|
||||
|
||||
ssize_t bytesSent;
|
||||
frameOffset = 0;
|
||||
uint16_t tmp16;
|
||||
|
||||
memcpy(frameBuffer+frameOffset, MAC_LTE_START_STRING,
|
||||
strlen(MAC_LTE_START_STRING));
|
||||
frameOffset += strlen(MAC_LTE_START_STRING);
|
||||
|
||||
/******************************************************************************/
|
||||
/* Now write out fixed fields (the mandatory elements of struct mac_lte_info) */
|
||||
frameBuffer[frameOffset++] = radioType;
|
||||
frameBuffer[frameOffset++] = direction;
|
||||
frameBuffer[frameOffset++] = rntiType;
|
||||
|
||||
/*************************************/
|
||||
/* Now optional fields */
|
||||
|
||||
/* RNTI */
|
||||
frameBuffer[frameOffset++] = MAC_LTE_RNTI_TAG;
|
||||
tmp16 = htons(rnti);
|
||||
memcpy(frameBuffer+frameOffset, &tmp16, 2);
|
||||
frameOffset += 2;
|
||||
|
||||
/* UEId */
|
||||
frameBuffer[frameOffset++] = MAC_LTE_UEID_TAG;
|
||||
tmp16 = htons(ueid);
|
||||
memcpy(frameBuffer+frameOffset, &tmp16, 2);
|
||||
frameOffset += 2;
|
||||
|
||||
/* Subframe number */
|
||||
frameBuffer[frameOffset++] = MAC_LTE_FRAME_SUBFRAME_TAG;
|
||||
tmp16 = htons(sfnSf); // frame counter : this will give an expert info as wireshark expects SF and not F
|
||||
memcpy(frameBuffer+frameOffset, &tmp16, 2);
|
||||
frameOffset += 2;
|
||||
|
||||
frameBuffer[frameOffset++] = MAC_LTE_CRC_STATUS_TAG;
|
||||
frameBuffer[frameOffset++] = crcStatus;
|
||||
|
||||
#ifdef WIRESHARK_DEV
|
||||
frameOffset += 2;
|
||||
tmp16 = htons(sfnSf); // subframe
|
||||
@@ -293,55 +276,55 @@ static void SendFrame(guint8 radioType, guint8 direction, guint8 rntiType,
|
||||
frameBuffer[frameOffset++] = retx;
|
||||
}
|
||||
|
||||
//#ifdef WIRESHARK_DEV
|
||||
//#ifdef WIRESHARK_DEV
|
||||
|
||||
/* Relating to out-of-band events */
|
||||
/* N.B. dissector will only look to these fields if length is 0... */
|
||||
if (pdu_buffer_size==0) {
|
||||
switch (oob_event) {
|
||||
case ltemac_send_preamble :
|
||||
LOG_D(OPT,"ltemac_send_preamble event %02x."
|
||||
//"%02x."
|
||||
"%02x.%02x\n",
|
||||
MAC_LTE_SEND_PREAMBLE_TAG,
|
||||
//ltemac_send_preamble,
|
||||
rnti,
|
||||
oob_event_value);
|
||||
//frameBuffer[frameOffset++]=0;
|
||||
//frameBuffer[frameOffset++]=0;
|
||||
//frameBuffer[frameOffset++]=0;
|
||||
frameBuffer[frameOffset++] = MAC_LTE_SEND_PREAMBLE_TAG;
|
||||
//frameBuffer[frameOffset++]=ltemac_send_preamble;
|
||||
frameBuffer[frameOffset++]=rnti; // is the preamble
|
||||
frameBuffer[frameOffset++]=oob_event_value;
|
||||
break;
|
||||
case ltemac_send_preamble :
|
||||
LOG_D(OPT,"ltemac_send_preamble event %02x."
|
||||
//"%02x."
|
||||
"%02x.%02x\n",
|
||||
MAC_LTE_SEND_PREAMBLE_TAG,
|
||||
//ltemac_send_preamble,
|
||||
rnti,
|
||||
oob_event_value);
|
||||
//frameBuffer[frameOffset++]=0;
|
||||
//frameBuffer[frameOffset++]=0;
|
||||
//frameBuffer[frameOffset++]=0;
|
||||
frameBuffer[frameOffset++] = MAC_LTE_SEND_PREAMBLE_TAG;
|
||||
//frameBuffer[frameOffset++]=ltemac_send_preamble;
|
||||
frameBuffer[frameOffset++]=rnti; // is the preamble
|
||||
frameBuffer[frameOffset++]=oob_event_value;
|
||||
break;
|
||||
|
||||
case ltemac_send_sr:
|
||||
frameBuffer[frameOffset++]=MAC_LTE_SR_TAG ;
|
||||
frameOffset+=2;
|
||||
frameBuffer[frameOffset++]=rnti;
|
||||
frameOffset++;
|
||||
frameBuffer[frameOffset++]=oob_event_value;
|
||||
frameOffset++;
|
||||
break;
|
||||
case ltemac_send_sr:
|
||||
frameBuffer[frameOffset++]=MAC_LTE_SR_TAG ;
|
||||
frameOffset+=2;
|
||||
frameBuffer[frameOffset++]=rnti;
|
||||
frameOffset++;
|
||||
frameBuffer[frameOffset++]=oob_event_value;
|
||||
frameOffset++;
|
||||
break;
|
||||
|
||||
case ltemac_sr_failure:
|
||||
default:
|
||||
LOG_W(OPT,"not implemeneted yet\n");
|
||||
break;
|
||||
case ltemac_sr_failure:
|
||||
default:
|
||||
LOG_W(OPT,"not implemeneted yet\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//#endif
|
||||
//#endif
|
||||
/***************************************/
|
||||
/* Now write the MAC PDU */
|
||||
frameBuffer[frameOffset++] = MAC_LTE_PAYLOAD_TAG;
|
||||
|
||||
|
||||
/* Append actual PDU */
|
||||
//memcpy(frameBuffer+frameOffset, g_PDUBuffer, g_PDUOffset);
|
||||
//frameOffset += g_PDUOffset;
|
||||
if (pdu_buffer != NULL) {
|
||||
memcpy(frameBuffer+frameOffset, (void*)pdu_buffer, pdu_buffer_size);
|
||||
memcpy(frameBuffer+frameOffset, (void *)pdu_buffer, pdu_buffer_size);
|
||||
frameOffset += pdu_buffer_size;
|
||||
}
|
||||
|
||||
@@ -358,44 +341,36 @@ static void SendFrame(guint8 radioType, guint8 direction, guint8 rntiType,
|
||||
|
||||
/* Write an individual PDU (PCAP packet header + mac-context + mac-pdu) */
|
||||
static int MAC_LTE_PCAP_WritePDU(MAC_Context_Info_t *context,
|
||||
const uint8_t *PDU, unsigned int length)
|
||||
{
|
||||
const uint8_t *PDU, unsigned int length) {
|
||||
pcaprec_hdr_t packet_header;
|
||||
uint8_t context_header[256];
|
||||
int offset = 0;
|
||||
unsigned short tmp16;
|
||||
|
||||
/*****************************************************************/
|
||||
/* Context information (same as written by UDP heuristic clients */
|
||||
context_header[offset++] = context->radioType;
|
||||
context_header[offset++] = context->direction;
|
||||
context_header[offset++] = context->rntiType;
|
||||
|
||||
/* RNTI */
|
||||
context_header[offset++] = MAC_LTE_RNTI_TAG;
|
||||
tmp16 = htons(context->rnti);
|
||||
memcpy(context_header+offset, &tmp16, 2);
|
||||
offset += 2;
|
||||
|
||||
/* UEId */
|
||||
context_header[offset++] = MAC_LTE_UEID_TAG;
|
||||
tmp16 = htons(context->ueid);
|
||||
memcpy(context_header+offset, &tmp16, 2);
|
||||
offset += 2;
|
||||
|
||||
/* Subframe number */
|
||||
context_header[offset++] = MAC_LTE_FRAME_SUBFRAME_TAG;
|
||||
tmp16 = htons(context->subFrameNumber);
|
||||
memcpy(context_header+offset, &tmp16, 2);
|
||||
offset += 2;
|
||||
|
||||
/* CRC Status */
|
||||
context_header[offset++] = MAC_LTE_CRC_STATUS_TAG;
|
||||
context_header[offset++] = context->crcStatusOK;
|
||||
|
||||
/* Data tag immediately preceding PDU */
|
||||
context_header[offset++] = MAC_LTE_PAYLOAD_TAG;
|
||||
|
||||
/****************************************************************/
|
||||
/* PCAP Header */
|
||||
/* TODO: Timestamp might want to be relative to a more sensible
|
||||
@@ -404,13 +379,11 @@ static int MAC_LTE_PCAP_WritePDU(MAC_Context_Info_t *context,
|
||||
packet_header.ts_usec = (context->subframesSinceCaptureStart % 1000) * 1000;
|
||||
packet_header.incl_len = offset + length;
|
||||
packet_header.orig_len = offset + length;
|
||||
|
||||
/***************************************************************/
|
||||
/* Now write everything to the file */
|
||||
fwrite(&packet_header, sizeof(pcaprec_hdr_t), 1, file_fd);
|
||||
fwrite(context_header, 1, offset, file_fd);
|
||||
fwrite(PDU, 1, length, file_fd);
|
||||
|
||||
return 1;
|
||||
}
|
||||
#include <common/ran_context.h>
|
||||
@@ -419,117 +392,129 @@ extern RAN_CONTEXT_t RC;
|
||||
/* Remote serveraddress (where Wireshark is running) */
|
||||
void trace_pdu(int direction, uint8_t *pdu_buffer, unsigned int pdu_buffer_size,
|
||||
int ueid, int rntiType, int rnti, uint16_t sysFrameNumber, uint8_t subFrameNumber, int oob_event,
|
||||
int oob_event_value)
|
||||
{
|
||||
int oob_event_value) {
|
||||
MAC_Context_Info_t pdu_context;
|
||||
int radioType=FDD_RADIO;
|
||||
|
||||
if (RC.eNB[0][0]!=NULL)
|
||||
radioType=RC.eNB[0][0]->frame_parms.frame_type== FDD ? FDD_RADIO:TDD_RADIO;
|
||||
|
||||
if (PHY_vars_UE_g[0][0] != NULL)
|
||||
radioType=PHY_vars_UE_g[0][0]->frame_parms.frame_type== FDD ? FDD_RADIO:TDD_RADIO;
|
||||
|
||||
switch (opt_type) {
|
||||
case OPT_WIRESHARK :
|
||||
if (g_socksd == -1) {
|
||||
return;
|
||||
}
|
||||
case OPT_WIRESHARK :
|
||||
if (g_socksd == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
SendFrame( radioType,
|
||||
(direction == DIRECTION_DOWNLINK) ? DIRECTION_DOWNLINK : DIRECTION_UPLINK,
|
||||
rntiType, rnti, ueid, (sysFrameNumber<<4) + subFrameNumber,
|
||||
1, 0, 1, //guint8 isPredefinedData, guint8 retx, guint8 crcStatus
|
||||
oob_event,oob_event_value,
|
||||
pdu_buffer, pdu_buffer_size);
|
||||
break;
|
||||
SendFrame( radioType,
|
||||
(direction == DIRECTION_DOWNLINK) ? DIRECTION_DOWNLINK : DIRECTION_UPLINK,
|
||||
rntiType, rnti, ueid, (sysFrameNumber<<4) + subFrameNumber,
|
||||
1, 0, 1, //guint8 isPredefinedData, guint8 retx, guint8 crcStatus
|
||||
oob_event,oob_event_value,
|
||||
pdu_buffer, pdu_buffer_size);
|
||||
break;
|
||||
|
||||
case OPT_PCAP:
|
||||
if (file_fd == NULL) {
|
||||
return;
|
||||
}
|
||||
case OPT_PCAP:
|
||||
if (file_fd == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
pdu_context.radioType = radioType;
|
||||
pdu_context.direction = (direction == DIRECTION_DOWNLINK) ? DIRECTION_DOWNLINK
|
||||
: DIRECTION_UPLINK;
|
||||
pdu_context.rntiType = rntiType;
|
||||
pdu_context.rnti = rnti;
|
||||
pdu_context.ueid = ueid;
|
||||
pdu_context.isRetx = 0;
|
||||
pdu_context.crcStatusOK =1;
|
||||
pdu_context.sysFrameNumber = sysFrameNumber;
|
||||
pdu_context.subFrameNumber = subFrameNumber;
|
||||
pdu_context.subframesSinceCaptureStart = subframesSinceCaptureStart++;
|
||||
MAC_LTE_PCAP_WritePDU( &pdu_context, pdu_buffer, pdu_buffer_size);
|
||||
break;
|
||||
pdu_context.radioType = radioType;
|
||||
pdu_context.direction = (direction == DIRECTION_DOWNLINK) ? DIRECTION_DOWNLINK
|
||||
: DIRECTION_UPLINK;
|
||||
pdu_context.rntiType = rntiType;
|
||||
pdu_context.rnti = rnti;
|
||||
pdu_context.ueid = ueid;
|
||||
pdu_context.isRetx = 0;
|
||||
pdu_context.crcStatusOK =1;
|
||||
pdu_context.sysFrameNumber = sysFrameNumber;
|
||||
pdu_context.subFrameNumber = subFrameNumber;
|
||||
pdu_context.subframesSinceCaptureStart = subframesSinceCaptureStart++;
|
||||
MAC_LTE_PCAP_WritePDU( &pdu_context, pdu_buffer, pdu_buffer_size);
|
||||
break;
|
||||
|
||||
case OPT_TSHARK:
|
||||
default:
|
||||
break;
|
||||
case OPT_TSHARK:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------*/
|
||||
int init_opt(char *path, char *ip)
|
||||
{
|
||||
int init_opt(void) {
|
||||
char *in_type=NULL;
|
||||
paramdef_t opt_params[] = OPT_PARAMS_DESC ;
|
||||
checkedparam_t opt_checkParams[] = OPTPARAMS_CHECK_DESC;
|
||||
uint16_t in_port;
|
||||
config_set_checkfunctions(opt_params, opt_checkParams,
|
||||
sizeof(opt_params)/sizeof(paramdef_t));
|
||||
config_get( opt_params,sizeof(opt_params)/sizeof(paramdef_t),OPT_CONFIGPREFIX);
|
||||
subframesSinceCaptureStart = 0;
|
||||
int tmptype = config_get_processedint( &(opt_params[OPTTYPE_IDX]));
|
||||
|
||||
if (path != NULL) {
|
||||
strncpy( in_path, path, sizeof(in_path) );
|
||||
in_path[sizeof(in_path) - 1] = 0; // terminate string
|
||||
if (tmptype == OPT_NONE) {
|
||||
opt_enabled=0;
|
||||
LOG_I(OPT,"OPT disabled\n");
|
||||
return 0;
|
||||
} else if (tmptype == OPT_PCAP && strlen(in_path) > 0) {
|
||||
opt_type = OPT_PCAP;
|
||||
opt_enabled=1;
|
||||
LOG_I(OPT,"Enabling OPT for PCAP with the following file %s \n",in_path);
|
||||
} else if (tmptype == OPT_WIRESHARK && strlen(in_ip) > 0) {
|
||||
opt_enabled=1;
|
||||
opt_type = OPT_WIRESHARK;
|
||||
LOG_I(OPT,"Enabling OPT for wireshark for local interface %s\n",in_ip);
|
||||
} else {
|
||||
strcpy( in_path, "/tmp/opt.pcap" );
|
||||
}
|
||||
|
||||
if (ip != NULL) {
|
||||
strncpy( in_ip, ip, sizeof(in_ip) );
|
||||
in_ip[sizeof(in_ip) - 1] = 0; // terminate string
|
||||
} else {
|
||||
strcpy( in_ip, "127.0.0.1" );
|
||||
LOG_E(OPT,"Invalid OPT configuration\n");
|
||||
config_printhelp(opt_params,sizeof(opt_params)/sizeof(paramdef_t),OPT_CONFIGPREFIX);
|
||||
}
|
||||
|
||||
in_port = PACKET_MAC_LTE_DEFAULT_UDP_PORT;
|
||||
|
||||
// trace_mode
|
||||
switch (opt_type) {
|
||||
case OPT_WIRESHARK:
|
||||
case OPT_WIRESHARK:
|
||||
|
||||
/* Create local server socket only if using localhost address */
|
||||
if (strcmp(in_ip, "127.0.0.1") == 0) {
|
||||
opt_create_listener_socket(in_ip, in_port);
|
||||
}
|
||||
/* Create local server socket only if using localhost address */
|
||||
if (strcmp(in_ip, "127.0.0.1") == 0) {
|
||||
opt_create_listener_socket(in_ip, in_port);
|
||||
}
|
||||
|
||||
g_socksd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
g_socksd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
|
||||
if (g_socksd == -1) {
|
||||
LOG_E(OPT, "Error trying to create socket (errno=%d)\n", errno);
|
||||
LOG_E(OPT, "CREATING SOCKET FAILED\n");
|
||||
return (-1);
|
||||
}
|
||||
if (g_socksd == -1) {
|
||||
LOG_E(OPT, "Error trying to create socket (errno=%d)\n", errno);
|
||||
LOG_E(OPT, "CREATING SOCKET FAILED\n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Get remote IP address from the function argument */
|
||||
g_serv_addr.sin_family = AF_INET;
|
||||
g_serv_addr.sin_port = htons(in_port);
|
||||
g_serv_addr.sin_addr.s_addr = inet_addr(in_ip);
|
||||
break;
|
||||
/* Get remote IP address from the function argument */
|
||||
g_serv_addr.sin_family = AF_INET;
|
||||
g_serv_addr.sin_port = htons(in_port);
|
||||
g_serv_addr.sin_addr.s_addr = inet_addr(in_ip);
|
||||
break;
|
||||
|
||||
case OPT_PCAP:
|
||||
file_fd = fopen(in_path, "w");
|
||||
case OPT_PCAP:
|
||||
file_fd = fopen(in_path, "w");
|
||||
|
||||
if (file_fd == NULL) {
|
||||
LOG_D(OPT, "Failed to open file \"%s\" for writing\n", in_path);
|
||||
return (-1);
|
||||
}
|
||||
/* Write the file header */
|
||||
fwrite(&file_header, sizeof(pcap_hdr_t), 1, file_fd);
|
||||
break;
|
||||
if (file_fd == NULL) {
|
||||
LOG_D(OPT, "Failed to open file \"%s\" for writing\n", in_path);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
case OPT_TSHARK:
|
||||
LOG_W(OPT, "Tshark is currently not supported\n");
|
||||
opt_type = OPT_NONE;
|
||||
break;
|
||||
/* Write the file header */
|
||||
fwrite(&file_header, sizeof(pcap_hdr_t), 1, file_fd);
|
||||
break;
|
||||
|
||||
default:
|
||||
opt_type = OPT_NONE;
|
||||
LOG_W(OPT, "supported Option\n");
|
||||
break;
|
||||
case OPT_TSHARK:
|
||||
LOG_W(OPT, "Tshark is currently not supported\n");
|
||||
opt_type = OPT_NONE;
|
||||
break;
|
||||
|
||||
default:
|
||||
opt_type = OPT_NONE;
|
||||
LOG_W(OPT, "supported Option\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if ( opt_type == OPT_WIRESHARK )
|
||||
@@ -543,8 +528,7 @@ int init_opt(char *path, char *ip)
|
||||
// memset(mac_info, 0, sizeof(mac_lte_info)+pdu_buffer_size + 8);
|
||||
return (1);
|
||||
}
|
||||
void terminate_opt(void)
|
||||
{
|
||||
void terminate_opt(void) {
|
||||
/* Close local socket */
|
||||
// free(mac_info);
|
||||
if (opt_type != OPT_NONE) {
|
||||
@@ -552,18 +536,18 @@ void terminate_opt(void)
|
||||
}
|
||||
|
||||
switch (opt_type) {
|
||||
case OPT_WIRESHARK:
|
||||
close(g_socksd);
|
||||
g_socksd = -1;
|
||||
break;
|
||||
case OPT_WIRESHARK:
|
||||
close(g_socksd);
|
||||
g_socksd = -1;
|
||||
break;
|
||||
|
||||
case OPT_PCAP:
|
||||
fclose (file_fd);
|
||||
file_fd = NULL;
|
||||
break;
|
||||
case OPT_PCAP:
|
||||
fclose (file_fd);
|
||||
file_fd = NULL;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+83
-139
@@ -67,30 +67,21 @@ void x2ap_eNB_register_eNB(x2ap_eNB_instance_t *instance_p,
|
||||
|
||||
static
|
||||
void x2ap_eNB_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind) {
|
||||
|
||||
int result;
|
||||
|
||||
DevAssert(sctp_data_ind != NULL);
|
||||
|
||||
x2ap_eNB_handle_message(instance, sctp_data_ind->assoc_id, sctp_data_ind->stream,
|
||||
sctp_data_ind->buffer, sctp_data_ind->buffer_length);
|
||||
|
||||
result = itti_free(TASK_UNKNOWN, sctp_data_ind->buffer);
|
||||
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
|
||||
|
||||
}
|
||||
|
||||
static
|
||||
void x2ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp)
|
||||
{
|
||||
void x2ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp) {
|
||||
x2ap_eNB_instance_t *instance_p;
|
||||
x2ap_eNB_data_t *x2ap_enb_data_p;
|
||||
|
||||
DevAssert(sctp_new_association_resp != NULL);
|
||||
|
||||
printf("x2ap_eNB_handle_sctp_association_resp at 1\n");
|
||||
dump_trees();
|
||||
|
||||
printf("x2ap_eNB_handle_sctp_association_resp at 1\n");
|
||||
dump_trees();
|
||||
instance_p = x2ap_eNB_get_instance(instance);
|
||||
DevAssert(instance_p != NULL);
|
||||
|
||||
@@ -99,13 +90,15 @@ dump_trees();
|
||||
*/
|
||||
if (sctp_new_association_resp->assoc_id != -1) {
|
||||
x2ap_enb_data_p = x2ap_get_eNB(instance_p, sctp_new_association_resp->assoc_id,
|
||||
sctp_new_association_resp->ulp_cnx_id);
|
||||
sctp_new_association_resp->ulp_cnx_id);
|
||||
|
||||
if (x2ap_enb_data_p != NULL) {
|
||||
/* some sanity check - to be refined at some point */
|
||||
if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
|
||||
X2AP_ERROR("x2ap_enb_data_p not NULL and sctp state not SCTP_STATE_ESTABLISHED, what to do?\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
x2ap_enb_data_p->in_streams = sctp_new_association_resp->in_streams;
|
||||
x2ap_enb_data_p->out_streams = sctp_new_association_resp->out_streams;
|
||||
return;
|
||||
@@ -113,70 +106,60 @@ dump_trees();
|
||||
}
|
||||
|
||||
x2ap_enb_data_p = x2ap_get_eNB(instance_p, -1,
|
||||
sctp_new_association_resp->ulp_cnx_id);
|
||||
sctp_new_association_resp->ulp_cnx_id);
|
||||
DevAssert(x2ap_enb_data_p != NULL);
|
||||
|
||||
printf("x2ap_eNB_handle_sctp_association_resp at 2\n");
|
||||
dump_trees();
|
||||
printf("x2ap_eNB_handle_sctp_association_resp at 2\n");
|
||||
dump_trees();
|
||||
|
||||
if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
|
||||
X2AP_WARN("Received unsuccessful result for SCTP association (%u), instance %d, cnx_id %u\n",
|
||||
sctp_new_association_resp->sctp_state,
|
||||
instance,
|
||||
sctp_new_association_resp->ulp_cnx_id);
|
||||
|
||||
x2ap_handle_x2_setup_message(x2ap_enb_data_p,
|
||||
sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN);
|
||||
|
||||
sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("x2ap_eNB_handle_sctp_association_resp at 3\n");
|
||||
dump_trees();
|
||||
|
||||
printf("x2ap_eNB_handle_sctp_association_resp at 3\n");
|
||||
dump_trees();
|
||||
/* Update parameters */
|
||||
x2ap_enb_data_p->assoc_id = sctp_new_association_resp->assoc_id;
|
||||
x2ap_enb_data_p->in_streams = sctp_new_association_resp->in_streams;
|
||||
x2ap_enb_data_p->out_streams = sctp_new_association_resp->out_streams;
|
||||
|
||||
printf("x2ap_eNB_handle_sctp_association_resp at 4\n");
|
||||
dump_trees();
|
||||
|
||||
printf("x2ap_eNB_handle_sctp_association_resp at 4\n");
|
||||
dump_trees();
|
||||
/* Prepare new x2 Setup Request */
|
||||
x2ap_eNB_generate_x2_setup_request(instance_p, x2ap_enb_data_p);
|
||||
}
|
||||
|
||||
static
|
||||
void x2ap_eNB_handle_sctp_association_ind(instance_t instance, sctp_new_association_ind_t *sctp_new_association_ind)
|
||||
{
|
||||
void x2ap_eNB_handle_sctp_association_ind(instance_t instance, sctp_new_association_ind_t *sctp_new_association_ind) {
|
||||
x2ap_eNB_instance_t *instance_p;
|
||||
x2ap_eNB_data_t *x2ap_enb_data_p;
|
||||
|
||||
printf("x2ap_eNB_handle_sctp_association_ind at 1 (called for instance %d)\n", instance);
|
||||
dump_trees();
|
||||
printf("x2ap_eNB_handle_sctp_association_ind at 1 (called for instance %d)\n", instance);
|
||||
dump_trees();
|
||||
DevAssert(sctp_new_association_ind != NULL);
|
||||
|
||||
instance_p = x2ap_eNB_get_instance(instance);
|
||||
DevAssert(instance_p != NULL);
|
||||
|
||||
x2ap_enb_data_p = x2ap_get_eNB(instance_p, sctp_new_association_ind->assoc_id, -1);
|
||||
|
||||
if (x2ap_enb_data_p != NULL) abort();
|
||||
// DevAssert(x2ap_enb_data_p != NULL);
|
||||
|
||||
// DevAssert(x2ap_enb_data_p != NULL);
|
||||
if (x2ap_enb_data_p == NULL) {
|
||||
/* Create new eNB descriptor */
|
||||
x2ap_enb_data_p = calloc(1, sizeof(*x2ap_enb_data_p));
|
||||
DevAssert(x2ap_enb_data_p != NULL);
|
||||
|
||||
x2ap_enb_data_p->cnx_id = x2ap_eNB_fetch_add_global_cnx_id();
|
||||
|
||||
x2ap_enb_data_p->x2ap_eNB_instance = instance_p;
|
||||
|
||||
/* Insert the new descriptor in list of known eNB
|
||||
* but not yet associated.
|
||||
*/
|
||||
RB_INSERT(x2ap_enb_map, &instance_p->x2ap_enb_head, x2ap_enb_data_p);
|
||||
x2ap_enb_data_p->state = X2AP_ENB_STATE_CONNECTED;
|
||||
instance_p->x2_target_enb_nb++;
|
||||
|
||||
if (instance_p->x2_target_enb_pending_nb > 0) {
|
||||
instance_p->x2_target_enb_pending_nb--;
|
||||
}
|
||||
@@ -184,37 +167,31 @@ dump_trees();
|
||||
X2AP_WARN("x2ap_enb_data_p already exists\n");
|
||||
}
|
||||
|
||||
printf("x2ap_eNB_handle_sctp_association_ind at 2\n");
|
||||
dump_trees();
|
||||
printf("x2ap_eNB_handle_sctp_association_ind at 2\n");
|
||||
dump_trees();
|
||||
/* Update parameters */
|
||||
x2ap_enb_data_p->assoc_id = sctp_new_association_ind->assoc_id;
|
||||
x2ap_enb_data_p->in_streams = sctp_new_association_ind->in_streams;
|
||||
x2ap_enb_data_p->out_streams = sctp_new_association_ind->out_streams;
|
||||
|
||||
printf("x2ap_eNB_handle_sctp_association_ind at 3\n");
|
||||
dump_trees();
|
||||
printf("x2ap_eNB_handle_sctp_association_ind at 3\n");
|
||||
dump_trees();
|
||||
}
|
||||
|
||||
int x2ap_eNB_init_sctp (x2ap_eNB_instance_t *instance_p,
|
||||
net_ip_address_t *local_ip_addr,
|
||||
uint32_t enb_port_for_X2C)
|
||||
{
|
||||
net_ip_address_t *local_ip_addr,
|
||||
uint32_t enb_port_for_X2C) {
|
||||
// Create and alloc new message
|
||||
MessageDef *message;
|
||||
sctp_init_t *sctp_init = NULL;
|
||||
|
||||
DevAssert(instance_p != NULL);
|
||||
DevAssert(local_ip_addr != NULL);
|
||||
|
||||
message = itti_alloc_new_message (TASK_X2AP, SCTP_INIT_MSG_MULTI_REQ);
|
||||
sctp_init = &message->ittiMsg.sctp_init_multi;
|
||||
|
||||
sctp_init->port = enb_port_for_X2C;
|
||||
sctp_init->ppid = X2AP_SCTP_PPID;
|
||||
sctp_init->ipv4 = 1;
|
||||
sctp_init->ipv6 = 0;
|
||||
sctp_init->nb_ipv4_addr = 1;
|
||||
|
||||
#if 0
|
||||
memcpy(&sctp_init->ipv4_address,
|
||||
local_ip_addr,
|
||||
@@ -227,9 +204,7 @@ int x2ap_eNB_init_sctp (x2ap_eNB_instance_t *instance_p,
|
||||
*/
|
||||
sctp_init->nb_ipv6_addr = 0;
|
||||
sctp_init->ipv6_address[0] = "0:0:0:0:0:0:0:1";
|
||||
|
||||
return itti_send_msg_to_task (TASK_SCTP, instance_p->instance, message);
|
||||
|
||||
}
|
||||
|
||||
static void x2ap_eNB_register_eNB(x2ap_eNB_instance_t *instance_p,
|
||||
@@ -237,47 +212,33 @@ static void x2ap_eNB_register_eNB(x2ap_eNB_instance_t *instance_p,
|
||||
net_ip_address_t *local_ip_addr,
|
||||
uint16_t in_streams,
|
||||
uint16_t out_streams,
|
||||
uint32_t enb_port_for_X2C,
|
||||
int multi_sd)
|
||||
{
|
||||
|
||||
uint32_t enb_port_for_X2C,
|
||||
int multi_sd) {
|
||||
MessageDef *message = NULL;
|
||||
sctp_new_association_req_multi_t *sctp_new_association_req = NULL;
|
||||
x2ap_eNB_data_t *x2ap_enb_data = NULL;
|
||||
|
||||
DevAssert(instance_p != NULL);
|
||||
DevAssert(target_eNB_ip_address != NULL);
|
||||
|
||||
message = itti_alloc_new_message(TASK_X2AP, SCTP_NEW_ASSOCIATION_REQ_MULTI);
|
||||
|
||||
sctp_new_association_req = &message->ittiMsg.sctp_new_association_req_multi;
|
||||
|
||||
sctp_new_association_req->port = enb_port_for_X2C;
|
||||
sctp_new_association_req->ppid = X2AP_SCTP_PPID;
|
||||
|
||||
sctp_new_association_req->in_streams = in_streams;
|
||||
sctp_new_association_req->out_streams = out_streams;
|
||||
|
||||
sctp_new_association_req->multi_sd = multi_sd;
|
||||
|
||||
memcpy(&sctp_new_association_req->remote_address,
|
||||
target_eNB_ip_address,
|
||||
sizeof(*target_eNB_ip_address));
|
||||
|
||||
memcpy(&sctp_new_association_req->local_address,
|
||||
local_ip_addr,
|
||||
sizeof(*local_ip_addr));
|
||||
|
||||
/* Create new eNB descriptor */
|
||||
x2ap_enb_data = calloc(1, sizeof(*x2ap_enb_data));
|
||||
DevAssert(x2ap_enb_data != NULL);
|
||||
|
||||
x2ap_enb_data->cnx_id = x2ap_eNB_fetch_add_global_cnx_id();
|
||||
sctp_new_association_req->ulp_cnx_id = x2ap_enb_data->cnx_id;
|
||||
|
||||
x2ap_enb_data->assoc_id = -1;
|
||||
x2ap_enb_data->x2ap_eNB_instance = instance_p;
|
||||
|
||||
/* Insert the new descriptor in list of known eNB
|
||||
* but not yet associated.
|
||||
*/
|
||||
@@ -285,18 +246,14 @@ static void x2ap_eNB_register_eNB(x2ap_eNB_instance_t *instance_p,
|
||||
x2ap_enb_data->state = X2AP_ENB_STATE_WAITING;
|
||||
instance_p->x2_target_enb_nb ++;
|
||||
instance_p->x2_target_enb_pending_nb ++;
|
||||
|
||||
itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message);
|
||||
}
|
||||
|
||||
static
|
||||
void x2ap_eNB_handle_register_eNB(instance_t instance,
|
||||
x2ap_register_enb_req_t *x2ap_register_eNB)
|
||||
{
|
||||
x2ap_register_enb_req_t *x2ap_register_eNB) {
|
||||
x2ap_eNB_instance_t *new_instance;
|
||||
|
||||
DevAssert(x2ap_register_eNB != NULL);
|
||||
|
||||
/* Look if the provided instance already exists */
|
||||
new_instance = x2ap_eNB_get_instance(instance);
|
||||
|
||||
@@ -308,13 +265,10 @@ void x2ap_eNB_handle_register_eNB(instance_t instance,
|
||||
DevCheck(new_instance->mcc == x2ap_register_eNB->mcc, new_instance->mcc, x2ap_register_eNB->mcc, 0);
|
||||
DevCheck(new_instance->mnc == x2ap_register_eNB->mnc, new_instance->mnc, x2ap_register_eNB->mnc, 0);
|
||||
X2AP_WARN("eNB[%d] already registered\n", instance);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
new_instance = calloc(1, sizeof(x2ap_eNB_instance_t));
|
||||
DevAssert(new_instance != NULL);
|
||||
|
||||
RB_INIT(&new_instance->x2ap_enb_head);
|
||||
|
||||
/* Copy usefull parameters */
|
||||
new_instance->instance = instance;
|
||||
new_instance->eNB_name = x2ap_register_eNB->eNB_name;
|
||||
@@ -324,10 +278,9 @@ void x2ap_eNB_handle_register_eNB(instance_t instance,
|
||||
new_instance->mcc = x2ap_register_eNB->mcc;
|
||||
new_instance->mnc = x2ap_register_eNB->mnc;
|
||||
new_instance->mnc_digit_length = x2ap_register_eNB->mnc_digit_length;
|
||||
|
||||
new_instance->num_cc = x2ap_register_eNB->num_cc;
|
||||
|
||||
for (int i = 0; i< x2ap_register_eNB->num_cc; i++){
|
||||
for (int i = 0; i< x2ap_register_eNB->num_cc; i++) {
|
||||
new_instance->eutra_band[i] = x2ap_register_eNB->eutra_band[i];
|
||||
new_instance->downlink_frequency[i] = x2ap_register_eNB->downlink_frequency[i];
|
||||
new_instance->uplink_frequency_offset[i] = x2ap_register_eNB->uplink_frequency_offset[i];
|
||||
@@ -343,44 +296,40 @@ void x2ap_eNB_handle_register_eNB(instance_t instance,
|
||||
memcpy(new_instance->target_enb_x2_ip_address,
|
||||
x2ap_register_eNB->target_enb_x2_ip_address,
|
||||
x2ap_register_eNB->nb_x2 * sizeof(net_ip_address_t));
|
||||
|
||||
new_instance->nb_x2 = x2ap_register_eNB->nb_x2;
|
||||
new_instance->enb_x2_ip_address = x2ap_register_eNB->enb_x2_ip_address;
|
||||
new_instance->sctp_in_streams = x2ap_register_eNB->sctp_in_streams;
|
||||
new_instance->sctp_out_streams = x2ap_register_eNB->sctp_out_streams;
|
||||
new_instance->enb_port_for_X2C = x2ap_register_eNB->enb_port_for_X2C;
|
||||
|
||||
/* Add the new instance to the list of eNB (meaningfull in virtual mode) */
|
||||
x2ap_eNB_insert_new_instance(new_instance);
|
||||
|
||||
X2AP_INFO("Registered new eNB[%d] and %s eNB id %u\n",
|
||||
instance,
|
||||
x2ap_register_eNB->cell_type == CELL_MACRO_ENB ? "macro" : "home",
|
||||
x2ap_register_eNB->eNB_id);
|
||||
instance,
|
||||
x2ap_register_eNB->cell_type == CELL_MACRO_ENB ? "macro" : "home",
|
||||
x2ap_register_eNB->eNB_id);
|
||||
|
||||
/* initiate the SCTP listener */
|
||||
if (x2ap_eNB_init_sctp(new_instance,&x2ap_register_eNB->enb_x2_ip_address,x2ap_register_eNB->enb_port_for_X2C) < 0 ) {
|
||||
X2AP_ERROR ("Error while sending SCTP_INIT_MSG to SCTP \n");
|
||||
return;
|
||||
X2AP_ERROR ("Error while sending SCTP_INIT_MSG to SCTP \n");
|
||||
return;
|
||||
}
|
||||
X2AP_INFO("eNB[%d] eNB id %u acting as a listner (server)\n",
|
||||
instance, x2ap_register_eNB->eNB_id);
|
||||
|
||||
X2AP_INFO("eNB[%d] eNB id %u acting as a listner (server)\n",
|
||||
instance, x2ap_register_eNB->eNB_id);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void x2ap_eNB_handle_sctp_init_msg_multi_cnf(
|
||||
instance_t instance_id,
|
||||
sctp_init_msg_multi_cnf_t *m)
|
||||
{
|
||||
instance_t instance_id,
|
||||
sctp_init_msg_multi_cnf_t *m) {
|
||||
x2ap_eNB_instance_t *instance;
|
||||
int index;
|
||||
|
||||
DevAssert(m != NULL);
|
||||
|
||||
instance = x2ap_eNB_get_instance(instance_id);
|
||||
DevAssert(instance != NULL);
|
||||
|
||||
instance->multi_sd = m->multi_sd;
|
||||
|
||||
/* Exit if CNF message reports failure.
|
||||
* Failure means multi_sd < 0.
|
||||
*/
|
||||
@@ -392,72 +341,67 @@ void x2ap_eNB_handle_sctp_init_msg_multi_cnf(
|
||||
/* Trying to connect to the provided list of eNB ip address */
|
||||
|
||||
for (index = 0; index < instance->nb_x2; index++) {
|
||||
|
||||
X2AP_INFO("eNB[%d] eNB id %u acting as an initiator (client)\n",
|
||||
instance_id, instance->eNB_id);
|
||||
x2ap_eNB_register_eNB(instance,
|
||||
&instance->target_enb_x2_ip_address[index],
|
||||
&instance->enb_x2_ip_address,
|
||||
instance->sctp_in_streams,
|
||||
instance->sctp_out_streams,
|
||||
instance->enb_port_for_X2C,
|
||||
instance->multi_sd);
|
||||
X2AP_INFO("eNB[%d] eNB id %u acting as an initiator (client)\n",
|
||||
instance_id, instance->eNB_id);
|
||||
x2ap_eNB_register_eNB(instance,
|
||||
&instance->target_enb_x2_ip_address[index],
|
||||
&instance->enb_x2_ip_address,
|
||||
instance->sctp_in_streams,
|
||||
instance->sctp_out_streams,
|
||||
instance->enb_port_for_X2C,
|
||||
instance->multi_sd);
|
||||
}
|
||||
}
|
||||
|
||||
void *x2ap_task(void *arg)
|
||||
{
|
||||
void *x2ap_task(void *arg) {
|
||||
MessageDef *received_msg = NULL;
|
||||
int result;
|
||||
|
||||
X2AP_DEBUG("Starting X2AP layer\n");
|
||||
|
||||
x2ap_eNB_prepare_internal_data();
|
||||
|
||||
itti_mark_task_ready(TASK_X2AP);
|
||||
|
||||
while (1) {
|
||||
itti_receive_msg(TASK_X2AP, &received_msg);
|
||||
|
||||
switch (ITTI_MSG_ID(received_msg)) {
|
||||
case TERMINATE_MESSAGE:
|
||||
X2AP_WARN(" *** Exiting X2AP thread\n");
|
||||
itti_exit_task();
|
||||
break;
|
||||
case TERMINATE_MESSAGE:
|
||||
X2AP_WARN(" *** Exiting X2AP thread\n");
|
||||
itti_exit_task();
|
||||
break;
|
||||
|
||||
case X2AP_REGISTER_ENB_REQ:
|
||||
x2ap_eNB_handle_register_eNB(ITTI_MESSAGE_GET_INSTANCE(received_msg),
|
||||
&X2AP_REGISTER_ENB_REQ(received_msg));
|
||||
break;
|
||||
case X2AP_REGISTER_ENB_REQ:
|
||||
x2ap_eNB_handle_register_eNB(ITTI_MESSAGE_GET_INSTANCE(received_msg),
|
||||
&X2AP_REGISTER_ENB_REQ(received_msg));
|
||||
break;
|
||||
|
||||
case SCTP_INIT_MSG_MULTI_CNF:
|
||||
x2ap_eNB_handle_sctp_init_msg_multi_cnf(ITTI_MESSAGE_GET_INSTANCE(received_msg),
|
||||
&received_msg->ittiMsg.sctp_init_msg_multi_cnf);
|
||||
break;
|
||||
case SCTP_INIT_MSG_MULTI_CNF:
|
||||
x2ap_eNB_handle_sctp_init_msg_multi_cnf(ITTI_MESSAGE_GET_INSTANCE(received_msg),
|
||||
&received_msg->ittiMsg.sctp_init_msg_multi_cnf);
|
||||
break;
|
||||
|
||||
case SCTP_NEW_ASSOCIATION_RESP:
|
||||
x2ap_eNB_handle_sctp_association_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg),
|
||||
&received_msg->ittiMsg.sctp_new_association_resp);
|
||||
break;
|
||||
case SCTP_NEW_ASSOCIATION_RESP:
|
||||
x2ap_eNB_handle_sctp_association_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg),
|
||||
&received_msg->ittiMsg.sctp_new_association_resp);
|
||||
break;
|
||||
|
||||
case SCTP_NEW_ASSOCIATION_IND:
|
||||
x2ap_eNB_handle_sctp_association_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg),
|
||||
&received_msg->ittiMsg.sctp_new_association_ind);
|
||||
break;
|
||||
case SCTP_NEW_ASSOCIATION_IND:
|
||||
x2ap_eNB_handle_sctp_association_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg),
|
||||
&received_msg->ittiMsg.sctp_new_association_ind);
|
||||
break;
|
||||
|
||||
case SCTP_DATA_IND:
|
||||
x2ap_eNB_handle_sctp_data_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg),
|
||||
&received_msg->ittiMsg.sctp_data_ind);
|
||||
break;
|
||||
case SCTP_DATA_IND:
|
||||
x2ap_eNB_handle_sctp_data_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg),
|
||||
&received_msg->ittiMsg.sctp_data_ind);
|
||||
break;
|
||||
|
||||
default:
|
||||
X2AP_ERROR("Received unhandled message: %d:%s\n",
|
||||
ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg));
|
||||
break;
|
||||
default:
|
||||
X2AP_ERROR("Received unhandled message: %d:%s\n",
|
||||
ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg));
|
||||
break;
|
||||
}
|
||||
|
||||
result = itti_free (ITTI_MSG_ORIGIN_ID(received_msg), received_msg);
|
||||
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
|
||||
|
||||
received_msg = NULL;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user