Commit 33cd8caf authored by Eurecom's avatar Eurecom

after merge with abs

parent 248fdfbd
......@@ -109,11 +109,11 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue,
// use OFDM symbol from within 1/8th of the CP to avoid ISI
rx_offset -= nb_prefix_samples / 8;
#ifdef DEBUG_FEP
//#ifdef DEBUG_FEP
// if (ue->frame <100)
printf("slot_fep: slot %d, symbol %d, nb_prefix_samples %u, nb_prefix_samples0 %u, rx_offset %u\n",
Ns, symbol, nb_prefix_samples, nb_prefix_samples0, rx_offset);
#endif
LOG_D(PHY,"slot_fep: slot %d, symbol %d, nb_prefix_samples %u, nb_prefix_samples0 %u, rx_offset %u energy %d\n",
Ns, symbol, nb_prefix_samples, nb_prefix_samples0, rx_offset, dB_fixed(signal_energy(&common_vars->rxdata[0][rx_offset],frame_parms->ofdm_symbol_size)));
//#endif
for (unsigned char aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
memset(&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],0,frame_parms->ofdm_symbol_size*sizeof(int32_t));
......
......@@ -97,12 +97,12 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
cset_start_symb = pdcch_pdu_rel15->StartSymbolIndex;
cset_nsymb = pdcch_pdu_rel15->DurationSymbols;
dci_idx = 0;
LOG_I(PHY, "Coreset rb_offset %d, nb_rb %d BWP Start %d\n",rb_offset,n_rb,pdcch_pdu_rel15->BWPStart);
LOG_I(PHY, "Coreset starting subcarrier %d on symbol %d (%d symbols)\n", cset_start_sc, cset_start_symb, cset_nsymb);
LOG_D(PHY, "Coreset rb_offset %d, nb_rb %d BWP Start %d\n",rb_offset,n_rb,pdcch_pdu_rel15->BWPStart);
LOG_D(PHY, "Coreset starting subcarrier %d on symbol %d (%d symbols)\n", cset_start_sc, cset_start_symb, cset_nsymb);
// DMRS length is per OFDM symbol
uint32_t dmrs_length = n_rb*6; //2(QPSK)*3(per RB)*6(REG per CCE)
uint32_t encoded_length = dci_pdu->AggregationLevel*108; //2(QPSK)*9(per RB)*6(REG per CCE)
/*if (dci_pdu->RNTI!=0xFFFF)*/ LOG_I(PHY, "DL_DCI : rb_offset %d, nb_rb %d, DMRS length per symbol %d\t DCI encoded length %d (precoder_granularity %d,reg_mapping %d),Scrambling_Id %d,ScramblingRNTI %x,PayloadSizeBits %d\n",
if (dci_pdu->RNTI!=0xFFFF) LOG_D(PHY, "DL_DCI : rb_offset %d, nb_rb %d, DMRS length per symbol %d\t DCI encoded length %d (precoder_granularity %d,reg_mapping %d),Scrambling_Id %d,ScramblingRNTI %x,PayloadSizeBits %d\n",
rb_offset, n_rb,dmrs_length, encoded_length,pdcch_pdu_rel15->precoderGranularity,pdcch_pdu_rel15->CceRegMappingType,
dci_pdu->ScramblingId,dci_pdu->ScramblingRNTI,dci_pdu->PayloadSizeBits);
dmrs_length += rb_offset*6; // To accommodate more DMRS symbols in case of rb offset
......
......@@ -397,7 +397,7 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
uci_pdu->harq->harq_confidence_level = no_conf ? 1 : 0;
uci_pdu->harq->harq_list = (nfapi_nr_harq_t*)malloc(1);
uci_pdu->harq->harq_list[0].harq_value = index&0x01;
LOG_D(PHY, "[DLSCH/PDSCH/PUCCH] %d.%d HARQ value %d with confidence level (0 is good, 1 is bad) %d xrt_mag %d n0 %d (%d,%d) pucch0_thres %d, cqi %d, SNRtimes10 %d\n",
LOG_I(PHY, "[DLSCH/PDSCH/PUCCH] %d.%d HARQ value %d with confidence level (0 is good, 1 is bad) %d xrt_mag %d n0 %d (%d,%d) pucch0_thres %d, cqi %d, SNRtimes10 %d\n",
frame,slot,uci_pdu->harq->harq_list[0].harq_value,uci_pdu->harq->harq_confidence_level,xrtmag_dBtimes10,max_n0,uci_stats->pucch0_n00,uci_stats->pucch0_n01,uci_stats->pucch0_thres,cqi,SNRtimes10);
if (pucch_pdu->sr_flag == 1) {
......
......@@ -823,6 +823,14 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
LOG_D(PHY,"we end nr_pdcch_unscrambling()\n");
LOG_D(PHY,"Ending nr_rx_pdcch() function\n");
if (rel15->rnti!=0xFFFF && slot == 7) {
LOG_M("pdcch_rxdataF0.m","rxdataF0",common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[0],2048*14,1,1);
LOG_M("pdcch_chestF_ext0.m","rxdataF_comp0",pdcch_vars->dl_ch_estimates_ext[0],n_rb*12,1,1);
LOG_M("pdcch_rxdataF_ext0.m","rxdataF_ext0",pdcch_vars->rxdataF_ext[0],n_rb*12,1,1);
LOG_M("pdcch_rxdataF_comp0.m","rxdataF_comp0",pdcch_vars->rxdataF_comp[0],n_rb*12,1,1);
LOG_M("slot7rxsig.m","s7rxs",&ue->common_vars.rxdata[0][frame_parms->get_samples_slot_timestamp(slot,frame_parms,0)],30720,1,1);
exit(-1);
}
return (0);
}
......
......@@ -164,7 +164,7 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
gNB->Mod_id,frame,slot,pdcch_pdu_id,ul_pdcch_pdu_id);
if (pdcch_pdu_id >= 0 || ul_pdcch_pdu_id >= 0) {
LOG_I(PHY, "[gNB %d] Frame %d slot %d Calling nr_generate_dci_top (number of UL/DL DCI %d/%d)\n",
LOG_D(PHY, "[gNB %d] Frame %d slot %d Calling nr_generate_dci_top (number of UL/DL DCI %d/%d)\n",
gNB->Mod_id, frame, slot,
gNB->ul_pdcch_pdu[ul_pdcch_pdu_id].pdcch_pdu.pdcch_pdu.pdcch_pdu_rel15.numDlDci,
gNB->pdcch_pdu[pdcch_pdu_id].pdcch_pdu.pdcch_pdu_rel15.numDlDci);
......
......@@ -1682,7 +1682,9 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_IN);
LOG_D(PHY," ****** start RX-Chain for Frame.Slot %d.%d ****** \n", frame_rx%1024, nr_slot_rx);
LOG_D(PHY," ****** start RX-Chain for Frame.Slot %d.%d (energy %d dB)****** \n",
frame_rx%1024, nr_slot_rx,
dB_fixed(signal_energy(ue->common_vars.common_vars_rx_data_per_thread[proc->thread_id].rxdataF[0],2048*14)));
/*
uint8_t next1_thread_id = proc->thread_id== (RX_NB_TH-1) ? 0:(proc->thread_id+1);
......
......@@ -412,6 +412,7 @@ typedef struct NRRrcConfigurationReq_s {
int sib1_tda;
int pdsch_AntennaPorts;
int pusch_AntennaPorts;
int minRXTXTIMEpdsch;
int do_CSIRS;
int pusch_TargetSNRx10;
int pucch_TargetSNRx10;
......
......@@ -1021,6 +1021,8 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) {
NRRRC_CONFIGURATION_REQ (msg_p).pdsch_AntennaPorts = *GNBParamList.paramarray[i][GNB_PDSCH_ANTENNAPORTS_IDX].iptr;
printf("pusch_AntennaPorts %d\n",*GNBParamList.paramarray[i][GNB_PUSCH_ANTENNAPORTS_IDX].iptr);
NRRRC_CONFIGURATION_REQ (msg_p).pusch_AntennaPorts = *GNBParamList.paramarray[i][GNB_PUSCH_ANTENNAPORTS_IDX].iptr;
printf("minTXRXTIMEpdsch %d\n",*GNBParamList.paramarray[i][GNB_MINRXTXTIMEPDSCH_IDX].iptr);
NRRRC_CONFIGURATION_REQ (msg_p).minRXTXTIMEpdsch = *GNBParamList.paramarray[i][GNB_MINRXTXTIMEPDSCH_IDX].iptr;
NRRRC_CONFIGURATION_REQ (msg_p).sib1_tda = *GNBParamList.paramarray[i][GNB_SIB1_TDA_IDX].iptr;
printf("Do CSI-RS %d\n",*GNBParamList.paramarray[i][GNB_DO_CSIRS_IDX].iptr);
NRRRC_CONFIGURATION_REQ (msg_p).do_CSIRS = *GNBParamList.paramarray[i][GNB_DO_CSIRS_IDX].iptr;
......
......@@ -119,6 +119,7 @@ typedef enum {
#define GNB_CONFIG_STRING_SIB1TDA "sib1_tda"
#define GNB_CONFIG_STRING_DOCSIRS "do_CSIRS"
#define GNB_CONFIG_STRING_NRCELLID "nr_cellid"
#define GNB_CONFIG_STRING_MINRXTXTIMEPDSCH "min_rxtxtime_pdsch"
/*-----------------------------------------------------------------------------------------------------------------------------------------*/
/* cell configuration parameters */
......@@ -145,6 +146,7 @@ typedef enum {
{GNB_CONFIG_STRING_SIB1TDA, NULL, 0, iptr:NULL, defintval:0, TYPE_INT, 0}, \
{GNB_CONFIG_STRING_DOCSIRS, NULL, 0, iptr:NULL, defintval:0, TYPE_INT, 0}, \
{GNB_CONFIG_STRING_NRCELLID, NULL, 0, u64ptr:NULL, defint64val:1, TYPE_UINT64, 0}, \
{GNB_CONFIG_STRING_MINRXTXTIMEPDSCH, NULL, 0, iptr:NULL, defintval:2, TYPE_INT, 0} \
}
#define GNB_GNB_ID_IDX 0
......@@ -167,6 +169,7 @@ typedef enum {
#define GNB_SIB1_TDA_IDX 17
#define GNB_DO_CSIRS_IDX 18
#define GNB_NRCELLID_IDX 19
#define GNB_MINRXTXTIMEPDSCH_IDX 20
#define TRACKING_AREA_CODE_OKRANGE {0x0001,0xFFFD}
#define GNBPARAMS_CHECK { \
......
......@@ -743,7 +743,7 @@ void nr_fr1_dlsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t
if (UE_info->num_UEs == 0)
return;
if (slot!=11) return;
if (slot!=1) return;
const int CC_id = 0;
......@@ -886,10 +886,11 @@ void nr_schedule_ue_spec(module_id_t module_id,
harq->is_waiting = true;
UE_info->mac_stats[UE_id].dlsch_rounds[harq->round]++;
LOG_D(NR_MAC,
"%4d.%2d [DLSCH/PDSCH/PUCCH] RNTI %04x start %3d RBs %3d startSymbol %2d nb_symbol %2d dmrspos %x MCS %2d TBS %4d HARQ PID %2d round %d RV %d NDI %d dl_data_to_ULACK %d (%d.%d) TPC %d\n",
LOG_I(NR_MAC,
"%4d.%2d [DLSCH/PDSCH/PUCCH] UE %d RNTI %04x start %3d RBs %3d startSymbol %2d nb_symbol %2d dmrspos %x MCS %2d TBS %4d HARQ PID %2d round %d RV %d NDI %d dl_data_to_ULACK %d (%d.%d) TPC %d\n",
frame,
slot,
UE_id,
rnti,
sched_pdsch->rbStart,
sched_pdsch->rbSize,
......@@ -925,7 +926,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu));
dl_req->nPDUs += 1;
pdcch_pdu = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15;
LOG_D(NR_MAC,"Trying to configure DL pdcch for bwp %d, cs %d\n",bwpid,coresetid);
LOG_I(NR_MAC,"Trying to configure DL pdcch for UE %d, bwp %d, cs %d\n",UE_id,bwpid,coresetid);
NR_SearchSpace_t *ss = (bwp||bwpd) ? sched_ctrl->search_space:gNB_mac->sched_ctrlCommon->search_space;
NR_ControlResourceSet_t *coreset = (bwp||bwpd)? sched_ctrl->coreset:gNB_mac->sched_ctrlCommon->coreset;
nr_configure_pdcch(pdcch_pdu, ss, coreset, scc, genericParameters, NULL);
......
......@@ -702,7 +702,7 @@ void nr_configure_pdcch(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu,
sps = bwp->cyclicPrefix == NULL ? 14 : 12;
}
else {
AssertFatal(type0_PDCCH_CSS_config!=NULL,"type0_PDCCH_CSS_config is null\n");
AssertFatal(type0_PDCCH_CSS_config!=NULL,"type0_PDCCH_CSS_config is null,bwp %p\n",bwp);
pdcch_pdu->BWPSize = type0_PDCCH_CSS_config->num_rbs;
pdcch_pdu->BWPStart = type0_PDCCH_CSS_config->cset_start_rb;
pdcch_pdu->SubcarrierSpacing = type0_PDCCH_CSS_config->scs_pdcch;
......
......@@ -325,7 +325,7 @@ int8_t nr_mac_rrc_data_ind(const module_id_t module_idP,
NR_ServingCellConfigCommon_t *scc=RC.nrrrc[module_idP]->carrier.servingcellconfigcommon;
uint8_t sdu2[100];
memset(&cellGroupConfig,0,sizeof(cellGroupConfig));
fill_initial_cellGroupConfig(rntiP,&cellGroupConfig,scc);
fill_initial_cellGroupConfig(rntiP,&cellGroupConfig,scc,&RC.nrrrc[module_idP]->carrier);
asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig,
NULL,
(void *)&cellGroupConfig,
......
......@@ -437,7 +437,7 @@ uint8_t do_SIB1_NR(rrc_gNB_carrier_data_t *carrier,
LOG_I(NR_RRC,"SIB1 freq: absoluteFrequencySSB %ld, absoluteFrequencyPointA %ld\n",
*configuration->scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB,
configuration->scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA);
LOG_I(NR_RRC,"SIB1 freq: absolute_diff %d, %d*(absolute_diff/(12*%d) - 10) %d\n",absolute_diff,scs_scaling2,scs_scaling,sib1->servingCellConfigCommon->downlinkConfigCommon.frequencyInfoDL.offsetToPointA);
LOG_I(NR_RRC,"SIB1 freq: absolute_diff %d, %d*(absolute_diff/(12*%d) - 10) %d\n",absolute_diff,scs_scaling2,scs_scaling,(int)sib1->servingCellConfigCommon->downlinkConfigCommon.frequencyInfoDL.offsetToPointA);
for(int i = 0; i< configuration->scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.count; i++) {
ASN_SEQUENCE_ADD(&sib1->servingCellConfigCommon->downlinkConfigCommon.frequencyInfoDL.scs_SpecificCarrierList.list,configuration->scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[i]);
......@@ -997,7 +997,8 @@ uint8_t do_RRCReject(uint8_t Mod_id,
void fill_initial_SpCellConfig(rnti_t rnti,
NR_SpCellConfig_t *SpCellConfig,
NR_ServingCellConfigCommon_t *scc) {
NR_ServingCellConfigCommon_t *scc,
rrc_gNB_carrier_data_t *carrier) {
SpCellConfig->servCellIndex = NULL;
SpCellConfig->reconfigurationWithSync = NULL;
......@@ -1193,7 +1194,9 @@ void fill_initial_SpCellConfig(rnti_t rnti,
long *delay[8];
for (int i=0;i<8;i++) {
delay[i] = calloc(1,sizeof(*delay[i]));
*delay[i] = (i+2/*+4*/);
AssertFatal(carrier->minRXTXTIMEpdsch >=2 && carrier->minRXTXTIMEpdsch <7,
"check minRXTXTIMEpdsch %d\n",carrier->minRXTXTIMEpdsch);
*delay[i] = (i+carrier->minRXTXTIMEpdsch);
ASN_SEQUENCE_ADD(&pucch_Config->dl_DataToUL_ACK->list,delay[i]);
}
......@@ -1402,7 +1405,8 @@ void fill_mastercellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, NR_CellGr
void fill_initial_cellGroupConfig(rnti_t rnti,
NR_CellGroupConfig_t *cellGroupConfig,
NR_ServingCellConfigCommon_t *scc) {
NR_ServingCellConfigCommon_t *scc,
rrc_gNB_carrier_data_t *carrier) {
NR_RLC_BearerConfig_t *rlc_BearerConfig = NULL;
NR_RLC_Config_t *rlc_Config = NULL;
......@@ -1493,7 +1497,7 @@ void fill_initial_cellGroupConfig(rnti_t rnti,
cellGroupConfig->spCellConfig = calloc(1,sizeof(*cellGroupConfig->spCellConfig));
fill_initial_SpCellConfig(rnti,cellGroupConfig->spCellConfig,scc);
fill_initial_SpCellConfig(rnti,cellGroupConfig->spCellConfig,scc,carrier);
cellGroupConfig->sCellToAddModList = NULL;
cellGroupConfig->sCellToReleaseList = NULL;
......@@ -1504,7 +1508,8 @@ uint8_t do_RRCSetup(rrc_gNB_ue_context_t *const ue_context_pP,
uint8_t *const buffer,
const uint8_t transaction_id,
OCTET_STRING_t *masterCellGroup_from_DU,
NR_ServingCellConfigCommon_t *scc)
NR_ServingCellConfigCommon_t *scc,
rrc_gNB_carrier_data_t *carrier)
//------------------------------------------------------------------------------
{
asn_enc_rval_t enc_rval;
......@@ -1571,7 +1576,7 @@ uint8_t do_RRCSetup(rrc_gNB_ue_context_t *const ue_context_pP,
}
else {
cellGroupConfig = calloc(1, sizeof(NR_CellGroupConfig_t));
fill_initial_cellGroupConfig(ue_context_pP->ue_context.rnti,cellGroupConfig,scc);
fill_initial_cellGroupConfig(ue_context_pP->ue_context.rnti,cellGroupConfig,scc,carrier);
enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig,
NULL,
......
......@@ -91,11 +91,13 @@ uint8_t do_RRCReject(uint8_t Mod_id,
void fill_initial_SpCellConfig(rnti_t rnti,
NR_SpCellConfig_t *SpCellConfig,
NR_ServingCellConfigCommon_t *scc);
NR_ServingCellConfigCommon_t *scc,
rrc_gNB_carrier_data_t *carrier);
void fill_initial_cellGroupConfig(rnti_t rnti,
NR_CellGroupConfig_t *cellGroupConfig,
NR_ServingCellConfigCommon_t *scc);
NR_ServingCellConfigCommon_t *scc,
rrc_gNB_carrier_data_t *carrier);
void fill_mastercellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, NR_CellGroupConfig_t *ue_context_mastercellGroup);
......@@ -103,7 +105,8 @@ uint8_t do_RRCSetup(rrc_gNB_ue_context_t *const ue_context_pP,
uint8_t *const buffer,
const uint8_t transaction_id,
OCTET_STRING_t *masterCellGroup_from_DU,
NR_ServingCellConfigCommon_t *scc);
NR_ServingCellConfigCommon_t *scc,
rrc_gNB_carrier_data_t *carrier);
uint8_t do_NR_SecurityModeCommand(
const protocol_ctxt_t *const ctxt_pP,
......
......@@ -447,8 +447,7 @@ typedef struct {
int sib1_tda;
int pdsch_AntennaPorts;
int pusch_AntennaPorts;
int pusch_TargetSNRx10;
int pucch_TargetSNRx10;
int minRXTXTIMEpdsch;
int do_CSIRS;
NR_BCCH_DL_SCH_Message_t *siblock1;
NR_ServingCellConfigCommon_t *servingcellconfigcommon;
......
......@@ -332,6 +332,7 @@ char openair_rrc_gNB_configuration(const module_id_t gnb_mod_idP, gNB_RrcConfigu
rrc->carrier.ssb_SubcarrierOffset = configuration->ssb_SubcarrierOffset;
rrc->carrier.pdsch_AntennaPorts = configuration->pdsch_AntennaPorts;
rrc->carrier.pusch_AntennaPorts = configuration->pusch_AntennaPorts;
rrc->carrier.minRXTXTIMEpdsch = configuration->minRXTXTIMEpdsch;
rrc->carrier.sib1_tda = configuration->sib1_tda;
rrc->carrier.do_CSIRS = configuration->do_CSIRS;
/// System Information INIT
......@@ -444,17 +445,18 @@ rrc_gNB_generate_RRCSetup(
// T_INT(ctxt_pP->subframe),
// T_INT(ctxt_pP->rnti));
gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context;
gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id];
ue_p->Srb0.Tx_buffer.payload_size = do_RRCSetup(ue_context_pP,
(uint8_t *) ue_p->Srb0.Tx_buffer.Payload,
rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id),
masterCellGroup_from_DU,
scc);
scc,&rrc->carrier);
LOG_DUMPMSG(NR_RRC, DEBUG_RRC,
(char *)(ue_p->Srb0.Tx_buffer.Payload),
ue_p->Srb0.Tx_buffer.payload_size,
"[MSG] RRC Setup\n");
gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id];
switch (rrc->node_type) {
case ngran_gNB_CU:
// create an ITTI message
......@@ -567,7 +569,7 @@ rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest(
(uint8_t *) ue_p->Srb0.Tx_buffer.Payload,
rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id),
NULL,
scc);
scc,&rrc_instance_p->carrier);
LOG_DUMPMSG(NR_RRC, DEBUG_RRC,
(char *)(ue_p->Srb0.Tx_buffer.Payload),
......
......@@ -940,7 +940,7 @@ extern "C" {
LOG_I(HW, "openair0_cfg[0].sdr_addrs == '%s'\n", openair0_cfg[0].sdr_addrs);
LOG_I(HW, "openair0_cfg[0].clock_source == '%d' (internal = %d, external = %d)\n", openair0_cfg[0].clock_source,internal,external);
usrp_state_t *s ;
int choffset = 0;
int choffset = 1;
if ( device->priv == NULL) {
s=(usrp_state_t *)calloc(sizeof(usrp_state_t),1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment