Commit 9e805a6f authored by Tien-Thinh Nguyen's avatar Tien-Thinh Nguyen

correct indentation for smf main classes

parent 933e5d7b
......@@ -124,7 +124,6 @@ scid_t smf_app::generate_smf_context_ref()
return sm_context_ref_generator.get_uid();
}
//------------------------------------------------------------------------------
bool smf_app::is_seid_n4_exist(const uint64_t& seid) const
{
......@@ -276,7 +275,6 @@ smf_app::smf_app (const std::string& config_file) : m_seid2smf_context()
Logger::smf_app().startup( "Started" );
}
//------------------------------------------------------------------------------
//From SPGWU
void smf_app::start_upf_association(const pfcp::node_id_t& node_id)
......@@ -396,7 +394,6 @@ void smf_app::handle_itti_msg (std::shared_ptr<itti_n4_session_report_request> s
}
}
//------------------------------------------------------------------------------
void smf_app::handle_itti_msg (itti_n11_n1n2_message_transfer_response_status& m)
{
......@@ -421,7 +418,6 @@ void smf_app::handle_itti_msg (itti_n11_n1n2_message_transfer_response_status& m
}
//------------------------------------------------------------------------------
void smf_app::handle_itti_msg (itti_n11_update_pdu_session_status& m)
{
......@@ -735,7 +731,6 @@ void smf_app::handle_pdu_session_update_sm_context_request (std::shared_ptr<itti
}
//------------------------------------------------------------------------------
void smf_app::handle_network_requested_pdu_session_modification()
{
......@@ -770,8 +765,8 @@ void smf_app::handle_network_requested_pdu_session_modification()
// handle the message in smf_context
// sc.get()->handle_network_requested_pdu_session_modification(itti_msg);
}
//------------------------------------------------------------------------------
bool smf_app::is_supi_2_smf_context(const supi64_t& supi) const
{
......
......@@ -226,18 +226,21 @@ void smf_pdu_session::generate_far_id(pfcp::far_id_t& far_id)
{
far_id.far_id = far_id_generator.get_uid();
}
//------------------------------------------------------------------------------
// TODO check if prd_id should be uniq in the UPF or in the context of a pdn connection
void smf_pdu_session::release_far_id(const pfcp::far_id_t& far_id)
{
far_id_generator.free_uid(far_id.far_id);
}
//------------------------------------------------------------------------------
// TODO check if prd_id should be uniq in the UPF or in the context of a pdn connection
void smf_pdu_session::generate_pdr_id(pfcp::pdr_id_t& pdr_id)
{
pdr_id.rule_id = pdr_id_generator.get_uid();
}
//------------------------------------------------------------------------------
// TODO check if prd_id should be uniq in the UPF or in the context of a pdn connection
void smf_pdu_session::release_pdr_id(const pfcp::pdr_id_t& pdr_id)
......@@ -278,6 +281,7 @@ void smf_pdu_session::set_pdu_session_status (const pdu_session_status_e& status
{
pdu_session_status = status;
}
//------------------------------------------------------------------------------
pdu_session_status_e smf_pdu_session::get_pdu_session_status () const
{
......@@ -302,6 +306,7 @@ void smf_context::insert_procedure(std::shared_ptr<smf_procedure>& sproc)
std::unique_lock<std::recursive_mutex> lock(m_context);
pending_procedures.push_back(sproc);
}
//------------------------------------------------------------------------------
bool smf_context::find_procedure(const uint64_t& trxn_id, std::shared_ptr<smf_procedure>& proc)
{
......@@ -314,6 +319,7 @@ bool smf_context::find_procedure(const uint64_t& trxn_id, std::shared_ptr<smf_pr
}
return false;
}
//------------------------------------------------------------------------------
void smf_context::remove_procedure(smf_procedure* proc)
{
......@@ -326,7 +332,6 @@ void smf_context::remove_procedure(smf_procedure* proc)
}
}
//------------------------------------------------------------------------------
void smf_context::handle_itti_msg (itti_n4_session_establishment_response& seresp)
{
......@@ -339,6 +344,7 @@ void smf_context::handle_itti_msg (itti_n4_session_establishment_response& seres
Logger::smf_app().debug("Received N4 SESSION ESTABLISHMENT RESPONSE sender teid " TEID_FMT " pfcp_tx_id %" PRIX64", smf_procedure not found, discarded!", seresp.seid, seresp.trxn_id);
}
}
//------------------------------------------------------------------------------
void smf_context::handle_itti_msg (itti_n4_session_modification_response& smresp)
{
......@@ -352,6 +358,7 @@ void smf_context::handle_itti_msg (itti_n4_session_modification_response& smresp
}
Logger::smf_app().info("Handle N4 SESSION MODIFICATION RESPONSE with SMF context %s", toString().c_str());
}
//------------------------------------------------------------------------------
void smf_context::handle_itti_msg (itti_n4_session_deletion_response& sdresp)
{
......@@ -365,6 +372,7 @@ void smf_context::handle_itti_msg (itti_n4_session_deletion_response& sdresp)
}
std::cout << toString() << std::endl;
}
//------------------------------------------------------------------------------
void smf_context::handle_itti_msg (std::shared_ptr<itti_n4_session_report_request>& req)
{
......@@ -388,7 +396,6 @@ std::string smf_context::toString() const
return s;
}
//------------------------------------------------------------------------------
void smf_context::get_default_qos(const snssai_t& snssai, const std::string& dnn, subscribed_default_qos_t &default_qos)
{
......@@ -416,7 +423,7 @@ void smf_context::get_default_qos_rule(QOSRulesIE &qos_rule, uint8_t pdu_session
qos_rule.qosruleidentifer = 0x01;
qos_rule.ruleoperationcode = CREATE_NEW_QOS_RULE;
qos_rule.dqrbit = THE_QOS_RULE_IS_DEFAULT_QOS_RULE;
if ((pdu_session_type == PDU_SESSION_TYPE_E_IPV4) or (pdu_session_type == PDU_SESSION_TYPE_E_IPV4V6) or (pdu_session_type == PDU_SESSION_TYPE_E_IPV6) or (pdu_session_type == PDU_SESSION_TYPE_E_ETHERNET)){
if ((pdu_session_type == PDU_SESSION_TYPE_E_IPV4) or (pdu_session_type == PDU_SESSION_TYPE_E_IPV4V6) or (pdu_session_type == PDU_SESSION_TYPE_E_IPV6) or (pdu_session_type == PDU_SESSION_TYPE_E_ETHERNET)) {
qos_rule.numberofpacketfilters = 1;
qos_rule.packetfilterlist.create_modifyandadd_modifyandreplace = (Create_ModifyAndAdd_ModifyAndReplace *)calloc (1, sizeof (Create_ModifyAndAdd_ModifyAndReplace));
qos_rule.packetfilterlist.create_modifyandadd_modifyandreplace[0].packetfilterdirection = 0b11; //bi-directional
......@@ -426,7 +433,7 @@ void smf_context::get_default_qos_rule(QOSRulesIE &qos_rule, uint8_t pdu_session
qos_rule.qosruleprecedence = 1;
}
if (pdu_session_type == PDU_SESSION_TYPE_E_UNSTRUCTURED){
if (pdu_session_type == PDU_SESSION_TYPE_E_UNSTRUCTURED) {
qos_rule.numberofpacketfilters = 0;
qos_rule.qosruleprecedence = 1;
}
......@@ -493,7 +500,7 @@ void smf_context::get_session_ambr(SessionAMBR& session_ambr, const snssai_t& sn
if (nullptr != ss.get()){
ss.get()->find_dnn_configuration(dnn, sdc);
if (nullptr != sdc.get()){
if (nullptr != sdc.get()) {
Logger::smf_app().debug("Default AMBR info from the DNN configuration, downlink %s, uplink %s", (sdc.get()->session_ambr).downlink.c_str(), (sdc.get()->session_ambr).uplink.c_str());
//Downlink
......@@ -512,19 +519,16 @@ void smf_context::get_session_ambr(SessionAMBR& session_ambr, const snssai_t& sn
session_ambr.uint_for_session_ambr_for_downlink = AMBR_VALUE_IS_INCREMENTED_IN_MULTIPLES_OF_1PBPS;
session_ambr.session_ambr_for_downlink = std::stoi((sdc.get()->session_ambr).downlink.substr(0, leng_of_session_ambr_dl-4));
}
catch (const std::exception& e)
{
} catch (const std::exception& e) {
Logger::smf_app().warn("Undefined error: %s", e.what());
//assign default value
session_ambr.session_ambr_for_downlink = 1;
session_ambr.uint_for_session_ambr_for_downlink = AMBR_VALUE_IS_INCREMENTED_IN_MULTIPLES_OF_1MBPS;
}
//Uplink
size_t leng_of_session_ambr_ul = (sdc.get()->session_ambr).uplink.length();
try{
try {
std::string session_ambr_ul_unit = (sdc.get()->session_ambr).uplink.substr(leng_of_session_ambr_ul-4); //4 last characters stand for mbps, kbps, ..
if (session_ambr_ul_unit.compare("Kbps") == 0)
session_ambr.uint_for_session_ambr_for_uplink = AMBR_VALUE_IS_INCREMENTED_IN_MULTIPLES_OF_1KBPS;
......@@ -538,9 +542,7 @@ void smf_context::get_session_ambr(SessionAMBR& session_ambr, const snssai_t& sn
session_ambr.uint_for_session_ambr_for_uplink = AMBR_VALUE_IS_INCREMENTED_IN_MULTIPLES_OF_1PBPS;
session_ambr.session_ambr_for_uplink = std::stoi((sdc.get()->session_ambr).uplink.substr(0, leng_of_session_ambr_ul-4));
}
catch (const std::exception& e)
{
} catch (const std::exception& e) {
Logger::smf_app().warn("Undefined error: %s", e.what());
//assign default value
session_ambr.session_ambr_for_uplink = 1;
......@@ -557,8 +559,6 @@ void smf_context::get_session_ambr(SessionAMBR& session_ambr, const snssai_t& sn
}
//------------------------------------------------------------------------------
void smf_context::get_session_ambr(Ngap_PDUSessionAggregateMaximumBitRate_t& session_ambr, const snssai_t& snssai, const std::string& dnn)
{
......@@ -576,10 +576,10 @@ void smf_context::get_session_ambr(Ngap_PDUSessionAggregateMaximumBitRate_t& ses
session_ambr.pDUSessionAggregateMaximumBitRateUL.size = 4;
session_ambr.pDUSessionAggregateMaximumBitRateUL.buf = (uint8_t *) calloc(4, sizeof (uint8_t));
if (nullptr != ss.get()){
if (nullptr != ss.get()) {
ss.get()->find_dnn_configuration(dnn, sdc);
if (nullptr != sdc.get()){
if (nullptr != sdc.get()) {
Logger::smf_app().debug("Default AMBR info from the DNN configuration, downlink %s, uplink %s", (sdc.get()->session_ambr).downlink.c_str(), (sdc.get()->session_ambr).uplink.c_str());
//Downlink
size_t leng_of_session_ambr_dl = (sdc.get()->session_ambr).downlink.length();
......@@ -593,9 +593,7 @@ void smf_context::get_session_ambr(Ngap_PDUSessionAggregateMaximumBitRate_t& ses
if (session_ambr_dl_unit.compare("Gbps") == 0)
bit_rate_dl *= 1000000000;
INT32_TO_BUFFER(bit_rate_dl, session_ambr.pDUSessionAggregateMaximumBitRateDL.buf);
}
catch (const std::exception& e)
{
} catch (const std::exception& e) {
Logger::smf_app().warn("Undefined error: %s", e.what());
//assign default value
bit_rate_dl = 1;
......@@ -604,7 +602,7 @@ void smf_context::get_session_ambr(Ngap_PDUSessionAggregateMaximumBitRate_t& ses
//Uplink
size_t leng_of_session_ambr_ul = (sdc.get()->session_ambr).uplink.length();
try{
try {
bit_rate_ul = std::stoi((sdc.get()->session_ambr).uplink.substr(0, leng_of_session_ambr_ul - 4));
std::string session_ambr_ul_unit = (sdc.get()->session_ambr).uplink.substr(leng_of_session_ambr_ul - 4); //4 last characters stand for mbps, kbps, ..
if (session_ambr_ul_unit.compare("Kbps") == 0)
......@@ -614,9 +612,7 @@ void smf_context::get_session_ambr(Ngap_PDUSessionAggregateMaximumBitRate_t& ses
if (session_ambr_ul_unit.compare("Gbps") == 0)
bit_rate_ul *= 1000000000;
INT32_TO_BUFFER(bit_rate_ul, session_ambr.pDUSessionAggregateMaximumBitRateUL.buf);
}
catch (const std::exception& e)
{
} catch (const std::exception& e) {
Logger::smf_app().warn("Undefined error: %s", e.what());
//assign default value
bit_rate_ul = 1;
......@@ -630,7 +626,6 @@ void smf_context::get_session_ambr(Ngap_PDUSessionAggregateMaximumBitRate_t& ses
}
//------------------------------------------------------------------------------
void smf_context::handle_pdu_session_create_sm_context_request (std::shared_ptr<itti_n11_create_sm_context_request> smreq)
{
......@@ -651,7 +646,7 @@ void smf_context::handle_pdu_session_create_sm_context_request (std::shared_ptr<
uint32_t pdu_session_id = sm_context_req_msg.get_pdu_session_id();
//Step 2. check the validity of the UE request, if valid send PDU Session Accept, otherwise send PDU Session Reject to AMF
if (!verify_sm_context_request(smreq)){ //TODO: Need to implement this function
if (!verify_sm_context_request(smreq)) { //TODO: Need to implement this function
// Not a valid request...
Logger::smf_app().warn("Received PDU_SESSION_CREATESMCONTEXT_REQUEST, the request is not valid!");
problem_details.setCause(pdu_session_application_error_e2str[PDU_SESSION_APPLICATION_ERROR_SUBSCRIPTION_DENIED]);
......@@ -702,7 +697,7 @@ void smf_context::handle_pdu_session_create_sm_context_request (std::shared_ptr<
std::shared_ptr<smf_pdu_session> sp = {};
bool find_pdn = sd.get()->find_pdu_session(pdu_session_id, sp);
if (nullptr == sp.get()){
if (nullptr == sp.get()) {
Logger::smf_app().debug("Create a new PDN connection!");
//create a new pdn connection
sp = std::shared_ptr<smf_pdu_session>( new smf_pdu_session());
......@@ -711,7 +706,7 @@ void smf_context::handle_pdu_session_create_sm_context_request (std::shared_ptr<
//amf id
sp.get()->amf_id = sm_context_req_msg.get_serving_nf_id();
sd->insert_pdu_session(sp);
} else{
} else {
Logger::smf_app().debug("PDN connection is already existed!");
//TODO:
}
......@@ -762,9 +757,9 @@ void smf_context::handle_pdu_session_create_sm_context_request (std::shared_ptr<
std::shared_ptr<session_management_subscription> ss = {};
std::shared_ptr<dnn_configuration_t> sdc = {};
find_dnn_subscription(snssai, ss);
if (nullptr != ss.get()){
if (nullptr != ss.get()) {
ss.get()->find_dnn_configuration(sd->dnn_in_use, sdc);
if (nullptr != sdc.get()){
if (nullptr != sdc.get()) {
paa.pdn_type.pdn_type = sdc.get()->pdu_session_types.default_session_type.pdu_session_type;
//TODO: static ip address
}
......@@ -815,7 +810,7 @@ void smf_context::handle_pdu_session_create_sm_context_request (std::shared_ptr<
//Step 9. Create session establishment procedure and run the procedure
//if request is accepted
if (request_accepted){
if (request_accepted) {
if (set_paa) {
sm_context_resp_pending->res.set_paa(paa); //will be used when procedure is running
sp->set(paa);
......@@ -860,7 +855,7 @@ void smf_context::handle_pdu_session_create_sm_context_request (std::shared_ptr<
sm_context_resp->res.set_cause(UNKNOWN_ERROR);
}
}else{ //if request is rejected
} else { //if request is rejected
//TODO:
//un-subscribe to the modifications of Session Management Subscription data for (SUPI, DNN, S-NSSAI)
}
......@@ -873,7 +868,7 @@ void smf_context::handle_pdu_session_create_sm_context_request (std::shared_ptr<
//free paa
paa_t free_paa = {};
free_paa = sm_context_resp->res.get_paa();
if (free_paa.is_ip_assigned()){
if (free_paa.is_ip_assigned()) {
switch (sp->pdn_type.pdn_type) {
case PDN_TYPE_E_IPV4:
case PDN_TYPE_E_IPV4V6:
......@@ -944,10 +939,10 @@ void smf_context::handle_pdu_session_update_sm_context_request (std::shared_ptr<
std::shared_ptr<smf_pdu_session> sp = {};
bool find_dnn = find_dnn_context (sm_context_req_msg.get_snssai(), sm_context_req_msg.get_dnn(), sd);
bool find_pdn = false;
if (find_dnn){
if (find_dnn) {
find_pdn = sd.get()->find_pdu_session(sm_context_req_msg.get_pdu_session_id(), sp);
}
if (!find_dnn or !find_pdn){
if (!find_dnn or !find_pdn) {
//error, send reply to AMF with error code "Context Not Found"
Logger::smf_app().warn("DNN or PDU session context does not exist!");
problem_details.setCause(pdu_session_application_error_e2str[PDU_SESSION_APPLICATION_ERROR_CONTEXT_NOT_FOUND]);
......@@ -969,7 +964,7 @@ void smf_context::handle_pdu_session_update_sm_context_request (std::shared_ptr<
//Step 2.1. Decode N1 (if content is available)
if (sm_context_req_msg.n1_sm_msg_is_set()){
if (sm_context_req_msg.n1_sm_msg_is_set()) {
std::string n1_sm_msg, n1_sm_msg_hex; //N1 SM container
nas_message_t decoded_nas_msg = {};
......@@ -999,11 +994,11 @@ void smf_context::handle_pdu_session_update_sm_context_request (std::shared_ptr<
//FOR TESTing PDU_SESSION_MODIFICATION_REQUEST, should be REMOVED!!!
uint8_t message_type = PDU_SESSION_MODIFICATION_REQUEST;
//end
switch (message_type){
switch (message_type) {
// switch (decoded_nas_msg.plain.sm.header.message_type){
//PDU_SESSION_MODIFICATION_REQUEST - UE initiated PDU session modification request (Step 1)
case PDU_SESSION_MODIFICATION_REQUEST:{
case PDU_SESSION_MODIFICATION_REQUEST: {
Logger::smf_app().debug("PDU_SESSION_MODIFICATION_REQUEST");
//PDU Session Modification procedure (UE-initiated, step 1.a, Section 4.3.3.2@3GPP TS 23.502)
procedure_type = session_management_procedures_type_e::PDU_SESSION_MODIFICATION_UE_INITIATED_STEP1;
......@@ -1049,13 +1044,13 @@ void smf_context::handle_pdu_session_update_sm_context_request (std::shared_ptr<
uint8_t number_of_rules = decoded_nas_msg.plain.sm.pdu_session_modification_request.qosrules.lengthofqosrulesie;
QOSRulesIE * qos_rules_ie = (QOSRulesIE *) calloc (1, sizeof(QOSRulesIE));
qos_rules_ie = decoded_nas_msg.plain.sm.pdu_session_modification_request.qosrules.qosrulesie;
for (int i = 0; i < number_of_rules; i++){
for (int i = 0; i < number_of_rules; i++) {
//qos_rules_ie[0].qosruleidentifer
if ((qos_rules_ie[i].ruleoperationcode == CREATE_NEW_QOS_RULE) and (qos_rules_ie[i].segregation == SEGREGATION_REQUESTED)){
//Request to bind specific SDF to a dedicated QoS flow
if (qos_rules_ie[i].qosruleidentifer == 0) {
//new QoS rule
} else{
} else {
//existing QoS rule
}
}
......@@ -1072,7 +1067,7 @@ void smf_context::handle_pdu_session_update_sm_context_request (std::shared_ptr<
}
//verify the PDU session ID
if (smreq->req.get_pdu_session_id() != decoded_nas_msg.plain.sm.pdu_session_modification_request.pdusessionidentity){
if (smreq->req.get_pdu_session_id() != decoded_nas_msg.plain.sm.pdu_session_modification_request.pdusessionidentity) {
//TODO: error
}
......@@ -1125,7 +1120,7 @@ void smf_context::handle_pdu_session_update_sm_context_request (std::shared_ptr<
//PDU_SESSION_MODIFICATION_COMPLETE - PDU Session Modification procedure (UE-initiated/Network-requested) (step 3)
//PDU Session Modification Command Complete
case PDU_SESSION_MODIFICATION_COMPLETE:{
case PDU_SESSION_MODIFICATION_COMPLETE: {
//PDU Session Modification procedure (Section 4.3.3.2@3GPP TS 23.502)
//TODO: should be verified since mentioned PDU_SESSION_MODIFICATION_COMMAND ACK in spec (see Step 11, section 4.3.3.2@3GPP TS 23.502)
//send response
......@@ -1147,21 +1142,21 @@ void smf_context::handle_pdu_session_update_sm_context_request (std::shared_ptr<
break;
//PDU Session Release UE-Initiated (Step 1)
case PDU_SESSION_RELEASE_REQUEST:{
case PDU_SESSION_RELEASE_REQUEST: {
//PDU Session Release procedure (Section 4.3.4@3GPP TS 23.502)
//TODO:
}
break;
//PDU Session Release UE-Initiated (Step 3)
case PDU_SESSION_RELEASE_COMPLETE:{
case PDU_SESSION_RELEASE_COMPLETE: {
//PDU Session Release procedure
//TODO:
}
break;
//To be verified
case PDU_SESSION_RELEASE_COMMAND:{
case PDU_SESSION_RELEASE_COMMAND: {
//PDU Session Release procedure (Section 4.3.4@3GPP TS 23.502)
//TODO:
......@@ -1178,7 +1173,7 @@ void smf_context::handle_pdu_session_update_sm_context_request (std::shared_ptr<
//Step 2.2. Decode N2 (if content is available)
if (sm_context_req_msg.n2_sm_info_is_set()){
if (sm_context_req_msg.n2_sm_info_is_set()) {
//get necessary information (N2 SM information)
std::string n2_sm_info_type_str = smreq->req.get_n2_sm_info_type();
......@@ -1191,11 +1186,11 @@ void smf_context::handle_pdu_session_update_sm_context_request (std::shared_ptr<
memcpy ((void *)data, (void *)n2_sm_information.c_str(), data_len);
//decode N2 SM Info
switch (n2_sm_info_type){
switch (n2_sm_info_type) {
//UE-Requested PDU Session Establishment procedure (Section 4.3.2.2.1@3GPP TS 23.502)
//or UE Triggered Service Request Procedure (step 2)
case n2_sm_info_type_e::PDU_RES_SETUP_RSP:{
case n2_sm_info_type_e::PDU_RES_SETUP_RSP: {
Logger::smf_app().info("PDU Session Establishment Request, processing N2 SM Information");
//Ngap_PDUSessionResourceSetupResponseTransfer_t
// Ngap_QosFlowPerTNLInformation_t qosFlowPerTNLInformation;
......@@ -1211,7 +1206,7 @@ void smf_context::handle_pdu_session_update_sm_context_request (std::shared_ptr<
//Ngap_PDUSessionResourceSetupResponseTransfer
std::shared_ptr<Ngap_PDUSessionResourceSetupResponseTransfer_t> decoded_msg = std::make_shared<Ngap_PDUSessionResourceSetupResponseTransfer_t>();
int decode_status = smf_n1_n2_inst.decode_n2_sm_information(decoded_msg, n2_sm_information);
if (decode_status == RETURNerror){
if (decode_status == RETURNerror) {
Logger::smf_api_server().warn("asn_decode failed");
//TODO: send error to AMF
}
......@@ -1232,7 +1227,7 @@ void smf_context::handle_pdu_session_update_sm_context_request (std::shared_ptr<
sm_context_req_msg.set_dl_fteid(dl_teid);
for (int i =0; i< decoded_msg->dLQosFlowPerTNLInformation.associatedQosFlowList.list.count; i++ ){
for (int i =0; i< decoded_msg->dLQosFlowPerTNLInformation.associatedQosFlowList.list.count; i++ ) {
pfcp::qfi_t qfi((uint8_t)(decoded_msg->dLQosFlowPerTNLInformation.associatedQosFlowList.list.array[i])->qosFlowIdentifier);
sm_context_req_msg.add_qfi(qfi);
Logger::smf_app().debug("QoSFlowPerTNLInformation, AssociatedQosFlowList, QFI %d",(decoded_msg->dLQosFlowPerTNLInformation.associatedQosFlowList.list.array[i])->qosFlowIdentifier );
......@@ -1243,13 +1238,13 @@ void smf_context::handle_pdu_session_update_sm_context_request (std::shared_ptr<
break;
//PDU Session Modification procedure (UE-initiated, Section 4.3.3.2@3GPP TS 23.502 or SMF-Requested)(Step 2)
case n2_sm_info_type_e::PDU_RES_MOD_RSP:{
case n2_sm_info_type_e::PDU_RES_MOD_RSP: {
procedure_type = session_management_procedures_type_e::PDU_SESSION_MODIFICATION_UE_INITIATED_STEP2;
//Ngap_PDUSessionResourceModifyResponseTransfer
std::shared_ptr<Ngap_PDUSessionResourceModifyResponseTransfer_t> decoded_msg = std::make_shared<Ngap_PDUSessionResourceModifyResponseTransfer_t>();
int decode_status = smf_n1_n2_inst.decode_n2_sm_information(decoded_msg, n2_sm_information);
if (decode_status == RETURNerror){
if (decode_status == RETURNerror) {
Logger::smf_api_server().warn("asn_decode failed");
//TODO: send error to AMF
}
......@@ -1268,7 +1263,7 @@ void smf_context::handle_pdu_session_update_sm_context_request (std::shared_ptr<
memcpy (&dl_teid.teid_gre_key, decoded_msg->dL_NGU_UP_TNLInformation->choice.gTPTunnel->transportLayerAddress.buf, 4);
sm_context_req_msg.set_dl_fteid(dl_teid);
//list of Qos Flows which have been successfully setup or modified
for (int i =0; i< decoded_msg->qosFlowAddOrModifyResponseList->list.count; i++ ){
for (int i =0; i< decoded_msg->qosFlowAddOrModifyResponseList->list.count; i++ ) {
sm_context_req_msg.add_qfi((decoded_msg->qosFlowAddOrModifyResponseList->list.array[i])->qosFlowIdentifier);
}
//TODO:
......@@ -1281,13 +1276,13 @@ void smf_context::handle_pdu_session_update_sm_context_request (std::shared_ptr<
break;
//PDU Session Modification procedure
case n2_sm_info_type_e::PDU_RES_MOD_FAIL:{
case n2_sm_info_type_e::PDU_RES_MOD_FAIL: {
//TODO:
}
break;
//PDU Session Release procedure (UE-initiated, Section 4.3.4.2@3GPP TS 23.502 or SMF-Requested)(Step 2)
case n2_sm_info_type_e::PDU_RES_REL_RSP:{
case n2_sm_info_type_e::PDU_RES_REL_RSP: {
//TODO:
}
break;
......@@ -1303,7 +1298,7 @@ void smf_context::handle_pdu_session_update_sm_context_request (std::shared_ptr<
}
//Step 3. For Service Request
if (!sm_context_req_msg.n1_sm_msg_is_set() and !sm_context_req_msg.n2_sm_info_is_set() and sm_context_req_msg.upCnx_state_is_set()){
if (!sm_context_req_msg.n1_sm_msg_is_set() and !sm_context_req_msg.n2_sm_info_is_set() and sm_context_req_msg.upCnx_state_is_set()) {
procedure_type = session_management_procedures_type_e::SERVICE_REQUEST_UE_TRIGGERED_STEP1;
//if request accepted-> set unCnxState to ACTIVATING
//Update upCnxState
......@@ -1314,7 +1309,7 @@ void smf_context::handle_pdu_session_update_sm_context_request (std::shared_ptr<
//get QFIs associated with PDU session ID
std::vector<smf_qos_flow> qos_flows = {};
sp.get()->get_qos_flows(qos_flows);
for (auto i: qos_flows){
for (auto i: qos_flows) {
sm_context_req_msg.add_qfi(i.qfi.qfi);
}
//TODO: to be completed
......@@ -1322,7 +1317,7 @@ void smf_context::handle_pdu_session_update_sm_context_request (std::shared_ptr<
}
//Step 4. Create a procedure for update sm context and let the procedure handle the request if necessary
if (update_upf){
if (update_upf) {
//TODO:
session_update_sm_context_procedure* proc = new session_update_sm_context_procedure(sp);
std::shared_ptr<smf_procedure> sproc = std::shared_ptr<smf_procedure>(proc);
......@@ -1361,7 +1356,7 @@ bool smf_context::find_dnn_subscription(const snssai_t& snssai, std::shared_ptr<
{
Logger::smf_app().info( "find_dnn_subscription: %d, map size %d", (uint8_t)snssai.sST, dnn_subscriptions.size());
//std::unique_lock<std::recursive_mutex> lock(m_context);
if (dnn_subscriptions.count((uint8_t)snssai.sST) > 0 ){
if (dnn_subscriptions.count((uint8_t)snssai.sST) > 0) {
ss = dnn_subscriptions.at((uint8_t)snssai.sST);
return true;
}
......@@ -1474,7 +1469,7 @@ void session_management_subscription::insert_dnn_configuration(std::string dnn,
//------------------------------------------------------------------------------
void session_management_subscription::find_dnn_configuration(std::string dnn, std::shared_ptr<dnn_configuration_t>& dnn_configuration){
Logger::smf_app().info( "find_dnn_configuration with dnn %s", dnn.c_str());
if (dnn_configurations.count(dnn) > 0){
if (dnn_configurations.count(dnn) > 0) {
dnn_configuration = dnn_configurations.at(dnn);
}
}
......
......@@ -35,6 +35,7 @@ void qos_flow_context_updated::set_cause(const uint8_t cause)
{
cause_value = cause;
}
//-----------------------------------------------------------------------------
void qos_flow_context_updated::set_qfi(const pfcp::qfi_t& q)
{
......@@ -166,7 +167,6 @@ void pdu_session_msg::set_pdu_session_type (uint8_t const& pdu_session_type)
m_pdu_session_type = pdu_session_type;
}
//-----------------------------------------------------------------------------
extended_protocol_discriminator_t pdu_session_create_sm_context::get_epd() const
{
......@@ -354,7 +354,6 @@ std::string pdu_session_create_sm_context_response::get_amf_url() const
}
//-----------------------------------------------------------------------------
/* pdu_session_update_sm_context_request */
std::string pdu_session_update_sm_context_request::get_n2_sm_information() const{
return m_n2_sm_information;
}
......@@ -408,7 +407,7 @@ void pdu_session_update_sm_context_request::add_qfi(pfcp::qfi_t const& qfi)
//-----------------------------------------------------------------------------
void pdu_session_update_sm_context_request::get_qfis(std::vector<pfcp::qfi_t>& q)
{
for (auto qfi: qfis){
for (auto qfi: qfis) {
q.push_back(qfi);
}
}
......@@ -427,7 +426,6 @@ void pdu_session_update_sm_context_request::get_dl_fteid(fteid_t& t)
}
//-----------------------------------------------------------------------------
void pdu_session_update_sm_context_request::set_upCnx_state(std::string const& value)
{
......@@ -465,7 +463,6 @@ void pdu_session_update_sm_context_response::set_pti(procedure_transaction_id_t
m_pti = pti;
}
//-----------------------------------------------------------------------------
void pdu_session_update_sm_context_response::set_cause(uint8_t cause)
{
......@@ -477,7 +474,6 @@ uint8_t pdu_session_update_sm_context_response::get_cause(){
return m_cause;
}
//-----------------------------------------------------------------------------
std::string pdu_session_update_sm_context_response::get_n2_sm_information() const{
return m_n2_sm_information;
......
......@@ -55,10 +55,10 @@ void smf_n10_task (void*);
* To read content of the response from UDM
*/
static std::size_t callback(
const char* in,
const char *in,
std::size_t size,
std::size_t num,
std::string* out)
std::string *out)
{
const std::size_t totalBytes(size * num);
out->append(in, totalBytes);
......@@ -84,7 +84,6 @@ void smf_n10_task (void *args_p)
//}
break;
case TERMINATE:
if (itti_msg_terminate *terminate = dynamic_cast<itti_msg_terminate*>(msg)) {
Logger::smf_n10().info( "Received terminate message");
......@@ -92,7 +91,6 @@ void smf_n10_task (void *args_p)
}
break;
default:
Logger::smf_n10().info( "no handler for msg type %d", msg->msg_type);
}
......@@ -113,9 +111,9 @@ smf_n10::smf_n10 ()
}
void smf_n10::handle_receive_sm_data_notification()
{
//TODO:
}
bool smf_n10::get_sm_data(supi64_t& supi, std::string& dnn, snssai_t& snssai, std::shared_ptr<session_management_subscription> subscription)
......@@ -134,7 +132,7 @@ bool smf_n10::get_sm_data(supi64_t& supi, std::string& dnn, snssai_t& snssai, st
std::string url = std::string(inet_ntoa (*((struct in_addr *)&smf_cfg.udm_addr.ipv4_addr))) + ":" + std::to_string(smf_cfg.udm_addr.port) + "/nudm-sdm/v2/" + std::to_string(supi) +"/sm-data";
Logger::smf_n10().debug("[get_sm_data] UDM's URL: %s ", url.c_str());
if(curl) {
if (curl) {
CURLcode res = {};
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
......@@ -151,20 +149,19 @@ bool smf_n10::get_sm_data(supi64_t& supi, std::string& dnn, snssai_t& snssai, st
curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get());
//curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData);
int numRetries = 0;
while (numRetries < UDM_NUMBER_RETRIES){
while (numRetries < UDM_NUMBER_RETRIES) {
res = curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
Logger::smf_n10().debug("[get_sm_data] Response from UDM, Http Code: %d ", httpCode);
if (static_cast<http_response_codes_e> (httpCode) == http_response_codes_e::HTTP_RESPONSE_CODE_OK)
{
if (static_cast<http_response_codes_e> (httpCode) == http_response_codes_e::HTTP_RESPONSE_CODE_OK) {
Logger::smf_n10().debug("[get_sm_data] Got successful response from UDM, URL: %s ", url.c_str());
//Logger::smf_n10().debug("[get_sm_data] Http Data from UDM: %s ", *httpData.get());
try{
try {
jsonData = nlohmann::json::parse(*httpData.get());
//curl_easy_cleanup(curl);
break;
} catch (json::exception& e){
} catch (json::exception& e) {
Logger::smf_n10().warn("[get_sm_data] Couldn't Parse json data from UDM");
}
numRetries++;
......@@ -178,7 +175,7 @@ bool smf_n10::get_sm_data(supi64_t& supi, std::string& dnn, snssai_t& snssai, st
}
//process the response
if (!jsonData.empty()){
if (!jsonData.empty()) {
Logger::smf_n10().debug("[get_sm_data] GET response from UDM %s", jsonData.dump().c_str());
//retrieve SessionManagementSubscription and store in the context
......@@ -230,13 +227,13 @@ bool smf_n10::get_sm_data(supi64_t& supi, std::string& dnn, snssai_t& snssai, st
//sdc = std::shared_ptr<dnn_configuration_t> (dnn_configuration);
subscription->insert_dnn_configuration(it.key(), dnn_configuration);
} catch (nlohmann::json::exception& e){
} catch (nlohmann::json::exception& e) {
Logger::smf_n10().warn("[get_sm_data] exception message %s, exception id %d ", e.what(), e.id);
return false;
}
}
return true;
} else{
} else {
return false;
}
......
......@@ -64,10 +64,10 @@ void smf_n11_task (void*);
// To read content of the response from UDM
static std::size_t callback(
const char* in,
const char *in,
std::size_t size,
std::size_t num,
std::string* out)
std::string *out)
{
const std::size_t totalBytes(size * num);
out->append(in, totalBytes);
......@@ -116,7 +116,7 @@ void smf_n11_task (void *args_p)
smf_n11::smf_n11 ()
{
Logger::smf_n11().startup("Starting...");
if (itti_inst->create_task(TASK_SMF_N11, smf_n11_task, nullptr) ) {
if (itti_inst->create_task(TASK_SMF_N11, smf_n11_task, nullptr)) {
Logger::smf_n11().error( "Cannot create task TASK_SMF_N11" );
throw std::runtime_error( "Cannot create task TASK_SMF_N11" );
}
......@@ -209,7 +209,7 @@ void smf_n11::send_n1n2_message_transfer_request(std::shared_ptr<itti_n11_create
Logger::smf_n11().debug("Sending message to AMF....");
if(curl) {
if (curl) {
CURLcode res = {};
struct curl_slist *headers = nullptr;
struct curl_slist *slist = nullptr;
......@@ -267,9 +267,9 @@ void smf_n11::send_n1n2_message_transfer_request(std::shared_ptr<itti_n11_create
//get cause from the response
json response_data = {};
try{
try {
response_data = json::parse(*httpData.get());
} catch (json::exception& e){
} catch (json::exception& e) {
Logger::smf_n11().error( "Could not get the cause from the response");
//Set the default Cause
response_data["cause"] = "504 Gateway Timeout";
......@@ -283,7 +283,7 @@ void smf_n11::send_n1n2_message_transfer_request(std::shared_ptr<itti_n11_create
itti_msg->set_cause(response_data["cause"]);
if (context_res_msg.get_cause() == REQUEST_ACCEPTED) {
itti_msg->set_msg_type(PDU_SESSION_ESTABLISHMENT_ACCEPT);
}else {
} else {
itti_msg->set_msg_type(PDU_SESSION_ESTABLISHMENT_REJECT);
}
std::shared_ptr<itti_n11_n1n2_message_transfer_response_status> i = std::shared_ptr<itti_n11_n1n2_message_transfer_response_status>(itti_msg);
......@@ -304,7 +304,7 @@ void smf_n11::send_pdu_session_update_sm_context_response(std::shared_ptr<itti_n
{
Logger::smf_n11().debug("Send PDUSessionUpdateContextResponse to AMF ");
switch(sm_context_res->session_procedure_type){
switch (sm_context_res->session_procedure_type) {
case session_management_procedures_type_e::PDU_SESSION_TEST: {
Logger::smf_n11().debug("PDU_SESSION_TEST");
......@@ -384,10 +384,10 @@ void smf_n11::send_pdu_session_update_sm_context_response(Pistache::Http::Respon
nlohmann::json json_data = {};
to_json(json_data, smContextUpdateError);
if (!json_data.empty()){
if (!json_data.empty()) {
httpResponse.headers().add<Pistache::Http::Header::ContentType>(Pistache::Http::Mime::MediaType("application/json"));
httpResponse.send(code, json_data.dump().c_str());
} else{
} else {
httpResponse.send(code);
}
......@@ -433,10 +433,10 @@ void smf_n11::send_pdu_session_create_sm_context_response(Pistache::Http::Respon
Logger::smf_n11().debug("[SMF N11] Send PDUSessionUpdateContextResponse to AMF!");
nlohmann::json json_data = {};
to_json(json_data, smContextCreatedData);
if (!json_data.empty()){
if (!json_data.empty()) {
httpResponse.headers().add<Pistache::Http::Header::ContentType>(Pistache::Http::Mime::MediaType("application/json"));
httpResponse.send(code, json_data.dump().c_str());
} else{
} else {
httpResponse.send(code);
}
......
......@@ -72,17 +72,16 @@ extern smf_app *smf_app_inst;
* To read content of the response from UDM
*/
static std::size_t callback(
const char* in,
const char *in,
std::size_t size,
std::size_t num,
std::string* out)
std::string *out)
{
const std::size_t totalBytes(size * num);
out->append(in, totalBytes);
return totalBytes;
}
//-----------------------------------------------------------------------------------------------------
void smf_n1_n2::create_n1_sm_container(pdu_session_msg& msg, uint8_t n1_msg_type, std::string& nas_msg_str, cause_value_5gsm_e sm_cause)
{
......@@ -94,7 +93,7 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg& msg, uint8_t n1_msg_type
int bytes = { 0 };
int length = BUF_LEN;
unsigned char data[BUF_LEN] = {'\0'};
memset(data,0,sizeof(data));
memset(data, 0, sizeof(data));
nas_message_t nas_msg = {};
memset(&nas_msg, 0, sizeof(nas_message_t));
......@@ -117,7 +116,7 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg& msg, uint8_t n1_msg_type
//PDU Session Establishment Accept is including in the N1N2MessageTransfer Request sent from SMF to AMF (PDU Session Establishment procedure)
//PDU_SESSION_CREATE_SM_CONTEXT_RESPONSE
if (msg.get_msg_type() != PDU_SESSION_CREATE_SM_CONTEXT_RESPONSE){
if (msg.get_msg_type() != PDU_SESSION_CREATE_SM_CONTEXT_RESPONSE) {
Logger::smf_app().error("Cannot create an PDU Session Establishment Accept for this message (type %d)",msg.get_msg_type());
return;
}
......@@ -427,7 +426,7 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg& msg, uint8_t n1_msg_type
}
break;
default:{
default: {
Logger::smf_app().debug("Unknown PDU Session Type");
//TODO:
}
......@@ -438,7 +437,7 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg& msg, uint8_t n1_msg_type
bytes = nas_message_encode (data, &nas_msg, sizeof(data)/*don't know the size*/, nullptr);
Logger::smf_app().debug("Buffer Data: ");
for(int i = 0; i < bytes; i++)
for (int i = 0; i < bytes; i++)
printf("%02x ", data[i]);
printf(" (bytes %d)\n", bytes);
......@@ -453,7 +452,7 @@ void smf_n1_n2::create_n2_sm_information(pdu_session_msg& msg, uint8_t ngap_msg_
//TODO: To be filled with the correct parameters
Logger::smf_app().info("Create N2 SM Information, NGAP message type %d, IE type %d", ngap_msg_type, ngap_ie_type);
switch (ngap_ie_type){
switch (ngap_ie_type) {
//PDU Session Resource Setup Request Transfer
//need to be verified with Wireshark (case 1)
......@@ -581,7 +580,7 @@ void smf_n1_n2::create_n2_sm_information(pdu_session_msg& msg, uint8_t ngap_msg_
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters.qosCharacteristics.choice.nonDynamic5QI = (Ngap_NonDynamic5QIDescriptor_t *)(calloc (1, sizeof(Ngap_NonDynamic5QIDescriptor_t)));
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters.qosCharacteristics.choice.nonDynamic5QI->fiveQI = (uint8_t) qos_flow.qfi.qfi;
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters.allocationAndRetentionPriority.priorityLevelARP = qos_flow.qos_profile.arp.priority_level;
if (qos_flow.qos_profile.arp.preempt_cap.compare("NOT_PREEMPT") == 0){
if (qos_flow.qos_profile.arp.preempt_cap.compare("NOT_PREEMPT") == 0) {
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters.allocationAndRetentionPriority.pre_emptionCapability = Ngap_Pre_emptionCapability_shall_not_trigger_pre_emption;
} else {
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters.allocationAndRetentionPriority.pre_emptionCapability = Ngap_Pre_emptionCapability_may_trigger_pre_emption;
......@@ -607,9 +606,9 @@ void smf_n1_n2::create_n2_sm_information(pdu_session_msg& msg, uint8_t ngap_msg_
}
Logger::smf_app().debug("N2 SM buffer data: ");
for(int i = 0; i < er.encoded; i++)
printf("%02x ", (char)buffer[i]);
printf(" (%d bytes)\n",(int)er.encoded);
for( int i = 0; i < er.encoded; i++)
printf("%02x ", (char) buffer[i]);
printf(" (%d bytes)\n",(int) er.encoded);
std::string ngap_message ((char*) buffer, er.encoded);
ngap_msg_str = ngap_message;
}
......@@ -712,12 +711,12 @@ void smf_n1_n2::create_n2_sm_information(pdu_session_msg& msg, uint8_t ngap_msg_
ngap_QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters->qosCharacteristics.choice.nonDynamic5QI = (Ngap_NonDynamic5QIDescriptor_t *)(calloc (1, sizeof(Ngap_NonDynamic5QIDescriptor_t)));
ngap_QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters->qosCharacteristics.choice.nonDynamic5QI->fiveQI = qos_flow.qfi.qfi;
ngap_QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters->allocationAndRetentionPriority.priorityLevelARP = qos_flow.qos_profile.priority_level;
if (qos_flow.qos_profile.arp.preempt_cap.compare("NOT_PREEMPT") == 0){
if (qos_flow.qos_profile.arp.preempt_cap.compare("NOT_PREEMPT") == 0) {
ngap_QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters->allocationAndRetentionPriority.pre_emptionCapability = Ngap_Pre_emptionCapability_shall_not_trigger_pre_emption;
} else {
ngap_QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters->allocationAndRetentionPriority.pre_emptionCapability = Ngap_Pre_emptionCapability_may_trigger_pre_emption;
}
if ( qos_flow.qos_profile.arp.preempt_vuln.compare("NOT_PREEMPTABLE") == 0) {
if (qos_flow.qos_profile.arp.preempt_vuln.compare("NOT_PREEMPTABLE") == 0) {
ngap_QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters->allocationAndRetentionPriority.pre_emptionVulnerability = Ngap_Pre_emptionVulnerability_not_pre_emptable;
} else {
ngap_QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters->allocationAndRetentionPriority.pre_emptionVulnerability = Ngap_Pre_emptionVulnerability_pre_emptable;
......@@ -734,19 +733,18 @@ void smf_n1_n2::create_n2_sm_information(pdu_session_msg& msg, uint8_t ngap_msg_
//encode
size_t buffer_size = 512;
char *buffer = (char *)calloc(1, buffer_size);
char *buffer = (char *) calloc(1, buffer_size);
asn_enc_rval_t er = aper_encode_to_buffer(&asn_DEF_Ngap_PDUSessionResourceModifyRequestTransfer, nullptr, ngap_IEs, (void *)buffer, buffer_size);
if(er.encoded < 0)
{
if (er.encoded < 0) {
Logger::smf_app().warn("[Create N2 SM Information] NGAP PDU Session Resource Modify Request Transfer encode failed, er.encoded: %d", er.encoded);
return;
}
Logger::smf_app().debug("N2 SM buffer data: ");
for(int i = 0; i < er.encoded; i++)
printf("%02x ", (char)buffer[i]);
printf(" (%d bytes)\n",(int)er.encoded);
printf("%02x ", (char) buffer[i]);
printf(" (%d bytes)\n",(int) er.encoded);
std::string ngap_message ((char*) buffer, er.encoded);
ngap_msg_str = ngap_message;
}
......@@ -791,18 +789,17 @@ void smf_n1_n2::create_n2_sm_information(pdu_session_msg& msg, uint8_t ngap_msg_
//encode
size_t buffer_size = 512;
char *buffer = (char *)calloc(1,buffer_size);
char *buffer = (char *) calloc(1,buffer_size);
asn_enc_rval_t er = aper_encode_to_buffer(&asn_DEF_Ngap_PDUSessionResourceSetupResponseTransfer, nullptr, ngap_resource_response_transfer, (void *)buffer, buffer_size);
if(er.encoded < 0)
{
if (er.encoded < 0) {
Logger::smf_app().warn("[Create N2 SM Information] NGAP PDU Session Resource Setup Response Transfer encode failed, er.encoded: %d", er.encoded);
return;
}
Logger::smf_app().debug("N2 SM buffer data: ");
for(int i = 0; i < er.encoded; i++)
printf("%02x ", (char)buffer[i]);
for (int i = 0; i < er.encoded; i++)
printf("%02x ", (char) buffer[i]);
Logger::smf_app().debug(" (%d bytes) \n",er.encoded);
std::string ngap_message ((char*) buffer, er.encoded);
ngap_msg_str = ngap_message;
......@@ -842,18 +839,17 @@ void smf_n1_n2::create_n2_sm_information(pdu_session_msg& msg, uint8_t ngap_msg_
//encode
size_t buffer_size = 512;
char *buffer = (char *)calloc(1,buffer_size);
char *buffer = (char *) calloc(1,buffer_size);
asn_enc_rval_t er = aper_encode_to_buffer(&asn_DEF_Ngap_PDUSessionResourceReleaseCommandTransfer, nullptr, ngap_resource_release_command_transfer, (void *)buffer, buffer_size);
if(er.encoded < 0)
{
if (er.encoded < 0) {
Logger::smf_app().warn("[Create N2 SM Information] NGAP PDU Session Release Command encode failed, er.encoded: %d", er.encoded);
return;
}
Logger::smf_app().debug("N2 SM buffer data: ");
for(int i = 0; i < er.encoded; i++)
printf("%02x ", (char)buffer[i]);
for (int i = 0; i < er.encoded; i++)
printf("%02x ", (char) buffer[i]);
Logger::smf_app().debug(" (%d bytes) \n",er.encoded);
std::string ngap_message ((char*) buffer, er.encoded);
ngap_msg_str = ngap_message;
......@@ -878,15 +874,15 @@ int smf_n1_n2::decode_n1_sm_container(nas_message_t& nas_msg, std::string& n1_sm
int decoder_rc = RETURNok;
unsigned int msg_len = n1_sm_msg.length();
char *data = (char *)malloc(msg_len + 1);
char *data = (char *) malloc(msg_len + 1);
memset(data, 0, msg_len + 1);
memcpy ((void *)data, (void *)n1_sm_msg.c_str(), msg_len);
uint8_t *data_hex = (uint8_t *)malloc(msg_len/2 + 1);
uint8_t *data_hex = (uint8_t *) malloc(msg_len/2 + 1);
conv::ascii_to_hex (data_hex, (const char *) data);
printf("Content: ");
for(int i = 0;i<msg_len/2;i++)
printf(" %02x ",data_hex[i]);
for (int i = 0; i < msg_len/2; i++)
printf(" %02x ", data_hex[i]);
printf("\n");
//decode the NAS message (using NAS lib)
......@@ -911,14 +907,13 @@ int smf_n1_n2::decode_n1_sm_container(nas_message_t& nas_msg, std::string& n1_sm
int smf_n1_n2::decode_n2_sm_information(std::shared_ptr<Ngap_PDUSessionResourceSetupResponseTransfer_t>& ngap_IE, std::string& n2_sm_info){
Logger::smf_app().info("Decode NGAP message (PDUSessionResourceSetupResponseTransfer) from N2 SM Information");
unsigned int data_len = n2_sm_info.length();
unsigned char *data = (unsigned char *)malloc(data_len + 1);
unsigned char *data = (unsigned char *) malloc(data_len + 1);
memset(data, 0, data_len + 1);
memcpy ((void *)data, (void *)n2_sm_info.c_str(), data_len);
//PDUSessionResourceSetupResponseTransfer
asn_dec_rval_t rc = asn_decode(nullptr, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_Ngap_PDUSessionResourceSetupResponseTransfer, (void **)&ngap_IE, (void *)data, data_len);
if(rc.code != RC_OK)
{
if (rc.code != RC_OK) {
Logger::smf_api_server().warn("asn_decode failed with code %d", rc.code );
return RETURNerror;
}
......@@ -931,14 +926,13 @@ int smf_n1_n2::decode_n2_sm_information(std::shared_ptr<Ngap_PDUSessionResourceM
Logger::smf_app().info("Decode NGAP message (Ngap_PDUSessionResourceModifyResponseTransfer) from N2 SM Information");
unsigned int data_len = n2_sm_info.length();
unsigned char *data = (unsigned char *)malloc(data_len + 1);
unsigned char *data = (unsigned char *) malloc(data_len + 1);
memset(data, 0, data_len + 1);
memcpy ((void *)data, (void *)n2_sm_info.c_str(), data_len);
//Ngap_PDUSessionResourceModifyResponseTransfer
asn_dec_rval_t rc = asn_decode(nullptr, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_Ngap_PDUSessionResourceModifyResponseTransfer, (void **)&ngap_IE, (void *)data, data_len);
if(rc.code != RC_OK)
{
if (rc.code != RC_OK) {
Logger::smf_api_server().warn("asn_decode failed with code %d", rc.code );
return RETURNerror;
}
......
......@@ -49,7 +49,6 @@ extern smf_n4 *smf_n4_inst;
void smf_n4_task (void*);
//------------------------------------------------------------------------------
void smf_n4_task (void *args_p)
{
const task_id_t task_id = TASK_SMF_N4;
......@@ -204,7 +203,7 @@ smf_n4::smf_n4() : pfcp_l4_stack(string(inet_ntoa(smf_cfg.n4.addr4)), smf_cfg.n4
cp_function_features.load = 0;
if (itti_inst->create_task(TASK_SMF_N4, smf_n4_task, nullptr) ) {
if (itti_inst->create_task(TASK_SMF_N4, smf_n4_task, nullptr)) {
Logger::smf_n4().error( "Cannot create task TASK_SMF_N4" );
throw std::runtime_error( "Cannot create task TASK_SMF_N4" );
}
......@@ -262,6 +261,7 @@ void smf_n4::handle_receive_pfcp_msg(pfcp_msg& msg, const endpoint& remote_endpo
Logger::smf_n4().info( "handle_receive_pfcp_msg msg %d length %d, unknown, discarded!", msg.get_message_type(), msg.get_message_length());
}
}
//------------------------------------------------------------------------------
void smf_n4::handle_receive_heartbeat_request(pfcp::pfcp_msg& msg, const endpoint& remote_endpoint)
{
......@@ -280,6 +280,7 @@ void smf_n4::handle_receive_heartbeat_request(pfcp::pfcp_msg& msg, const endpoin
send_heartbeat_response(remote_endpoint, trxn_id);
}
}
//------------------------------------------------------------------------------
void smf_n4::handle_receive_heartbeat_response(pfcp::pfcp_msg& msg, const endpoint& remote_endpoint)
{
......@@ -298,6 +299,7 @@ void smf_n4::handle_receive_heartbeat_response(pfcp::pfcp_msg& msg, const endpoi
pfcp_associations::get_instance().handle_receive_heartbeat_response(trxn_id);
}
}
//------------------------------------------------------------------------------
void smf_n4::handle_receive_association_setup_request(pfcp::pfcp_msg& msg, const endpoint& remote_endpoint)
{
......@@ -388,6 +390,7 @@ void smf_n4::handle_receive_association_setup_response(pfcp::pfcp_msg& msg, cons
}
}
//------------------------------------------------------------------------------
void smf_n4::handle_receive_session_establishment_response(pfcp::pfcp_msg& msg, const endpoint& remote_endpoint)
{
......@@ -411,6 +414,7 @@ void smf_n4::handle_receive_session_establishment_response(pfcp::pfcp_msg& msg,
}
// else ignore
}
//------------------------------------------------------------------------------
void smf_n4::handle_receive_session_modification_response(pfcp::pfcp_msg& msg, const endpoint& remote_endpoint)
{
......@@ -434,6 +438,7 @@ void smf_n4::handle_receive_session_modification_response(pfcp::pfcp_msg& msg, c
}
// else ignore
}
//------------------------------------------------------------------------------
void smf_n4::handle_receive_session_deletion_response(pfcp::pfcp_msg& msg, const endpoint& remote_endpoint)
{
......@@ -457,6 +462,7 @@ void smf_n4::handle_receive_session_deletion_response(pfcp::pfcp_msg& msg, const
}
// else ignore
}
//------------------------------------------------------------------------------
void smf_n4::handle_receive_session_report_request(pfcp::pfcp_msg& msg, const endpoint& remote_endpoint)
{
......@@ -486,11 +492,13 @@ void smf_n4::send_n4_msg(itti_n4_association_setup_response& i)
{
send_response(i.r_endpoint, i.pfcp_ies, i.trxn_id);
}
//------------------------------------------------------------------------------
void smf_n4::send_n4_msg(itti_n4_session_report_response& i)
{
send_response(i.r_endpoint, i.seid, i.pfcp_ies, i.trxn_id);
}
//------------------------------------------------------------------------------
void smf_n4::send_heartbeat_request(std::shared_ptr<pfcp_association>& a)
{
......@@ -510,6 +518,7 @@ void smf_n4::send_heartbeat_request(std::shared_ptr<pfcp_association>& a)
Logger::smf_n4().warn( "TODO send_heartbeat_request() node_id IPV6, FQDN!");
}
}
//------------------------------------------------------------------------------
void smf_n4::send_heartbeat_response(const endpoint& r_endpoint, const uint64_t trxn_id)
{
......@@ -518,21 +527,25 @@ void smf_n4::send_heartbeat_response(const endpoint& r_endpoint, const uint64_t
h.set(r);
send_response(r_endpoint, h, trxn_id);
}
//------------------------------------------------------------------------------
void smf_n4::send_n4_msg(itti_n4_session_establishment_request& i)
{
send_request(i.r_endpoint, i.seid, i.pfcp_ies, TASK_SMF_N4, i.trxn_id);
}
//------------------------------------------------------------------------------
void smf_n4::send_n4_msg(itti_n4_session_modification_request& i)
{
send_request(i.r_endpoint, i.seid, i.pfcp_ies, TASK_SMF_N4, i.trxn_id);
}
//------------------------------------------------------------------------------
void smf_n4::send_n4_msg(itti_n4_session_deletion_request& i)
{
send_request(i.r_endpoint, i.seid, i.pfcp_ies, TASK_SMF_N4, i.trxn_id);
}
//------------------------------------------------------------------------------
void smf_n4::handle_receive(char* recv_buffer, const std::size_t bytes_transferred, const endpoint& remote_endpoint)
{
......@@ -549,6 +562,7 @@ void smf_n4::handle_receive(char* recv_buffer, const std::size_t bytes_transferr
Logger::smf_n4().info( "handle_receive exception %s", e.what());
}
}
//------------------------------------------------------------------------------
void smf_n4::time_out_itti_event(const uint32_t timer_id)
{
......
......@@ -39,14 +39,14 @@ public:
struct in6_addr prefix;
int prefix_len;
ipv6_pool() : prefix(), prefix_len(0) {}
ipv6_pool(): prefix(), prefix_len(0) {}
ipv6_pool(const struct in6_addr prfix, const int prfix_len) {
prefix = prfix;
prefix_len = prfix_len;
}
ipv6_pool(const ipv6_pool& p) : prefix(p.prefix), prefix_len(p.prefix_len) {}
ipv6_pool(const ipv6_pool& p): prefix(p.prefix), prefix_len(p.prefix_len) {}
bool alloc_address(struct in6_addr& allocated)
......@@ -59,7 +59,6 @@ public:
};
class ipv4_pool {
protected:
struct in_addr start;
......@@ -104,7 +103,7 @@ public:
start.s_addr = 0;
};
ipv4_pool(const struct in_addr first, const uint32_t range) : alloc() {
ipv4_pool(const struct in_addr first, const uint32_t range): alloc() {
start.s_addr = first.s_addr;
num = range;
int range32 = range >> 5;
......@@ -117,7 +116,7 @@ public:
}
};
ipv4_pool(const ipv4_pool& p) : num(p.num), alloc(p.alloc) {
ipv4_pool(const ipv4_pool& p): num(p.num), alloc(p.alloc) {
start.s_addr = p.start.s_addr;
};
......@@ -156,7 +155,7 @@ public:
std::vector<uint32_t> ipv4_pool_ids;
std::vector<uint32_t> ipv6_pool_ids;
apn_dynamic_pools() : ipv4_pool_ids(), ipv6_pool_ids() {}
apn_dynamic_pools(): ipv4_pool_ids(), ipv6_pool_ids() {}
void add_ipv4_pool_id(const uint32_t id)
{
......@@ -175,7 +174,7 @@ private:
std::map<std::string, apn_dynamic_pools> apns;
paa_dynamic() : ipv4_pools(), ipv6_pools(), apns() {};
paa_dynamic(): ipv4_pools(), ipv6_pools(), apns() {};
public:
static paa_dynamic& get_instance()
......@@ -277,7 +276,7 @@ public:
} else if (paa.pdn_type.pdn_type == PDN_TYPE_E_IPV4V6) {
bool success = false;
std::vector<uint32_t>::const_iterator it4 = {};
for (it4 = apn_pool.ipv4_pool_ids.begin();it4 != apn_pool.ipv4_pool_ids.end(); ++it4) {
for (it4 = apn_pool.ipv4_pool_ids.begin(); it4 != apn_pool.ipv4_pool_ids.end(); ++it4) {
if (ipv4_pools[*it4].free_address(paa.ipv4_address)) {
return true;
}
......@@ -295,7 +294,7 @@ public:
{
if (apns.count(apn_label)) {
apn_dynamic_pools& apn_pool = apns[apn_label];
for (std::vector<uint32_t>::const_iterator it4 = apn_pool.ipv4_pool_ids.begin();it4 != apn_pool.ipv4_pool_ids.end(); ++it4) {
for (std::vector<uint32_t>::const_iterator it4 = apn_pool.ipv4_pool_ids.begin(); it4 != apn_pool.ipv4_pool_ids.end(); ++it4) {
if (ipv4_pools[*it4].free_address(ipv4_address)) {
return true;
}
......
......@@ -59,7 +59,7 @@ int n4_session_restore_procedure::run()
{
if (pending_sessions.size()) {
itti_n4_restore *itti_msg = nullptr;
for (std::set<pfcp::fseid_t>::iterator it=pending_sessions.begin(); it!=pending_sessions.end();++it) {
for (std::set<pfcp::fseid_t>::iterator it=pending_sessions.begin(); it!=pending_sessions.end(); ++it) {
if (!itti_msg) {
itti_msg = new itti_n4_restore(TASK_SMF_N4, TASK_SMF_APP);
}
......@@ -146,8 +146,7 @@ int session_create_sm_context_procedure::run(std::shared_ptr<itti_n11_create_sm_
//wys-test-add
pfcp::outer_header_creation_t outer_header_creation = {};
if(smf_cfg.test_upf_cfg.is_test)
{
if(smf_cfg.test_upf_cfg.is_test) {
//wys-test-add
destination_interface.interface_value = pfcp::INTERFACE_VALUE_ACCESS; // ACCESS is for downlink, CORE for uplink
outer_header_creation.teid = 1;
......@@ -383,7 +382,7 @@ void session_create_sm_context_procedure::handle_itti_msg (itti_n4_session_estab
n11_triggered_pending->res.n1n2_message_transfer_data["n1MessageContainer"]["n1MessageContent"]["contentId"] = "n1SmMsg"; //part 2
//N2SM
if (n11_triggered_pending->res.get_cause() == REQUEST_ACCEPTED){
if (n11_triggered_pending->res.get_cause() == REQUEST_ACCEPTED) {
//TODO: fill the content of N1N2MessageTransferReqData
n11_triggered_pending->res.n1n2_message_transfer_data["n2InfoContainer"]["n2InformationClass"] = "SM";
n11_triggered_pending->res.n1n2_message_transfer_data["n2InfoContainer"]["smInfo"]["PduSessionId"] = n11_triggered_pending->res.get_pdu_session_id();
......@@ -449,16 +448,16 @@ int session_update_sm_context_procedure::run(std::shared_ptr<itti_n11_update_sm_
std::vector<pfcp::qfi_t> list_of_qfis_to_be_modified = {};
sm_context_req_msg.get_qfis(list_of_qfis_to_be_modified);
for (auto i:list_of_qfis_to_be_modified){
for (auto i:list_of_qfis_to_be_modified) {
Logger::smf_app().debug( "qfi to be modified: %d", i.qfi);
}
::fteid_t dl_fteid = {};
sm_context_req_msg.get_dl_fteid(dl_fteid); //eNB's fteid
for (auto qfi: list_of_qfis_to_be_modified){
for (auto qfi: list_of_qfis_to_be_modified) {
smf_qos_flow qos_flow = {};
if (!ppc->get_qos_flow(qfi, qos_flow)){ //no QoS flow found
if (!ppc->get_qos_flow(qfi, qos_flow)) { //no QoS flow found
Logger::smf_app().error( "Update SM Context procedure: could not found QoS flow with QFI %d", qfi.qfi);
//Set cause to SYSTEM_FAILURE and send response
qos_flow_context_updated qcu = {};
......@@ -469,7 +468,7 @@ int session_update_sm_context_procedure::run(std::shared_ptr<itti_n11_update_sm_
}
pfcp::far_id_t far_id = {};
pfcp::pdr_id_t pdr_id = {};
if ((dl_fteid == qos_flow.dl_fteid) and (not qos_flow.released)){
if ((dl_fteid == qos_flow.dl_fteid) and (not qos_flow.released)) {
Logger::smf_app().debug( "Update SM Context procedure: QFI %d dl_fteid unchanged", qfi.qfi);
qos_flow_context_updated qcu = {};
qcu.set_cause(REQUEST_ACCEPTED);
......@@ -571,11 +570,11 @@ int session_update_sm_context_procedure::run(std::shared_ptr<itti_n11_update_sm_
source_interface.interface_value = pfcp::INTERFACE_VALUE_CORE;
//local_fteid.from_core_fteid(peb.sgw_fteid_s5_s8_up);
if ( ppc->ipv4) {
if (ppc->ipv4) {
ue_ip_address.v4 = 1;
ue_ip_address.ipv4_address.s_addr = ppc->ipv4_address.s_addr;
}
if ( ppc->ipv6) {
if (ppc->ipv6) {
ue_ip_address.v6 = 1;
ue_ip_address.ipv6_address = ppc->ipv6_address;
}
......@@ -685,7 +684,7 @@ void session_update_sm_context_procedure::handle_itti_msg (itti_n4_session_modif
for (std::map<uint8_t, qos_flow_context_updated>::iterator it = qos_flow_context_to_be_updateds.begin(); it != qos_flow_context_to_be_updateds.end(); ++it)
Logger::smf_app().debug("qos_flow_context_to_be_modifieds qfi %d", it->first);
for (auto it_created_pdr : resp.pfcp_ies.created_pdrs) {
for (auto it_created_pdr: resp.pfcp_ies.created_pdrs) {
pfcp::pdr_id_t pdr_id = {};
if (it_created_pdr.get(pdr_id)) {
smf_qos_flow flow = {};
......@@ -757,7 +756,7 @@ void session_update_sm_context_procedure::handle_itti_msg (itti_n4_session_modif
if (cause.cause_value == CAUSE_VALUE_REQUEST_ACCEPTED) {
// TODO failed rule id
for (auto it_update_far : n4_triggered->pfcp_ies.update_fars) {
for (auto it_update_far: n4_triggered->pfcp_ies.update_fars) {
pfcp::far_id_t far_id = {};
if (it_update_far.get(far_id)) {
smf_qos_flow flow = {};
......@@ -803,7 +802,7 @@ void session_update_sm_context_procedure::handle_itti_msg (itti_n4_session_modif
//change value here to test the corresponding message
session_procedure_type = session_management_procedures_type_e::PDU_SESSION_TEST;
switch (session_procedure_type){
switch (session_procedure_type) {
//FOR TESTING PURPOSE
case session_management_procedures_type_e::PDU_SESSION_TEST: {
......@@ -833,7 +832,7 @@ void session_update_sm_context_procedure::handle_itti_msg (itti_n4_session_modif
break;
//PDU Session Establishment UE-Requested
case session_management_procedures_type_e::PDU_SESSION_ESTABLISHMENT_UE_REQUESTED:{
case session_management_procedures_type_e::PDU_SESSION_ESTABLISHMENT_UE_REQUESTED: {
//No need to create N1/N2 Container, just Cause
Logger::smf_app().info( "PDU Session Establishment Request (UE-Initiated)");
n11_triggered_pending->res.sm_context_updated_data["cause"] = n11_triggered_pending->res.get_cause();
......@@ -841,7 +840,7 @@ void session_update_sm_context_procedure::handle_itti_msg (itti_n4_session_modif
break;
//UE-Triggered Service Request Procedure (Step 1)
case session_management_procedures_type_e::SERVICE_REQUEST_UE_TRIGGERED_STEP1:{
case session_management_procedures_type_e::SERVICE_REQUEST_UE_TRIGGERED_STEP1: {
// Create N2 SM Information: PDU Session Resource Setup Request Transfer IE
//N2 SM Information
......@@ -860,7 +859,7 @@ void session_update_sm_context_procedure::handle_itti_msg (itti_n4_session_modif
break;
//UE-triggered Service Request (Step 2)
case session_management_procedures_type_e::SERVICE_REQUEST_UE_TRIGGERED_STEP2:{
case session_management_procedures_type_e::SERVICE_REQUEST_UE_TRIGGERED_STEP2: {
//No need to create N1/N2 Container, just Cause
Logger::smf_app().info( "UE Triggered Service Request (Step 2)");
n11_triggered_pending->res.sm_context_updated_data["cause"] = n11_triggered_pending->res.get_cause();
......@@ -868,7 +867,7 @@ void session_update_sm_context_procedure::handle_itti_msg (itti_n4_session_modif
break;
//PDU Session Modification UE-initiated (Step 1)
case session_management_procedures_type_e::PDU_SESSION_MODIFICATION_UE_INITIATED_STEP1:{
case session_management_procedures_type_e::PDU_SESSION_MODIFICATION_UE_INITIATED_STEP1: {
//N1 SM: PDU Session Modification Command​
//N2 SM: PDU Session Resource Modify Request Transfer IE
......@@ -895,7 +894,7 @@ void session_update_sm_context_procedure::handle_itti_msg (itti_n4_session_modif
break;
//PDU Session Modification UE-initiated (Step 2)
case session_management_procedures_type_e::PDU_SESSION_MODIFICATION_UE_INITIATED_STEP2:{
case session_management_procedures_type_e::PDU_SESSION_MODIFICATION_UE_INITIATED_STEP2: {
//No need to create N1/N2 Container
Logger::smf_app().info( "PDU Session Modification UE-initiated (Step 2)");
//TODO:
......@@ -903,7 +902,7 @@ void session_update_sm_context_procedure::handle_itti_msg (itti_n4_session_modif
break;
//PDU Session Modification UE-initiated (Step 3)
case session_management_procedures_type_e::PDU_SESSION_MODIFICATION_UE_INITIATED_STEP3:{
case session_management_procedures_type_e::PDU_SESSION_MODIFICATION_UE_INITIATED_STEP3: {
//No need to create N1/N2 Container
Logger::smf_app().info( "PDU Session Modification UE-initiated (Step 3)");
//TODO:
......@@ -911,7 +910,7 @@ void session_update_sm_context_procedure::handle_itti_msg (itti_n4_session_modif
break;
//PDU Session Release UE-initiated (Step 1)
case session_management_procedures_type_e::PDU_SESSION_RELEASE_UE_REQUESTED_STEP1:{
case session_management_procedures_type_e::PDU_SESSION_RELEASE_UE_REQUESTED_STEP1: {
//N1 SM: PDU Session Release Command​
//N2 SM: PDU Session Resource Release Command Transfer
Logger::smf_app().info( "PDU Session Release UE-initiated (Step 1))");
......@@ -939,7 +938,7 @@ void session_update_sm_context_procedure::handle_itti_msg (itti_n4_session_modif
break;
//PDU Session Release UE-initiated (Step 2)
case session_management_procedures_type_e::PDU_SESSION_RELEASE_UE_REQUESTED_STEP2:{
case session_management_procedures_type_e::PDU_SESSION_RELEASE_UE_REQUESTED_STEP2: {
//No need to create N1/N2 Container
Logger::smf_app().info( "PDU Session Release UE-initiated (Step 2)");
//TODO:
......@@ -947,7 +946,7 @@ void session_update_sm_context_procedure::handle_itti_msg (itti_n4_session_modif
break;
//PDU Session Release UE-initiated (Step 3)
case session_management_procedures_type_e::PDU_SESSION_RELEASE_UE_REQUESTED_STEP3:{
case session_management_procedures_type_e::PDU_SESSION_RELEASE_UE_REQUESTED_STEP3: {
//No need to create N1/N2 Container
Logger::smf_app().info( "PDU Session Release UE-initiated (Step 3)");
//TODO:
......@@ -973,8 +972,7 @@ void session_update_sm_context_procedure::handle_itti_msg (itti_n4_session_modif
// For LADN, the SMF subscribes to the UE moving into or out of LADN service area event notification by providing the LADN DNN as an indicator for the Area Of Interest
//see step 17@section 4.3.2.2.1@3GPP TS 23.502
if (cause.cause_value != CAUSE_VALUE_REQUEST_ACCEPTED)
{
if (cause.cause_value != CAUSE_VALUE_REQUEST_ACCEPTED) {
//TODO: Nsmf_PDUSession_SMContextStatusNotify
/* If the PDU Session establishment is not successful, the SMF informs the AMF by invoking Nsmf_PDUSession_SMContextStatusNotify (Release). The SMF also releases any N4
session(s) created, any PDU Session address if allocated (e.g. IP address) and releases the association with PCF, if any.
......
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