Added some field in RRC eNB info structure to store additionnal information.
Corrected "get_next_UE_index" and "rrc_remove_UE". Started communication between RRC eNB and S1ap. Changed some S1ap structure definitions. Fixed warnings. pre-ci ok. git-svn-id: http://svn.eurecom.fr/openair4G/trunk@4410 818b1a75-f10b-46b9-bf7c-635c3b92a50f
This commit is contained in:
@@ -287,12 +287,12 @@ int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id,
|
||||
|
||||
s1ap_nas_first_req.rnti = 0xC03A;
|
||||
s1ap_nas_first_req.establishment_cause = RRC_CAUSE_MO_DATA;
|
||||
s1ap_nas_first_req.ue_identity.present = GUMMEI_PROVIDED;
|
||||
s1ap_nas_first_req.ue_identity.present = IDENTITY_PR_gummei;
|
||||
|
||||
s1ap_nas_first_req.ue_identity.identity.gummei.mcc = 208;
|
||||
s1ap_nas_first_req.ue_identity.identity.gummei.mnc = 34;
|
||||
s1ap_nas_first_req.ue_identity.identity.gummei.mme_code = 0;
|
||||
s1ap_nas_first_req.ue_identity.identity.gummei.mme_group_id = 0;
|
||||
s1ap_nas_first_req.ue_identity.choice.gummei.mcc = 208;
|
||||
s1ap_nas_first_req.ue_identity.choice.gummei.mnc = 34;
|
||||
s1ap_nas_first_req.ue_identity.choice.gummei.mme_code = 0;
|
||||
s1ap_nas_first_req.ue_identity.choice.gummei.mme_group_id = 0;
|
||||
|
||||
/* NAS Attach request with IMSI */
|
||||
uint8_t nas_attach_req_imsi[] =
|
||||
|
||||
@@ -82,16 +82,16 @@ int s1ap_eNB_handle_nas_first_req(
|
||||
* In case eNB has no MME associated, the eNB should inform RRC and discard
|
||||
* this request.
|
||||
*/
|
||||
if (s1ap_nas_first_req_p->ue_identity.present == GUMMEI_PROVIDED) {
|
||||
if (s1ap_nas_first_req_p->ue_identity.present == IDENTITY_PR_gummei) {
|
||||
mme_desc_p = s1ap_eNB_nnsf_select_mme_by_gummei(
|
||||
instance_p,
|
||||
s1ap_nas_first_req_p->establishment_cause,
|
||||
s1ap_nas_first_req_p->ue_identity.identity.gummei);
|
||||
s1ap_nas_first_req_p->ue_identity.choice.gummei);
|
||||
} else {
|
||||
mme_desc_p = s1ap_eNB_nnsf_select_mme_by_mme_code(
|
||||
instance_p,
|
||||
s1ap_nas_first_req_p->establishment_cause,
|
||||
s1ap_nas_first_req_p->ue_identity.identity.s_tmsi.mme_code);
|
||||
s1ap_nas_first_req_p->ue_identity.choice.s_tmsi.mme_code);
|
||||
}
|
||||
if (mme_desc_p == NULL) {
|
||||
S1AP_WARN("No MME is associated to the eNB\n");
|
||||
@@ -133,22 +133,22 @@ int s1ap_eNB_handle_nas_first_req(
|
||||
s1ap_nas_first_req_p->establishment_cause, RRC_CAUSE_LAST, 0);
|
||||
initial_ue_message_p->rrC_Establishment_Cause = s1ap_nas_first_req_p->establishment_cause;
|
||||
|
||||
if (s1ap_nas_first_req_p->ue_identity.present == S_TMSI_PROVIDED) {
|
||||
if (s1ap_nas_first_req_p->ue_identity.present == IDENTITY_PR_gummei) {
|
||||
initial_ue_message_p->presenceMask |= S1AP_INITIALUEMESSAGEIES_S_TMSI_PRESENT;
|
||||
|
||||
MME_CODE_TO_OCTET_STRING(s1ap_nas_first_req_p->ue_identity.identity.s_tmsi.mme_code,
|
||||
MME_CODE_TO_OCTET_STRING(s1ap_nas_first_req_p->ue_identity.choice.s_tmsi.mme_code,
|
||||
&initial_ue_message_p->s_tmsi.mMEC);
|
||||
M_TMSI_TO_OCTET_STRING(s1ap_nas_first_req_p->ue_identity.identity.s_tmsi.m_tmsi,
|
||||
M_TMSI_TO_OCTET_STRING(s1ap_nas_first_req_p->ue_identity.choice.s_tmsi.m_tmsi,
|
||||
&initial_ue_message_p->s_tmsi.m_TMSI);
|
||||
} else {
|
||||
initial_ue_message_p->presenceMask |= S1AP_INITIALUEMESSAGEIES_GUMMEI_ID_PRESENT;
|
||||
|
||||
MCC_MNC_TO_PLMNID(s1ap_nas_first_req_p->ue_identity.identity.gummei.mcc,
|
||||
s1ap_nas_first_req_p->ue_identity.identity.gummei.mnc,
|
||||
MCC_MNC_TO_PLMNID(s1ap_nas_first_req_p->ue_identity.choice.gummei.mcc,
|
||||
s1ap_nas_first_req_p->ue_identity.choice.gummei.mnc,
|
||||
&initial_ue_message_p->gummei_id.pLMN_Identity);
|
||||
MME_GID_TO_OCTET_STRING(s1ap_nas_first_req_p->ue_identity.identity.gummei.mme_group_id,
|
||||
MME_GID_TO_OCTET_STRING(s1ap_nas_first_req_p->ue_identity.choice.gummei.mme_group_id,
|
||||
&initial_ue_message_p->gummei_id.mME_Group_ID);
|
||||
MME_CODE_TO_OCTET_STRING(s1ap_nas_first_req_p->ue_identity.identity.gummei.mme_code,
|
||||
MME_CODE_TO_OCTET_STRING(s1ap_nas_first_req_p->ue_identity.choice.gummei.mme_code,
|
||||
&initial_ue_message_p->gummei_id.mME_Code);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
#ifndef S1AP_MESSAGES_TYPES_H_
|
||||
#define S1AP_MESSAGES_TYPES_H_
|
||||
|
||||
//-------------------------------------------------------------------------------------------//
|
||||
// Defines to access message fields.
|
||||
|
||||
#define S1AP_NAS_FIRST_REQ(mSGpTR) (mSGpTR)->msg.s1ap_nas_first_req
|
||||
|
||||
//-------------------------------------------------------------------------------------------//
|
||||
|
||||
enum cell_type_e {
|
||||
CELL_MACRO_ENB,
|
||||
CELL_HOME_ENB
|
||||
@@ -58,14 +65,18 @@ typedef struct {
|
||||
uint32_t m_tmsi;
|
||||
} s_tmsi_t;
|
||||
|
||||
typedef enum {
|
||||
IDENTITY_PR_NOTHING,
|
||||
IDENTITY_PR_s_tmsi,
|
||||
IDENTITY_PR_gummei,
|
||||
} identity_t;
|
||||
|
||||
typedef struct {
|
||||
#define S_TMSI_PROVIDED 0x0
|
||||
#define GUMMEI_PROVIDED 0x1
|
||||
unsigned present:1;
|
||||
identity_t present;
|
||||
union {
|
||||
gummei_t gummei;
|
||||
s_tmsi_t s_tmsi;
|
||||
} identity;
|
||||
gummei_t gummei;
|
||||
} choice;
|
||||
} ue_identity_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -1009,7 +1009,7 @@ uint8_t do_RRCConnectionRequest(uint8_t *buffer,uint8_t *rv) {
|
||||
|
||||
}
|
||||
|
||||
uint8_t do_RRCConnectionSetupComplete(uint8_t *buffer) {
|
||||
uint8_t do_RRCConnectionSetupComplete(uint8_t *buffer, const int dedicatedInfoNASLength, const char *dedicatedInfoNAS) {
|
||||
|
||||
|
||||
asn_enc_rval_t enc_rval;
|
||||
@@ -1042,7 +1042,8 @@ uint8_t do_RRCConnectionSetupComplete(uint8_t *buffer) {
|
||||
rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.registeredMME->mmegi.bits_unused=0;
|
||||
*/
|
||||
memset(&rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.dedicatedInfoNAS,0,sizeof(OCTET_STRING_t));
|
||||
OCTET_STRING_fromBuf(&rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.dedicatedInfoNAS,"NAS Info",8);
|
||||
OCTET_STRING_fromBuf(&rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.dedicatedInfoNAS,
|
||||
dedicatedInfoNAS, dedicatedInfoNASLength);
|
||||
|
||||
/*
|
||||
rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.registeredMME->mmec.buf = calloc(1,1);
|
||||
|
||||
@@ -55,6 +55,8 @@
|
||||
|
||||
uint16_t get_adjacent_cell_id(uint8_t Mod_id,uint8_t index);
|
||||
|
||||
u8 get_adjacent_cell_mod_id(uint16_t phyCellId);
|
||||
|
||||
/**
|
||||
\brief Generate a default configuration for SIB1 (eNB).
|
||||
@param frame_parms Used to store some basic parameters from PHY configuration
|
||||
@@ -102,7 +104,7 @@ uint8_t do_RRCConnectionRequest(uint8_t *buffer,u8 *rv);
|
||||
/** \brief Generate an RRCConnectionSetupComplete UL-DCCH-Message (UE)
|
||||
@param buffer Pointer to PER-encoded ASN.1 description of UL-DCCH-Message PDU
|
||||
@returns Size of encoded bit stream in bytes*/
|
||||
uint8_t do_RRCConnectionSetupComplete(uint8_t *buffer);
|
||||
uint8_t do_RRCConnectionSetupComplete(uint8_t *buffer, const int dedicatedInfoNASLength, const char *dedicatedInfoNAS);
|
||||
|
||||
/** \brief Generate an RRCConnectionReconfigurationComplete UL-DCCH-Message (UE)
|
||||
@param buffer Pointer to PER-encoded ASN.1 description of UL-DCCH-Message PDU
|
||||
|
||||
@@ -155,6 +155,8 @@ typedef struct{
|
||||
//unsigned short UE_index_list[NUMBER_OF_UE_MAX];
|
||||
//L2_ID UE_list[NUMBER_OF_UE_MAX];
|
||||
u8 UE_list[NUMBER_OF_UE_MAX][5];
|
||||
InitialUE_Identity_t UE_Initialue_identity[NUMBER_OF_UE_MAX];
|
||||
EstablishmentCause_t UE_establishment_cause[NUMBER_OF_UE_MAX];
|
||||
}__attribute__ ((__packed__)) eNB_RRC_INFO;
|
||||
|
||||
typedef struct{
|
||||
|
||||
+91
-63
@@ -238,14 +238,44 @@ void rrc_ue_generate_RRCConnectionRequest(u8 Mod_id, u32 frame, u8 eNB_index){
|
||||
|
||||
mui_t rrc_mui=0;
|
||||
|
||||
/* NAS Attach request with IMSI */
|
||||
static const char nas_attach_req_imsi[] =
|
||||
{
|
||||
0x07, 0x41,
|
||||
/* EPS Mobile identity = IMSI */
|
||||
0x71, 0x08, 0x29, 0x80, 0x43, 0x21, 0x43, 0x65, 0x87,
|
||||
0xF9,
|
||||
/* End of EPS Mobile Identity */
|
||||
0x02, 0xE0, 0xE0, 0x00, 0x20, 0x02, 0x03,
|
||||
0xD0, 0x11, 0x27, 0x1A, 0x80, 0x80, 0x21, 0x10, 0x01, 0x00, 0x00,
|
||||
0x10, 0x81, 0x06, 0x00, 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x0A, 0x00, 0x52, 0x12, 0xF2,
|
||||
0x01, 0x27, 0x11,
|
||||
};
|
||||
|
||||
/* NAS Attach request with GUTI */
|
||||
static const char nas_attach_req_guti[] =
|
||||
{
|
||||
0x07, 0x41,
|
||||
/* EPS Mobile identity = IMSI */
|
||||
0x71, 0x0B, 0xF6, 0x12, 0xF2, 0x01, 0x80, 0x00, 0x01, 0xE0, 0x00,
|
||||
0xDA, 0x1F,
|
||||
/* End of EPS Mobile Identity */
|
||||
0x02, 0xE0, 0xE0, 0x00, 0x20, 0x02, 0x03,
|
||||
0xD0, 0x11, 0x27, 0x1A, 0x80, 0x80, 0x21, 0x10, 0x01, 0x00, 0x00,
|
||||
0x10, 0x81, 0x06, 0x00, 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x0A, 0x00, 0x52, 0x12, 0xF2,
|
||||
0x01, 0x27, 0x11,
|
||||
};
|
||||
|
||||
/*------------------------------------------------------------------------------*/
|
||||
void rrc_ue_generate_RRCConnectionSetupComplete(u8 Mod_id, u32 frame, u8 eNB_index){
|
||||
/*------------------------------------------------------------------------------*/
|
||||
|
||||
u8 buffer[32];
|
||||
u8 buffer[100];
|
||||
u8 size;
|
||||
|
||||
size = do_RRCConnectionSetupComplete(buffer);
|
||||
size = do_RRCConnectionSetupComplete(buffer, sizeof(nas_attach_req_guti), nas_attach_req_guti);
|
||||
|
||||
LOG_I(RRC,"[UE %d][RAPROC] Frame %d : Logical Channel UL-DCCH (SRB1), Generating RRCConnectionSetupComplete (bytes%d, eNB %d)\n",
|
||||
Mod_id,frame, size, eNB_index);
|
||||
@@ -750,7 +780,7 @@ rrc_ue_process_radioResourceConfigDedicated(u8 Mod_id,u32 frame, u8 eNB_index,
|
||||
kRRCint,
|
||||
NULL
|
||||
#ifdef Rel10
|
||||
,(MBMS_SessionInfoList_r9_t *)NULL
|
||||
,(PMCH_InfoList_r9_t *)NULL
|
||||
#endif
|
||||
);
|
||||
|
||||
@@ -760,7 +790,7 @@ rrc_ue_process_radioResourceConfigDedicated(u8 Mod_id,u32 frame, u8 eNB_index,
|
||||
(DRB_ToAddModList_t*)NULL,
|
||||
(DRB_ToReleaseList_t*)NULL
|
||||
#ifdef Rel10
|
||||
,(MBMS_SessionInfoList_r9_t *)NULL
|
||||
,(PMCH_InfoList_r9_t *)NULL
|
||||
#endif
|
||||
);
|
||||
|
||||
@@ -901,7 +931,7 @@ rrc_ue_process_radioResourceConfigDedicated(u8 Mod_id,u32 frame, u8 eNB_index,
|
||||
NULL,
|
||||
kUPenc
|
||||
#ifdef Rel10
|
||||
,(MBMS_SessionInfoList_r9_t *)NULL
|
||||
,(PMCH_InfoList_r9_t *)NULL
|
||||
#endif
|
||||
);
|
||||
|
||||
@@ -911,7 +941,7 @@ rrc_ue_process_radioResourceConfigDedicated(u8 Mod_id,u32 frame, u8 eNB_index,
|
||||
radioResourceConfigDedicated->drb_ToAddModList,
|
||||
(DRB_ToReleaseList_t*)NULL
|
||||
#ifdef Rel10
|
||||
,(MBMS_SessionInfoList_r9_t *)NULL
|
||||
,(PMCH_InfoList_r9_t *)NULL
|
||||
#endif
|
||||
);
|
||||
for (i=0;i<radioResourceConfigDedicated->drb_ToAddModList->list.count;i++) {
|
||||
@@ -1155,7 +1185,6 @@ void rrc_ue_process_mobilityControlInfo(u8 Mod_id,u32 frame, u8 eNB_index,stru
|
||||
|
||||
DRB_ToReleaseList_t* drb2release_list;
|
||||
DRB_Identity_t *lcid;
|
||||
u8 i;
|
||||
LOG_N(RRC,"Note: This function needs some updates\n");
|
||||
if(UE_rrc_inst[Mod_id].Info[eNB_index].T310_active == 1)
|
||||
UE_rrc_inst[Mod_id].Info[eNB_index].T310_active = 0;
|
||||
@@ -1897,6 +1926,60 @@ void ue_meas_filtering(u8 Mod_id,u32 frame,u8 eNB_index){
|
||||
}
|
||||
}
|
||||
|
||||
//Below routine implements Measurement Reporting procedure from 36.331 Section 5.5.5
|
||||
void rrc_ue_generate_MeasurementReport(u8 Mod_id, u32 frame,u8 eNB_index) {
|
||||
|
||||
u8 buffer[32], size;
|
||||
u8 i;
|
||||
u8 target_eNB_offset;
|
||||
MeasId_t measId;
|
||||
PhysCellId_t cellId, targetCellId;
|
||||
long rsrq_s,rsrp_t,rsrq_t;
|
||||
long rsrp_s, nElem, nElem1;
|
||||
float rsrp_filtered, rsrq_filtered;
|
||||
nElem = 100;
|
||||
nElem1 = 33;
|
||||
static u32 pframe=0;
|
||||
target_eNB_offset = UE_rrc_inst[Mod_id].Info[0].handoverTarget; // eNB_offset of target eNB: used to obtain the mod_id of target eNB
|
||||
|
||||
for (i=0;i<MAX_MEAS_ID;i++) {
|
||||
if (UE_rrc_inst[Mod_id].measReportList[0][i] != NULL) {
|
||||
measId = UE_rrc_inst[Mod_id].measReportList[0][i]->measId;
|
||||
|
||||
// Note: Values in the meas report have to be the mapped values...to implement binary search for LUT
|
||||
rsrp_filtered = UE_rrc_inst[Mod_id].rsrp_db_filtered[eNB_index];//nid_cell];
|
||||
rsrp_s = binary_search_float(RSRP_meas_mapping,nElem, rsrp_filtered); //mapped RSRP of serving cell
|
||||
|
||||
rsrq_filtered = UE_rrc_inst[Mod_id].rsrq_db_filtered[eNB_index];//nid_cell]; //RSRQ of serving cell
|
||||
rsrq_s = binary_search_float(RSRQ_meas_mapping,nElem1,rsrp_filtered);//mapped RSRQ of serving cell
|
||||
|
||||
LOG_D(RRC,"[UE %d] Frame %d: source eNB %d :rsrp_s: %d rsrq_s: %d tmp: %f tmp1: %f \n",
|
||||
Mod_id,frame,eNB_index, rsrp_s,rsrq_s,rsrp_filtered,rsrq_filtered);
|
||||
|
||||
rsrp_t = binary_search_float(RSRP_meas_mapping,nElem,UE_rrc_inst[Mod_id].rsrp_db_filtered[target_eNB_offset]); //RSRP of target cell
|
||||
rsrq_t = binary_search_float(RSRQ_meas_mapping,nElem1,UE_rrc_inst[Mod_id].rsrq_db_filtered[target_eNB_offset]); //RSRQ of target cell
|
||||
|
||||
// if (measFlag == 1) {
|
||||
cellId = get_adjacent_cell_id(Mod_id,eNB_index); //PhycellId of serving cell
|
||||
targetCellId = UE_rrc_inst[Mod_id].HandoverInfoUe.targetCellId ;//get_adjacent_cell_id(Mod_id,target_eNB_offset); //PhycellId of target cell
|
||||
|
||||
if (pframe!=frame){
|
||||
pframe=frame;
|
||||
size = do_MeasurementReport(buffer,measId,targetCellId,rsrp_s,rsrq_s,rsrp_t,rsrq_t);
|
||||
LOG_D(RRC,"[UE %d] Frame %d: Sending MeasReport: servingCell(%d) targetCell(%d) rsrp_s(%d) rsrq_s(%d) rsrp_t(%d) rsrq_t(%d) \n",
|
||||
Mod_id, frame, cellId,targetCellId,rsrp_s,rsrq_s,rsrp_t,rsrq_t);
|
||||
LOG_I(RRC,"[UE %d] Frame %d : Generating Measurement Report for eNB %d\n",Mod_id,frame,eNB_index);
|
||||
LOG_D(RLC,"[MSC_MSG][FRAME %05d][RRC_UE][MOD %02d][][--- PDCP_DATA_REQ/%d Bytes (MeasurementReport to eNB %d MUI %d) --->][PDCP][MOD %02d][RB %02d]\n",
|
||||
frame, Mod_id+NB_eNB_INST, size, eNB_index, rrc_mui, Mod_id+NB_eNB_INST, DCCH);
|
||||
pdcp_data_req(Mod_id+NB_eNB_INST,frame,0,DCCH,rrc_mui++,0,size,buffer,1);
|
||||
//LOG_D(RRC, "[UE %d] Frame %d Sending MeasReport (%d bytes) through DCCH%d to PDCP \n",Mod_id,frame, size, DCCH);
|
||||
}
|
||||
// measFlag = 0; //re-setting measFlag so that no more MeasReports are sent in this frame
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Measurement report triggering, described in 36.331 Section 5.5.4.1: called periodically
|
||||
void ue_measurement_report_triggering(u8 Mod_id, u32 frame,u8 eNB_index) {
|
||||
u8 i,j;
|
||||
@@ -2022,62 +2105,6 @@ u8 check_trigger_meas_event(u8 Mod_id,u32 frame, u8 eNB_index, u8 ue_cnx_index,
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Below routine implements Measurement Reporting procedure from 36.331 Section 5.5.5
|
||||
void rrc_ue_generate_MeasurementReport(u8 Mod_id, u32 frame,u8 eNB_index) {
|
||||
|
||||
u8 buffer[32], size;
|
||||
u8 i,j;
|
||||
u8 target_eNB_offset;
|
||||
MeasId_t measId;
|
||||
PhysCellId_t cellId, targetCellId;
|
||||
long rsrq_s,rsrp_t,rsrq_t;
|
||||
long rsrp_s, nElem, nElem1;
|
||||
float rsrp_filtered, rsrq_filtered;
|
||||
nElem = 100;
|
||||
nElem1 = 33;
|
||||
static u32 pframe=0;
|
||||
int nid_cell = mac_xface->lte_frame_parms->Nid_cell;
|
||||
target_eNB_offset = UE_rrc_inst[Mod_id].Info[0].handoverTarget; // eNB_offset of target eNB: used to obtain the mod_id of target eNB
|
||||
|
||||
for (i=0;i<MAX_MEAS_ID;i++) {
|
||||
if (UE_rrc_inst[Mod_id].measReportList[0][i] != NULL) {
|
||||
measId = UE_rrc_inst[Mod_id].measReportList[0][i]->measId;
|
||||
|
||||
// Note: Values in the meas report have to be the mapped values...to implement binary search for LUT
|
||||
rsrp_filtered = UE_rrc_inst[Mod_id].rsrp_db_filtered[eNB_index];//nid_cell];
|
||||
rsrp_s = binary_search_float(RSRP_meas_mapping,nElem, rsrp_filtered); //mapped RSRP of serving cell
|
||||
|
||||
rsrq_filtered = UE_rrc_inst[Mod_id].rsrq_db_filtered[eNB_index];//nid_cell]; //RSRQ of serving cell
|
||||
rsrq_s = binary_search_float(RSRQ_meas_mapping,nElem1,rsrp_filtered);//mapped RSRQ of serving cell
|
||||
|
||||
LOG_D(RRC,"[UE %d] Frame %d: source eNB %d :rsrp_s: %d rsrq_s: %d tmp: %f tmp1: %f \n",
|
||||
Mod_id,frame,eNB_index, rsrp_s,rsrq_s,rsrp_filtered,rsrq_filtered);
|
||||
|
||||
rsrp_t = binary_search_float(RSRP_meas_mapping,nElem,UE_rrc_inst[Mod_id].rsrp_db_filtered[target_eNB_offset]); //RSRP of target cell
|
||||
rsrq_t = binary_search_float(RSRQ_meas_mapping,nElem1,UE_rrc_inst[Mod_id].rsrq_db_filtered[target_eNB_offset]); //RSRQ of target cell
|
||||
|
||||
// if (measFlag == 1) {
|
||||
cellId = get_adjacent_cell_id(Mod_id,eNB_index); //PhycellId of serving cell
|
||||
targetCellId = UE_rrc_inst[Mod_id].HandoverInfoUe.targetCellId ;//get_adjacent_cell_id(Mod_id,target_eNB_offset); //PhycellId of target cell
|
||||
|
||||
if (pframe!=frame){
|
||||
pframe=frame;
|
||||
size = do_MeasurementReport(buffer,measId,targetCellId,rsrp_s,rsrq_s,rsrp_t,rsrq_t);
|
||||
LOG_D(RRC,"[UE %d] Frame %d: Sending MeasReport: servingCell(%d) targetCell(%d) rsrp_s(%d) rsrq_s(%d) rsrp_t(%d) rsrq_t(%d) \n",
|
||||
Mod_id, frame, cellId,targetCellId,rsrp_s,rsrq_s,rsrp_t,rsrq_t);
|
||||
LOG_I(RRC,"[UE %d] Frame %d : Generating Measurement Report for eNB %d\n",Mod_id,frame,eNB_index);
|
||||
LOG_D(RLC,"[MSC_MSG][FRAME %05d][RRC_UE][MOD %02d][][--- PDCP_DATA_REQ/%d Bytes (MeasurementReport to eNB %d MUI %d) --->][PDCP][MOD %02d][RB %02d]\n",
|
||||
frame, Mod_id+NB_eNB_INST, size, eNB_index, rrc_mui, Mod_id+NB_eNB_INST, DCCH);
|
||||
pdcp_data_req(Mod_id+NB_eNB_INST,frame,0,DCCH,rrc_mui++,0,size,(char*)buffer,1);
|
||||
//LOG_D(RRC, "[UE %d] Frame %d Sending MeasReport (%d bytes) through DCCH%d to PDCP \n",Mod_id,frame, size, DCCH);
|
||||
}
|
||||
// measFlag = 0; //re-setting measFlag so that no more MeasReports are sent in this frame
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef Rel10
|
||||
int decode_MCCH_Message(u8 Mod_id, u32 frame, u8 eNB_index, u8 *Sdu, u8 Sdu_len,u8 mbsfn_sync_area) {
|
||||
|
||||
@@ -2292,6 +2319,7 @@ void *rrc_ue_task(void *args_p) {
|
||||
}
|
||||
|
||||
free (msg_p);
|
||||
msg_p = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
+98
-46
@@ -39,6 +39,7 @@
|
||||
|
||||
#include "defs.h"
|
||||
#include "extern.h"
|
||||
#include "UTIL/assertions.h"
|
||||
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
|
||||
#include "LAYER2/RLC/rlc.h"
|
||||
#include "UTIL/LOG/log.h"
|
||||
@@ -567,42 +568,45 @@ openair_rrc_lite_eNB_init (u8 Mod_id)
|
||||
|
||||
|
||||
u8
|
||||
get_next_UE_index (u8 Mod_id, u8 * UE_identity)
|
||||
get_next_UE_index (u8 Mod_id, u8 *UE_identity)
|
||||
{
|
||||
|
||||
u8 i, first_index = 255, reg = 0;
|
||||
static const u8 null_identity[5] =
|
||||
{0, 0, 0, 0, 0};
|
||||
|
||||
for (i = 0; i < NUMBER_OF_UE_MAX; i++)
|
||||
{
|
||||
|
||||
|
||||
if ((first_index == 255) && (*(unsigned int *) eNB_rrc_inst[Mod_id].Info.UE_list[i] == 0x00000000))
|
||||
first_index = i; // save first free position
|
||||
|
||||
if ((eNB_rrc_inst[Mod_id].Info.UE_list[i][0] == UE_identity[0]) &&
|
||||
(eNB_rrc_inst[Mod_id].Info.UE_list[i][1] == UE_identity[1]) &&
|
||||
(eNB_rrc_inst[Mod_id].Info.UE_list[i][2] == UE_identity[2]) &&
|
||||
(eNB_rrc_inst[Mod_id].Info.UE_list[i][3] == UE_identity[3]) &&
|
||||
(eNB_rrc_inst[Mod_id].Info.UE_list[i][4] == UE_identity[4])) // UE_identity already registered
|
||||
reg = 1;
|
||||
DevCheck(Mod_id < NB_eNB_INST, Mod_id, NB_eNB_INST, 0);
|
||||
|
||||
for (i = 0; i < NUMBER_OF_UE_MAX; i++) {
|
||||
if ((first_index == 255)
|
||||
&& (memcmp (eNB_rrc_inst[Mod_id].Info.UE_list[i], null_identity, sizeof(eNB_rrc_inst[0].Info.UE_list[0])))
|
||||
== 0) {
|
||||
first_index = i; // save first free position
|
||||
}
|
||||
|
||||
if (reg == 0) {
|
||||
LOG_I (RRC, "Adding UE %d\n", first_index);
|
||||
return (first_index);
|
||||
if (memcmp (eNB_rrc_inst[Mod_id].Info.UE_list[i], UE_identity, sizeof(eNB_rrc_inst[0].Info.UE_list[0])) == 0) {
|
||||
// UE_identity already registered
|
||||
reg = 1;
|
||||
}
|
||||
else
|
||||
}
|
||||
|
||||
if (reg == 0) {
|
||||
LOG_I(RRC, "Adding UE %d\n", first_index);
|
||||
return (first_index);
|
||||
}
|
||||
else {
|
||||
return (255);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rrc_remove_UE (u8 Mod_id, u8 UE_id)
|
||||
{
|
||||
DevCheck(Mod_id < NB_eNB_INST, Mod_id, UE_id, NB_eNB_INST);
|
||||
DevCheck(UE_id < NUMBER_OF_UE_MAX, Mod_id, UE_id, NUMBER_OF_UE_MAX);
|
||||
|
||||
LOG_I (RRC, "Removing UE %d\n", UE_id);
|
||||
eNB_rrc_inst[Mod_id].Info.Status[UE_id] = RRC_IDLE;
|
||||
*(unsigned int *) eNB_rrc_inst[Mod_id].Info.UE_list[UE_id] = 0x00000000;
|
||||
memset(eNB_rrc_inst[Mod_id].Info.UE_list[UE_id], 0, sizeof(eNB_rrc_inst[0].Info.UE_list[0]));
|
||||
}
|
||||
|
||||
|
||||
@@ -957,6 +961,8 @@ for (i = 0; i < 8; i++)
|
||||
|
||||
if (UE_index != 255)
|
||||
{
|
||||
eNB_rrc_inst[Mod_id].Info.UE_Initialue_identity[UE_index] = rrcConnectionRequest->ue_Identity;
|
||||
eNB_rrc_inst[Mod_id].Info.UE_establishment_cause[UE_index] = rrcConnectionRequest->establishmentCause;
|
||||
|
||||
// memcpy(&Rrc_xface->UE_id[Mod_id][UE_index],(u8 *)rrcConnectionRequest->ue_Identity.choice.randomValue.buf,5);
|
||||
memcpy (&eNB_rrc_inst[Mod_id].Info.UE_list[UE_index],
|
||||
@@ -1029,7 +1035,7 @@ for (i = 0; i < 8; i++)
|
||||
(DRB_ToAddModList_t *) NULL,
|
||||
(DRB_ToReleaseList_t *) NULL
|
||||
#ifdef Rel10
|
||||
, (MBMS_SessionInfoList_r9_t *) NULL
|
||||
, (PMCH_InfoList_r9_t *) NULL
|
||||
#endif
|
||||
);
|
||||
//LOG_D(RRC,"[eNB %d] RLC AM allocation index@0 is %d\n",Mod_id,rlc[Mod_id].m_rlc_am_array[0].allocation);
|
||||
@@ -1074,23 +1080,64 @@ rrc_eNB_process_RRCConnectionSetupComplete (u8 Mod_id,
|
||||
RRCConnectionSetupComplete_r8_IEs_t
|
||||
* rrcConnectionSetupComplete)
|
||||
{
|
||||
|
||||
LOG_I (RRC, "[eNB %d][RAPROC] Frame %d : Logical Channel UL-DCCH, ""processing RRCConnectionSetupComplete from UE %d\n",
|
||||
Mod_id, frame, UE_index);
|
||||
|
||||
// Forward message to S1AP layer
|
||||
#if defined(ENABLE_USE_MME) && !defined(ENABLE_ITTI)
|
||||
#if defined(ENABLE_USE_MME)
|
||||
if (oai_emulation.info.mme_enabled == 1)
|
||||
# if defined(ENABLE_ITTI)
|
||||
{
|
||||
MessageDef *message_p;
|
||||
|
||||
message_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_NAS_FIRST_REQ);
|
||||
S1AP_NAS_FIRST_REQ (message_p).rnti = eNB_mac_inst[Mod_id].UE_template[UE_index].rnti; // TODO check if this is the correct id to use
|
||||
|
||||
DevCheck(eNB_rrc_inst[Mod_id].Info.UE_establishment_cause[UE_index] < RRC_CAUSE_LAST, eNB_rrc_inst[Mod_id].Info.UE_establishment_cause[UE_index], RRC_CAUSE_LAST, Mod_id);
|
||||
S1AP_NAS_FIRST_REQ (message_p).establishment_cause = eNB_rrc_inst[Mod_id].Info.UE_establishment_cause[UE_index];
|
||||
|
||||
S1AP_NAS_FIRST_REQ (message_p).nas_pdu.buffer = rrcConnectionSetupComplete->dedicatedInfoNAS.buf;
|
||||
S1AP_NAS_FIRST_REQ (message_p).nas_pdu.length = rrcConnectionSetupComplete->dedicatedInfoNAS.size;
|
||||
if (rrcConnectionSetupComplete->registeredMME != NULL)
|
||||
{
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.present = IDENTITY_PR_gummei;
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.choice.gummei.mcc = 0; // TODO decode BIT STREAM
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.choice.gummei.mnc = 0; // TODO decode BIT STREAM
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.choice.gummei.mme_code = 0; // TODO decode BIT STREAM
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.choice.gummei.mme_group_id = 0; // TODO decode BIT STREAM
|
||||
}
|
||||
else
|
||||
{
|
||||
if (eNB_rrc_inst[Mod_id].Info.UE_Initialue_identity[UE_index].present == InitialUE_Identity_PR_s_TMSI)
|
||||
{
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.present = IDENTITY_PR_s_tmsi;
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.choice.s_tmsi.mme_code = 0; // TODO decode BIT STREAM
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.choice.s_tmsi.m_tmsi = 0; // TODO decode BIT STREAM
|
||||
}
|
||||
else
|
||||
{
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.present = IDENTITY_PR_NOTHING;
|
||||
}
|
||||
}
|
||||
|
||||
itti_send_msg_to_task (TASK_S1AP, Mod_id, message_p);
|
||||
}
|
||||
# else
|
||||
{
|
||||
s1ap_eNB_new_data_request (Mod_id, UE_index,
|
||||
rrcConnectionSetupComplete->dedicatedInfoNAS.
|
||||
buf,
|
||||
rrcConnectionSetupComplete->dedicatedInfoNAS.
|
||||
size);
|
||||
}
|
||||
else
|
||||
# endif
|
||||
#endif
|
||||
|
||||
{
|
||||
rrc_eNB_generate_SecurityModeCommand (Mod_id, frame, UE_index);
|
||||
//rrc_eNB_generate_UECapabilityEnquiry(Mod_id,frame,UE_index);
|
||||
// rrc_eNB_generate_UECapabilityEnquiry(Mod_id,frame,UE_index);
|
||||
}
|
||||
}
|
||||
|
||||
mui_t rrc_eNB_mui = 0;
|
||||
@@ -1578,7 +1625,7 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration (u8 Mod_id, u32 frame,
|
||||
//memcpy((void *)rrc_inst->handover_info[UE_index]->as_config.sourceRadioResourceConfig.srb_ToAddModList,(void *)SRB_list,sizeof(SRB_ToAddModList_t));
|
||||
rrc_inst->handover_info[UE_index]->as_config.sourceRadioResourceConfig.srb_ToAddModList = SRB_configList2;
|
||||
//memcpy((void *)rrc_inst->handover_info[UE_index]->as_config.sourceRadioResourceConfig.drb_ToAddModList,(void *)DRB_list,sizeof(DRB_ToAddModList_t));
|
||||
rrc_inst->handover_info[UE_index]->as_config.sourceRadioResourceConfig.drb_ToAddModList = DRB_configList;
|
||||
rrc_inst->handover_info[UE_index]->as_config.sourceRadioResourceConfig.drb_ToAddModList = *DRB_configList;
|
||||
rrc_inst->handover_info[UE_index]->as_config.sourceRadioResourceConfig.drb_ToReleaseList = NULL;
|
||||
rrc_inst->handover_info[UE_index]->as_config.sourceRadioResourceConfig.mac_MainConfig = CALLOC(1, sizeof(*rrc_inst->handover_info[UE_index]->as_config.sourceRadioResourceConfig.mac_MainConfig));
|
||||
memcpy((void *)rrc_inst->handover_info[UE_index]->as_config.sourceRadioResourceConfig.mac_MainConfig,
|
||||
@@ -1666,14 +1713,15 @@ rrc_eNB_process_MeasurementReport (u8 Mod_id, u32 frame, u16 UE_index,
|
||||
}
|
||||
void
|
||||
rrc_eNB_generate_HandoverPreparationInformation (u8 Mod_id, u32 frame, u8 UE_index, PhysCellId_t targetPhyId) {
|
||||
|
||||
u8 buffer[100];
|
||||
u8 size,UE_id_target;
|
||||
u8 UE_id_target;
|
||||
u8 mod_id_target = get_adjacent_cell_mod_id(targetPhyId);
|
||||
HANDOVER_INFO *handoverInfo = CALLOC(1,sizeof(*handoverInfo));
|
||||
/*
|
||||
u8 buffer[100];
|
||||
u8 size;
|
||||
struct PhysicalConfigDedicated **physicalConfigDedicated = &eNB_rrc_inst[Mod_id].physicalConfigDedicated[UE_index];
|
||||
RadioResourceConfigDedicated_t *radioResourceConfigDedicated = CALLOC(1,sizeof(RadioResourceConfigDedicated_t));
|
||||
|
||||
*/
|
||||
|
||||
handoverInfo->as_config.antennaInfoCommon.antennaPortsCount = 0; //Not used 0- but check value
|
||||
handoverInfo->as_config.sourceDl_CarrierFreq = 36090; //Verify!
|
||||
@@ -1736,6 +1784,16 @@ rrc_eNB_generate_HandoverPreparationInformation (u8 Mod_id, u32 frame, u8 UE_ind
|
||||
LOG_E(RRC,"\nError in obtaining Module ID of target eNB for handover \n");
|
||||
}
|
||||
|
||||
void rrc_eNB_process_handoverPreparationInformation(u8 Mod_id,u32 frame, u16 UE_index) {
|
||||
|
||||
LOG_I(RRC,"[eNB %d] Frame %d : Logical Channel UL-DCCH, processing RRCHandoverPreparationInformation, sending RRCConnectionReconfiguration to UE %d \n",Mod_id,frame,UE_index);
|
||||
|
||||
|
||||
//eNB_rrc_inst[Mod_id].Info.UE_list[UE_index]
|
||||
rrc_eNB_generate_RRCConnectionReconfiguration_handover(Mod_id,frame,UE_index,NULL,0);
|
||||
|
||||
}
|
||||
|
||||
void check_handovers(u8 Mod_id, u32 frame) {
|
||||
u8 i;
|
||||
for (i=0;i<NUMBER_OF_UE_MAX;i++) {
|
||||
@@ -1756,22 +1814,13 @@ void check_handovers(u8 Mod_id, u32 frame) {
|
||||
(i* NB_RB_MAX)+DCCH,
|
||||
rrc_eNB_mui++,0,
|
||||
eNB_rrc_inst[Mod_id].handover_info[i]->size,
|
||||
(char*)eNB_rrc_inst[Mod_id].handover_info[i]->buf,1);
|
||||
eNB_rrc_inst[Mod_id].handover_info[i]->buf,1);
|
||||
eNB_rrc_inst[Mod_id].handover_info[i]->ho_complete = 0xF2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rrc_eNB_process_handoverPreparationInformation(u8 Mod_id,u32 frame, u16 UE_index) {
|
||||
|
||||
LOG_I(RRC,"[eNB %d] Frame %d : Logical Channel UL-DCCH, processing RRCHandoverPreparationInformation, sending RRCConnectionReconfiguration to UE %d \n",Mod_id,frame,UE_index);
|
||||
|
||||
|
||||
//eNB_rrc_inst[Mod_id].Info.UE_list[UE_index]
|
||||
rrc_eNB_generate_RRCConnectionReconfiguration_handover(Mod_id,frame,UE_index,NULL,0);
|
||||
|
||||
}
|
||||
// 5.3.5.4 RRCConnectionReconfiguration including the mobilityControlInfo to prepare the UE handover
|
||||
void
|
||||
rrc_eNB_generate_RRCConnectionReconfiguration_handover (u8 Mod_id, u32 frame,u16 UE_index,u8 *nas_pdu,u32 nas_length) {
|
||||
@@ -1790,7 +1839,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover (u8 Mod_id, u32 frame,u16
|
||||
struct SRB_ToAddMod__rlc_Config *SRB2_rlc_config;
|
||||
struct SRB_ToAddMod__logicalChannelConfig *SRB2_lchan_config;
|
||||
struct LogicalChannelConfig__ul_SpecificParameters *SRB2_ul_SpecificParameters;
|
||||
LogicalChannelConfig_t *SRB1_logicalChannelConfig;
|
||||
LogicalChannelConfig_t *SRB1_logicalChannelConfig = NULL;
|
||||
SRB_ToAddModList_t *SRB_configList = rrc_inst->SRB_configList[UE_index]; // not used in this context: may be removed
|
||||
SRB_ToAddModList_t *SRB_configList2;
|
||||
|
||||
@@ -1800,7 +1849,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover (u8 Mod_id, u32 frame,u16
|
||||
struct PDCP_Config__rlc_UM *PDCP_rlc_UM;
|
||||
struct LogicalChannelConfig *DRB_lchan_config;
|
||||
struct LogicalChannelConfig__ul_SpecificParameters *DRB_ul_SpecificParameters;
|
||||
DRB_ToAddModList_t **DRB_configList = &rrc_inst->DRB_configList[UE_index];
|
||||
// DRB_ToAddModList_t **DRB_configList = &rrc_inst->DRB_configList[UE_index];
|
||||
DRB_ToAddModList_t *DRB_configList2;
|
||||
|
||||
MAC_MainConfig_t *mac_MainConfig;
|
||||
@@ -1813,7 +1862,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover (u8 Mod_id, u32 frame,u16
|
||||
MeasIdToAddMod_t *MeasId0, *MeasId1, *MeasId2, *MeasId3, *MeasId4, *MeasId5;
|
||||
QuantityConfig_t *quantityConfig;
|
||||
MobilityControlInfo_t *mobilityInfo;
|
||||
HandoverCommand_t handoverCommand;
|
||||
// HandoverCommand_t handoverCommand;
|
||||
u8 sourceModId = get_adjacent_cell_mod_id(rrc_inst->handover_info[UE_index]->as_context.reestablishmentInfo->sourcePhysCellId);
|
||||
#if Rel10
|
||||
long *sr_ProhibitTimer_r9;
|
||||
@@ -1822,7 +1871,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover (u8 Mod_id, u32 frame,u16
|
||||
long *logicalchannelgroup, *logicalchannelgroup_drb;
|
||||
long *maxHARQ_Tx, *periodicBSR_Timer;
|
||||
|
||||
RSRP_Range_t *rsrp;
|
||||
// RSRP_Range_t *rsrp;
|
||||
struct MeasConfig__speedStatePars *Sparams;
|
||||
CellsToAddMod_t *CellToAdd;
|
||||
CellsToAddModList_t *CellsToAddModList;
|
||||
@@ -2388,7 +2437,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover (u8 Mod_id, u32 frame,u16
|
||||
|
||||
mobilityInfo = CALLOC(1,sizeof(*mobilityInfo));
|
||||
memset((void *)mobilityInfo,0,sizeof(*mobilityInfo));
|
||||
mobilityInfo->targetPhysCellId = (PhysCellId_t) two_tier_hexagonal_cellIds[Mod_id, rrc_inst->handover_info[UE_index]->modid_t];
|
||||
mobilityInfo->targetPhysCellId = (PhysCellId_t) two_tier_hexagonal_cellIds[rrc_inst->handover_info[UE_index]->modid_t];
|
||||
LOG_D(RRC,"[eNB %d] Frame %d: handover preparation: targetPhysCellId: %d mod_id: %d UE_index: %d \n",
|
||||
Mod_id,frame, mobilityInfo->targetPhysCellId,Mod_id,UE_index);
|
||||
|
||||
@@ -2516,7 +2565,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover (u8 Mod_id, u32 frame,u16
|
||||
(DRB_ToAddModList_t *) NULL,
|
||||
(DRB_ToReleaseList_t *) NULL
|
||||
#ifdef Rel10
|
||||
, (MBMS_SessionInfoList_r9_t *) NULL
|
||||
, (PMCH_InfoList_r9_t *) NULL
|
||||
#endif
|
||||
);
|
||||
|
||||
@@ -2580,10 +2629,12 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover (u8 Mod_id, u32 frame,u16
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
handoverCommand.criticalExtensions.present = HandoverCommand__criticalExtensions_PR_c1;
|
||||
handoverCommand.criticalExtensions.choice.c1.present = HandoverCommand__criticalExtensions__c1_PR_handoverCommand_r8;
|
||||
handoverCommand.criticalExtensions.choice.c1.choice.handoverCommand_r8.handoverCommandMessage.buf = buffer;
|
||||
handoverCommand.criticalExtensions.choice.c1.choice.handoverCommand_r8.handoverCommandMessage.size = size;
|
||||
*/
|
||||
|
||||
if (sourceModId != 0xFF) {
|
||||
memcpy(eNB_rrc_inst[sourceModId].handover_info[eNB_rrc_inst[Mod_id].handover_info[UE_index]->ueid_s]->buf,
|
||||
@@ -2653,7 +2704,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete (u8 Mod_id, u32 frame,
|
||||
SRB_configList,
|
||||
DRB_configList, (DRB_ToReleaseList_t *) NULL
|
||||
#ifdef Rel10
|
||||
, (MBMS_SessionInfoList_r9_t *) NULL
|
||||
, (PMCH_InfoList_r9_t *) NULL
|
||||
#endif
|
||||
);
|
||||
|
||||
@@ -2972,6 +3023,7 @@ void *rrc_enb_task(void *args_p) {
|
||||
}
|
||||
|
||||
free (msg_p);
|
||||
msg_p = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user