Commit a108e703 authored by Rohit Gupta's avatar Rohit Gupta

Merge branch 'feature-44-dedicated-drb' of...

Merge branch 'feature-44-dedicated-drb' of https://gitlab.eurecom.fr/oai/openairinterface5g into feature-44-dedicated-drb
parents bcd96a7f 86a34cd5
...@@ -598,13 +598,13 @@ rrc_data_ind( ...@@ -598,13 +598,13 @@ rrc_data_ind(
if (ctxt_pP->enb_flag == ENB_FLAG_NO) { if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
LOG_N(RRC, "[UE %x] Frame %d: received a DCCH %d message on SRB %d with Size %d from eNB %d\n", LOG_N(RRC, "[UE %x] Frame %d: received a DCCH %d message on SRB %d with Size %d from eNB %d\n",
ctxt_pP->module_id, ctxt_pP->frame, DCCH_index,Srb_id-1,sdu_sizeP, ctxt_pP->eNB_index); ctxt_pP->module_id, ctxt_pP->frame, DCCH_index,Srb_id,sdu_sizeP, ctxt_pP->eNB_index);
} else { } else {
LOG_N(RRC, "[eNB %d] Frame %d: received a DCCH %d message on SRB %d with Size %d from UE %x\n", LOG_N(RRC, "[eNB %d] Frame %d: received a DCCH %d message on SRB %d with Size %d from UE %x\n",
ctxt_pP->module_id, ctxt_pP->module_id,
ctxt_pP->frame, ctxt_pP->frame,
DCCH_index, DCCH_index,
Srb_id-1, Srb_id,
sdu_sizeP, sdu_sizeP,
ctxt_pP->rnti); ctxt_pP->rnti);
} }
......
...@@ -1128,6 +1128,8 @@ rrc_eNB_generate_RRCConnectionRelease( ...@@ -1128,6 +1128,8 @@ rrc_eNB_generate_RRCConnectionRelease(
PDCP_TRANSMISSION_MODE_CONTROL); PDCP_TRANSMISSION_MODE_CONTROL);
} }
uint8_t qci_to_priority[9]={2,4,3,5,1,6,7,8,9};
// TBD: this directive can be remived if we create a similar e_rab_param_t structure in RRC context // TBD: this directive can be remived if we create a similar e_rab_param_t structure in RRC context
#if defined(ENABLE_ITTI) #if defined(ENABLE_ITTI)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
...@@ -1158,9 +1160,11 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co ...@@ -1158,9 +1160,11 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co
struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList *dedicatedInfoNASList = NULL; struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList *dedicatedInfoNASList = NULL;
DedicatedInfoNAS_t *dedicatedInfoNas = NULL; DedicatedInfoNAS_t *dedicatedInfoNas = NULL;
/* for no gcc warnings */
(void)dedicatedInfoNas;
long *logicalchannelgroup, *logicalchannelgroup_drb; long *logicalchannelgroup_drb;
int drb_identity_index=0;//, nas_sequence_flag = 0; int drb_identity_index=0;
uint8_t xid = rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id); //Transaction_id, uint8_t xid = rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id); //Transaction_id,
DRB_configList2=&ue_context_pP->ue_context.DRB_configList2[xid]; DRB_configList2=&ue_context_pP->ue_context.DRB_configList2[xid];
...@@ -1169,6 +1173,7 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co ...@@ -1169,6 +1173,7 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co
} }
//*DRB_configList = CALLOC(1, sizeof(*DRB_configList)); //*DRB_configList = CALLOC(1, sizeof(*DRB_configList));
*DRB_configList2 = CALLOC(1, sizeof(**DRB_configList2)); *DRB_configList2 = CALLOC(1, sizeof(**DRB_configList2));
/* Initialize NAS list */
dedicatedInfoNASList = CALLOC(1, sizeof(struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList)); dedicatedInfoNASList = CALLOC(1, sizeof(struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList));
int e_rab_done=0; int e_rab_done=0;
...@@ -1187,7 +1192,7 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co ...@@ -1187,7 +1192,7 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co
DRB_config->eps_BearerIdentity = CALLOC(1, sizeof(long)); DRB_config->eps_BearerIdentity = CALLOC(1, sizeof(long));
// allowed value 5..15, value : x+4 // allowed value 5..15, value : x+4
*(DRB_config->eps_BearerIdentity) = ue_context_pP->ue_context.e_rab[i].param.e_rab_id + 4; *(DRB_config->eps_BearerIdentity) = ue_context_pP->ue_context.e_rab[i].param.e_rab_id;//+ 4; // especial case generation
DRB_config->drb_Identity = 1 + drb_identity_index + e_rab_done;// + i ;// (DRB_Identity_t) ue_context_pP->ue_context.e_rab[i].param.e_rab_id; DRB_config->drb_Identity = 1 + drb_identity_index + e_rab_done;// + i ;// (DRB_Identity_t) ue_context_pP->ue_context.e_rab[i].param.e_rab_id;
// 1 + drb_identiy_index; // 1 + drb_identiy_index;
...@@ -1205,12 +1210,18 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co ...@@ -1205,12 +1210,18 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co
DRB_pdcp_config->rlc_AM = NULL; DRB_pdcp_config->rlc_AM = NULL;
DRB_pdcp_config->rlc_UM = NULL; DRB_pdcp_config->rlc_UM = NULL;
switch (ue_context_pP->ue_context.e_rab[i].param.qos.qci){ switch (ue_context_pP->ue_context.e_rab[i].param.qos.qci){
case 1: // RLC _UM /*
case 2: * type: realtime data with medium packer error rate
case 3: * action: swtich to RLC UM
case 4: */
case 5: case 1: // 100ms, 10^-2, p2, GBR
case 2: // 150ms, 10^-3, p4, GBR
case 3: // 50ms, 10^-3, p3, GBR
case 7: // 100ms, 10^-3, p7, GBR
case 65: // 75ms, 10^-2, p0.7, mission critical voice, GBR
case 66: // 100ms, 10^-2, p2, non-mission critical voice , GBR
// RLC // RLC
DRB_rlc_config->present = RLC_Config_PR_um_Bi_Directional; DRB_rlc_config->present = RLC_Config_PR_um_Bi_Directional;
DRB_rlc_config->choice.um_Bi_Directional.ul_UM_RLC.sn_FieldLength = SN_FieldLength_size10; DRB_rlc_config->choice.um_Bi_Directional.ul_UM_RLC.sn_FieldLength = SN_FieldLength_size10;
...@@ -1221,11 +1232,18 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co ...@@ -1221,11 +1232,18 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co
DRB_pdcp_config->rlc_UM = PDCP_rlc_UM; DRB_pdcp_config->rlc_UM = PDCP_rlc_UM;
PDCP_rlc_UM->pdcp_SN_Size = PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits; PDCP_rlc_UM->pdcp_SN_Size = PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits;
break; break;
case 6:
case 7: /*
case 8: * type: non-realtime data with low packer error rate
case 9: * action: swtich to RLC AM
default: */
case 4: // 300ms, 10^-6, p5
case 5: // 100ms, 10^-6, p1 , IMS signaling
case 6: // 300ms, 10^-6, p6
case 8: // 300ms, 10^-6, p8
case 9: // 300ms, 10^-6, p9
case 69: // 60ms, 10^-6, p0.5, mission critical delay sensitive data, Lowest Priority
case 70: // 200ms, 10^-6, p5.5, mision critical data
// RLC // RLC
DRB_rlc_config->present = RLC_Config_PR_am; DRB_rlc_config->present = RLC_Config_PR_am;
DRB_rlc_config->choice.am.ul_AM_RLC.t_PollRetransmit = T_PollRetransmit_ms50; DRB_rlc_config->choice.am.ul_AM_RLC.t_PollRetransmit = T_PollRetransmit_ms50;
...@@ -1240,8 +1258,12 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co ...@@ -1240,8 +1258,12 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co
DRB_pdcp_config->rlc_AM = PDCP_rlc_AM; DRB_pdcp_config->rlc_AM = PDCP_rlc_AM;
PDCP_rlc_AM->statusReportRequired = FALSE; PDCP_rlc_AM->statusReportRequired = FALSE;
//LOG_I(RRC,"not supported qci %d\n", ue_context_pP->ue_context.e_rab[i].param.qos.qci);
break; break;
default :
LOG_E(RRC,"not supported qci %d\n", ue_context_pP->ue_context.e_rab[i].param.qos.qci);
ue_context_pP->ue_context.e_rab[i].status = E_RAB_STATUS_FAILED;
ue_context_pP->ue_context.e_rab[i].xid = xid;
continue;
} }
DRB_pdcp_config->headerCompression.present = PDCP_Config__headerCompression_PR_notUsed; DRB_pdcp_config->headerCompression.present = PDCP_Config__headerCompression_PR_notUsed;
...@@ -1251,10 +1273,14 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co ...@@ -1251,10 +1273,14 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co
DRB_ul_SpecificParameters = CALLOC(1, sizeof(*DRB_ul_SpecificParameters)); DRB_ul_SpecificParameters = CALLOC(1, sizeof(*DRB_ul_SpecificParameters));
DRB_lchan_config->ul_SpecificParameters = DRB_ul_SpecificParameters; DRB_lchan_config->ul_SpecificParameters = DRB_ul_SpecificParameters;
DRB_ul_SpecificParameters->priority = ue_context_pP->ue_context.e_rab[i].param.qos.allocation_retention_priority.priority_level; if (ue_context_pP->ue_context.e_rab[i].param.qos.qci < 10 )
// TO DO DRB_ul_SpecificParameters->priority = qci_to_priority[ue_context_pP->ue_context.e_rab[i].param.qos.qci-1] + 3;
DRB_ul_SpecificParameters->prioritisedBitRate = // ue_context_pP->ue_context.e_rab[i].param.qos.allocation_retention_priority.priority_level;
LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity; else
DRB_ul_SpecificParameters->priority= 4;
DRB_ul_SpecificParameters->prioritisedBitRate = LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps8;
//LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity;
DRB_ul_SpecificParameters->bucketSizeDuration = DRB_ul_SpecificParameters->bucketSizeDuration =
LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50; LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50;
...@@ -1275,7 +1301,10 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co ...@@ -1275,7 +1301,10 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co
*DRB_ul_SpecificParameters->logicalChannelGroup *DRB_ul_SpecificParameters->logicalChannelGroup
); );
//if (nas_sequence_flag == 0) e_rab_done++;
ue_context_pP->ue_context.e_rab[i].status = E_RAB_STATUS_DONE;
ue_context_pP->ue_context.e_rab[i].xid = xid;
{ {
if (ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer != NULL) { if (ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer != NULL) {
dedicatedInfoNas = CALLOC(1, sizeof(DedicatedInfoNAS_t)); dedicatedInfoNas = CALLOC(1, sizeof(DedicatedInfoNAS_t));
...@@ -1284,7 +1313,10 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co ...@@ -1284,7 +1313,10 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co
(char*)ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer, (char*)ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer,
ue_context_pP->ue_context.e_rab[i].param.nas_pdu.length); ue_context_pP->ue_context.e_rab[i].param.nas_pdu.length);
ASN_SEQUENCE_ADD(&dedicatedInfoNASList->list, dedicatedInfoNas); ASN_SEQUENCE_ADD(&dedicatedInfoNASList->list, dedicatedInfoNas);
// nas_sequence_flag = 1; LOG_I(RRC,"add NAS info with size %d (rab id %d)\n",ue_context_pP->ue_context.e_rab[i].param.nas_pdu.length, i);
}
else {
LOG_W(RRC,"Not received activate dedicated EPS bearer context request\n");
} }
/* TODO parameters yet to process ... */ /* TODO parameters yet to process ... */
{ {
...@@ -1292,19 +1324,19 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co ...@@ -1292,19 +1324,19 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co
// ue_context_pP->ue_context.e_rab[i].param.sgw_addr; // ue_context_pP->ue_context.e_rab[i].param.sgw_addr;
// ue_context_pP->ue_context.e_rab[i].param.gtp_teid; // ue_context_pP->ue_context.e_rab[i].param.gtp_teid;
} }
}
}
/* If list is empty free the list and reset the address */ /* If list is empty free the list and reset the address */
if (dedicatedInfoNASList != NULL) { if (dedicatedInfoNASList != NULL) {
if (dedicatedInfoNASList->list.count == 0) { if (dedicatedInfoNASList->list.count == 0) {
free(dedicatedInfoNASList); free(dedicatedInfoNASList);
dedicatedInfoNASList = NULL; dedicatedInfoNASList = NULL;
LOG_W(RRC,"dedlicated NAS list is empty, free the list and reset the address\n");
} }
} } else {
} LOG_W(RRC,"dedlicated NAS list is empty\n");
e_rab_done++;
ue_context_pP->ue_context.e_rab[i].status = E_RAB_STATUS_DONE;
ue_context_pP->ue_context.e_rab[i].xid = xid;
} }
memset(buffer, 0, RRC_BUF_SIZE); memset(buffer, 0, RRC_BUF_SIZE);
...@@ -1324,6 +1356,7 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co ...@@ -1324,6 +1356,7 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co
#endif #endif
); );
#ifdef RRC_MSG_PRINT #ifdef RRC_MSG_PRINT
LOG_F(RRC,"[MSG] RRC Connection Reconfiguration\n"); LOG_F(RRC,"[MSG] RRC Connection Reconfiguration\n");
for (i = 0; i < size; i++) { for (i = 0; i < size; i++) {
...@@ -1346,7 +1379,7 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co ...@@ -1346,7 +1379,7 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co
#endif #endif
LOG_I(RRC, LOG_I(RRC,
"[eNB %d] Frame %d, Logical Channel DL-DCCH, Generate RRCConnectionReconfiguration (bytes %d, UE id %x)\n", "[eNB %d] Frame %d, Logical Channel DL-DCCH, Generate RRCConnectionReconfiguration (bytes %d, UE RNTI %x)\n",
ctxt_pP->module_id, ctxt_pP->frame, size, ue_context_pP->ue_context.rnti); ctxt_pP->module_id, ctxt_pP->frame, size, ue_context_pP->ue_context.rnti);
LOG_D(RRC, LOG_D(RRC,
...@@ -1496,7 +1529,7 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t* cons ...@@ -1496,7 +1529,7 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t* cons
SRB2_ul_SpecificParameters = CALLOC(1, sizeof(*SRB2_ul_SpecificParameters)); SRB2_ul_SpecificParameters = CALLOC(1, sizeof(*SRB2_ul_SpecificParameters));
SRB2_ul_SpecificParameters->priority = 1; SRB2_ul_SpecificParameters->priority = 3; // let some priority for SRB1 and dedicated DRBs
SRB2_ul_SpecificParameters->prioritisedBitRate = SRB2_ul_SpecificParameters->prioritisedBitRate =
LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity; LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity;
SRB2_ul_SpecificParameters->bucketSizeDuration = SRB2_ul_SpecificParameters->bucketSizeDuration =
...@@ -1591,9 +1624,9 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t* cons ...@@ -1591,9 +1624,9 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t* cons
DRB_ul_SpecificParameters = CALLOC(1, sizeof(*DRB_ul_SpecificParameters)); DRB_ul_SpecificParameters = CALLOC(1, sizeof(*DRB_ul_SpecificParameters));
DRB_lchan_config->ul_SpecificParameters = DRB_ul_SpecificParameters; DRB_lchan_config->ul_SpecificParameters = DRB_ul_SpecificParameters;
DRB_ul_SpecificParameters->priority = 2; // lower priority than srb1, srb2 DRB_ul_SpecificParameters->priority = 12; // lower priority than srb1, srb2 and other dedicated bearer
DRB_ul_SpecificParameters->prioritisedBitRate = DRB_ul_SpecificParameters->prioritisedBitRate =LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps8 ;
LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity; //LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity;
DRB_ul_SpecificParameters->bucketSizeDuration = DRB_ul_SpecificParameters->bucketSizeDuration =
LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50; LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50;
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
*******************************************************************************/ *******************************************************************************/
/*! \file rrc_eNB_S1AP.c /*! \file rrc_eNB_S1AP.c
* \brief rrc S1AP procedures for eNB * \brief rrc S1AP procedures for eNB
* \author Laurent Winckel, Sebastien ROUX, Navid Nikaein and Lionel GAUTHIER * \author Navid Nikaein, Laurent Winckel, Sebastien ROUX, and Lionel GAUTHIER
* \date 2013-2016 * \date 2013-2016
* \version 1.0 * \version 1.0
* \company Eurecom * \company Eurecom
......
...@@ -142,6 +142,7 @@ static int s1ap_eNB_decode_initiating_message(s1ap_message *message, ...@@ -142,6 +142,7 @@ static int s1ap_eNB_decode_initiating_message(s1ap_message *message,
//s1ap_xer_print_s1ap_e_rabsetuprequest(s1ap_xer__print2sp, message_string, message); //s1ap_xer_print_s1ap_e_rabsetuprequest(s1ap_xer__print2sp, message_string, message);
S1AP_INFO("TODO E_RABRelease nitiating message\n"); S1AP_INFO("TODO E_RABRelease nitiating message\n");
free(message_string); free(message_string);
break;
default: default:
S1AP_ERROR("Unknown procedure ID (%d) for initiating message\n", S1AP_ERROR("Unknown procedure ID (%d) for initiating message\n",
......
...@@ -771,6 +771,7 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id, ...@@ -771,6 +771,7 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id,
memcpy(S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].nas_pdu.buffer, memcpy(S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].nas_pdu.buffer,
item_p->nAS_PDU->buf, item_p->nAS_PDU->size); item_p->nAS_PDU->buf, item_p->nAS_PDU->size);
S1AP_DEBUG("Received NAS message with the E_RAB setup procedure\n");
} else { } else {
S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].nas_pdu.length = 0; S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].nas_pdu.length = 0;
S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].nas_pdu.buffer = NULL; S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].nas_pdu.buffer = NULL;
...@@ -951,6 +952,7 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t assoc_id, ...@@ -951,6 +952,7 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t assoc_id,
memcpy(S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].nas_pdu.buffer, memcpy(S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].nas_pdu.buffer,
item_p->nAS_PDU.buf, item_p->nAS_PDU.size); item_p->nAS_PDU.buf, item_p->nAS_PDU.size);
// S1AP_INFO("received a NAS PDU with size %d (%02x.%02x)\n",S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].nas_pdu.length, item_p->nAS_PDU.buf[0], item_p->nAS_PDU.buf[1]);
} else { } else {
S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].nas_pdu.length = 0; S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].nas_pdu.length = 0;
S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].nas_pdu.buffer = NULL; S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].nas_pdu.buffer = NULL;
......
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