Commit c649e5a8 authored by Tien-Thinh Nguyen's avatar Tien-Thinh Nguyen

update default qos rule/flow, add smf-requested modification

parent 251022eb
......@@ -55,29 +55,31 @@ class itti_nx_msg : public itti_msg {
};
//-----------------------------------------------------------------------------
class itti_nx_modify_pdu_session_request_network_requested : public itti_nx_msg {
class itti_nx_trigger_pdu_session_modification : public itti_nx_msg {
public:
itti_nx_modify_pdu_session_request_network_requested(const task_id_t orig,
itti_nx_trigger_pdu_session_modification(const task_id_t orig,
const task_id_t dest)
:
itti_nx_msg(NX_SESSION_MODIFICATION_REQUEST_NETWORK_REQUESTED, orig, dest) {
itti_nx_msg(NX_TRIGGER_SESSION_MODIFICATION, orig, dest) {
}
itti_nx_modify_pdu_session_request_network_requested(
const itti_nx_modify_pdu_session_request_network_requested &i)
itti_nx_trigger_pdu_session_modification(
const itti_nx_trigger_pdu_session_modification &i)
:
itti_nx_msg(i) {
itti_nx_msg(i),
msg(i.msg) {
}
itti_nx_modify_pdu_session_request_network_requested(
const itti_nx_modify_pdu_session_request_network_requested &i,
const task_id_t orig, const task_id_t dest)
itti_nx_trigger_pdu_session_modification(
const itti_nx_trigger_pdu_session_modification &i, const task_id_t orig,
const task_id_t dest)
:
itti_nx_msg(i, orig, dest) {
itti_nx_msg(i, orig, dest),
msg() {
}
const char* get_msg_name() {
return "NX_SESSION_MODIFICATION_REQUEST_NETWORK_REQUESTED";
return "NX_TRIGGER_PDU_SESSION_MODIFICATION";
}
;
// smf::pdu_session_create_sm_context_request req;
smf::pdu_session_modification_network_requested msg;
};
#endif /* ITTI_MSG_NX_HPP_INCLUDED_ */
......@@ -116,7 +116,7 @@ typedef enum {
N11_SESSION_N1N2_MESSAGE_TRANSFER_RESPONSE_STATUS,
N11_SESSION_RELEASE_SM_CONTEXT_REQUEST,
N11_SESSION_RELEASE_SM_CONTEXT_RESPONSE,
NX_SESSION_MODIFICATION_REQUEST_NETWORK_REQUESTED,
NX_TRIGGER_SESSION_MODIFICATION,
UDP_INIT,
UDP_DATA_REQ,
UDP_DATA_IND,
......
......@@ -8,9 +8,8 @@
int encode_qos_rules(QOSRules qosrules, uint8_t iei, uint8_t *buffer,
uint32_t len) {
uint8_t *len_qosrule = NULL;
uint8_t *len_qosrulesie = NULL;
uint8_t len_pos_qos_rule = 0;
uint8_t bitstream = 0;
uint32_t encoded = 0;
int encode_result = 0;
......@@ -35,6 +34,9 @@ int encode_qos_rules(QOSRules qosrules, uint8_t iei, uint8_t *buffer,
ENCODE_U8(buffer + encoded, qosrules.qosrulesie[i].qosruleidentifer,
encoded);
uint8_t *len_qosrule = NULL;
uint8_t len_pos_qos_rule = 0;
len_qosrule = buffer + encoded;
encoded++;
encoded++;
......@@ -115,6 +117,7 @@ int encode_qos_rules(QOSRules qosrules, uint8_t iei, uint8_t *buffer,
//len of qos rule ie
ENCODE_U16(len_qosrulesie, encoded - len_pos_qos_rulesie, temp);
return encoded;
}
......@@ -135,16 +138,107 @@ int decode_qos_rules(QOSRules *qosrules, uint8_t iei, uint8_t *buffer,
CHECK_LENGTH_DECODER(len - decoded, qosrules->lengthofqosrulesie);
qosrules->qosrulesie = (QOSRulesIE*) calloc(1, sizeof(QOSRulesIE));
QOSRulesIE *qosrulesie = (QOSRulesIE*) calloc(1, sizeof(QOSRulesIE));
int size = 0;
i = 0;
int pre_decoded_pos = decoded;
while (decoded < qosrules->lengthofqosrulesie) {
DECODE_U8(buffer + decoded, qosrulesie->qosruleidentifer,
decoded);
DECODE_U16(buffer + decoded, qosrulesie->LengthofQoSrule,
decoded);
DECODE_U8(buffer + decoded, bitstream, decoded);
qosrulesie->ruleoperationcode = (bitstream >> 5);
qosrulesie->dqrbit = (bitstream >> 4) & 0x01;
qosrulesie->numberofpacketfilters = bitstream & 0x0f;
if (qosrulesie->ruleoperationcode
== MODIFY_EXISTING_QOS_RULE_AND_DELETE_PACKET_FILTERS) {
qosrulesie->packetfilterlist.modifyanddelete =
(ModifyAndDelete*) calloc(
qosrulesie->numberofpacketfilters,
sizeof(ModifyAndDelete));
for (j = 0; j < qosrulesie->numberofpacketfilters; j++) {
DECODE_U8(buffer + decoded, bitstream, decoded);
qosrulesie->packetfilterlist.modifyanddelete[j]
.packetfilteridentifier = bitstream & 0x0f;
}
DECODE_U8(buffer + decoded, bitstream, decoded); //QoS rule precedence
qosrulesie->qosruleprecedence = bitstream;
DECODE_U8(buffer + decoded, bitstream, decoded); //QoS flow identifier (QFI)
qosrulesie->segregation = (bitstream >> 6) & 0x01;
qosrulesie->qosflowidentifer = bitstream & 0x3f;
} else if ((qosrulesie->ruleoperationcode == CREATE_NEW_QOS_RULE)
|| (qosrulesie->ruleoperationcode
== MODIFY_EXISTING_QOS_RULE_AND_ADD_PACKET_FILTERS)
|| (qosrulesie->ruleoperationcode
== MODIFY_EXISTING_QOS_RULE_AND_REPLACE_ALL_PACKET_FILTERS)) {
qosrulesie->packetfilterlist
.create_modifyandadd_modifyandreplace =
(Create_ModifyAndAdd_ModifyAndReplace*) calloc(
qosrulesie->numberofpacketfilters,
sizeof(Create_ModifyAndAdd_ModifyAndReplace));
for (j = 0; j < qosrulesie->numberofpacketfilters; j++) {
DECODE_U8(buffer + decoded, bitstream, decoded);
qosrulesie->packetfilterlist
.create_modifyandadd_modifyandreplace[j].packetfilterdirection =
(bitstream >> 4) & 0x03;
qosrulesie->packetfilterlist
.create_modifyandadd_modifyandreplace[j].packetfilteridentifier =
bitstream & 0x0f;
uint8_t *lenghtofpacketfiltercontents = (uint8_t*) (*(buffer + decoded)
- 1);
decoded++;
DECODE_U8(buffer + decoded, bitstream, decoded);
qosrulesie->packetfilterlist
.create_modifyandadd_modifyandreplace[j].packetfiltercontents
.component_type = bitstream;
if (qosrulesie->packetfilterlist
.create_modifyandadd_modifyandreplace[j].packetfiltercontents
.component_type != QOS_RULE_MATCHALL_TYPE) {
if ((decode_result = decode_bstring(
&qosrulesie->packetfilterlist
.create_modifyandadd_modifyandreplace[j].packetfiltercontents
.component_value,
lenghtofpacketfiltercontents, buffer + decoded, len - decoded))
< 0)
return decode_result;
else
decoded += decode_result;
}
}
DECODE_U8(buffer + decoded, bitstream, decoded);
qosrulesie->qosruleprecedence = bitstream;
DECODE_U8(buffer + decoded, bitstream, decoded);
qosrulesie->segregation = (bitstream >> 6) & 0x01;
qosrulesie->qosflowidentifer = bitstream & 0x3f;
}
i++;
size++;
}
free(qosrulesie);
qosrulesie = NULL;
decoded = pre_decoded_pos;
qosrules->qosrulesie = (QOSRulesIE*) calloc(size, sizeof(QOSRulesIE));
i = 0;
//for(i=0;i<numberrules;i++)
while (decoded < qosrules->lengthofqosrulesie) {
DECODE_U8(buffer + decoded, qosrules->qosrulesie[i].qosruleidentifer,
decoded);
// decoded++;
// decoded++;
DECODE_U16(buffer + decoded, qosrules->qosrulesie[i].LengthofQoSrule, decoded);
DECODE_U16(buffer + decoded, qosrules->qosrulesie[i].LengthofQoSrule,
decoded);
DECODE_U8(buffer + decoded, bitstream, decoded);
qosrules->qosrulesie[i].ruleoperationcode = (bitstream >> 5);
......@@ -220,6 +314,7 @@ int decode_qos_rules(QOSRules *qosrules, uint8_t iei, uint8_t *buffer,
i++;
}
return decoded;
}
......
......@@ -924,15 +924,29 @@ void smf_app::handle_pdu_session_release_sm_context_request(
}
//------------------------------------------------------------------------------
void smf_app::handle_network_requested_pdu_session_modification() {
std::shared_ptr<itti_nx_modify_pdu_session_request_network_requested> itti_msg =
std::make_shared<itti_nx_modify_pdu_session_request_network_requested>(
void smf_app::trigger_pdu_session_modification () {
//SMF-requested session modification, see section 4.3.3.2@3GPP TS 23.502
//The SMF may decide to modify PDU Session. This procedure also may be
//triggered based on locally configured policy or triggered from the (R)AN (see clause 4.2.6 and clause 4.9.1).
//It may also be triggered if the UP connection is activated (as described in Service Request procedure) and the
//SMF has marked that the status of one or more QoS Flows are deleted in the 5GC but not synchronized with
//the UE yet.
std::shared_ptr<itti_nx_trigger_pdu_session_modification> itti_msg =
std::make_shared<itti_nx_trigger_pdu_session_modification>(
TASK_SMF_N11, TASK_SMF_APP);
//step 1. collect the necessary information
supi_t supi = { };
std::string dnn;
pdu_session_id_t pdu_session_id = { 0 };
snssai_t nssai = { };
snssai_t snssai = { };
itti_msg->msg.set_supi(supi);
itti_msg->msg.set_dnn(dnn);
itti_msg->msg.set_pdu_session_id(pdu_session_id);
itti_msg->msg.set_snssai(snssai);
supi64_t supi64 = smf_supi_to_u64(supi);
......@@ -944,20 +958,13 @@ void smf_app::handle_network_requested_pdu_session_modification() {
Logger::smf_app().debug("Retrieve SMF context with SUPI " SUPI_64_FMT "",
supi64);
} else {
Logger::smf_app().debug("SMF context with SUPI " SUPI_64_FMT "does not exist",
supi64);
return;
}
//get dnn context
std::shared_ptr<dnn_context> sd = { };
if (!sc.get()->find_dnn_context(nssai, dnn, sd)) {
if (nullptr == sd.get()) {
return;
}
}
// handle the message in smf_context
// sc.get()->handle_network_requested_pdu_session_modification(itti_msg);
sc.get()->handle_pdu_session_modification_network_requested(itti_msg);
}
......
......@@ -218,11 +218,11 @@ class smf_app {
std::shared_ptr<itti_n11_release_sm_context_request> smreq);
/*
* Handle network-requested pdu session modification
* Trigger pdu session modification
* @param should be updated
* @return void
*/
void handle_network_requested_pdu_session_modification();
void trigger_pdu_session_modification();
/*
* Verify if SM Context is existed for this Supi
......
......@@ -98,69 +98,6 @@ void smf_qos_flow::deallocate_ressources() {
(uint8_t) qfi.qfi);
}
//------------------------------------------------------------------------------
void smf_qos_flow::get_default_qos_rule(QOSRulesIE &qos_rule) const {
Logger::smf_app().info("Get default QoS Rule this QoS Flow (%d)",
(uint8_t) qfi.qfi);
for (auto it : qos_rules) {
if (it.second.dqrbit == THE_QOS_RULE_IS_DEFAULT_QOS_RULE) {
qos_rule = it.second;
return;
}
}
}
//------------------------------------------------------------------------------
void smf_qos_flow::get_qos_rule(uint8_t rule_id, QOSRulesIE &qos_rule) const {
Logger::smf_app().info("Find QoS Rule with Rule Id %d", (uint8_t) rule_id);
if (qos_rules.count(rule_id) > 0) {
qos_rule = qos_rules.at(rule_id);
}
}
//------------------------------------------------------------------------------
void smf_qos_flow::update_qos_rule(QOSRulesIE qos_rule) {
Logger::smf_app().info("Update QoS Rule with Rule Id %d",
(uint8_t) qos_rule.qosruleidentifer);
uint8_t rule_id = qos_rule.qosruleidentifer;
if ((rule_id >= QOS_RULE_IDENTIFIER_FIRST )
and (rule_id <= QOS_RULE_IDENTIFIER_LAST )) {
qos_rules.erase(rule_id);
qos_rules.insert(std::pair<uint8_t, QOSRulesIE>(rule_id, qos_rule));
//marked to be synchronised with UE
qos_rules_to_be_synchronised.push_back(rule_id);
Logger::smf_app().trace("smf_qos_flow::update_qos_rule(%d) success",
rule_id);
} else {
Logger::smf_app().error(
"smf_qos_flow::update_qos_rule(%d) failed, invalid Rule Id", rule_id);
}
}
//------------------------------------------------------------------------------
void smf_qos_flow::add_qos_rule(QOSRulesIE qos_rule) {
Logger::smf_app().info("Add QoS Rule with Rule Id %d",
(uint8_t) qos_rule.qosruleidentifer);
uint8_t rule_id = qos_rule.qosruleidentifer;
if ((rule_id >= QOS_RULE_IDENTIFIER_FIRST )
and (rule_id <= QOS_RULE_IDENTIFIER_LAST )) {
if (qos_rules.count(rule_id) > 0) {
Logger::smf_app().error(
"smf_qos_flow::add_qos_rule(%d) failed, rule existed", rule_id);
} else {
qos_rules.insert(std::pair<uint8_t, QOSRulesIE>(rule_id, qos_rule));
Logger::smf_app().trace("smf_qos_flow::add_qos_rule(%d) success",
rule_id);
}
} else {
Logger::smf_app().error(
"smf_qos_flow::add_qos_rule(%d) failed, invalid Rule Id", rule_id);
}
}
//------------------------------------------------------------------------------
void smf_pdu_session::set(const paa_t &paa) {
switch (paa.pdn_type.pdn_type) {
......@@ -285,9 +222,10 @@ bool smf_pdu_session::get_qos_flow(const pfcp::qfi_t &qfi, smf_qos_flow &q) {
return false;
}
//------------------------------------------------------------------------------
smf_qos_flow& smf_pdu_session::get_qos_flow(const pfcp::qfi_t &qfi) {
return qos_flows[qfi.qfi];
void smf_pdu_session::set_default_qos_flow(const pfcp::qfi_t &qfi) {
default_qfi.qfi = qfi.qfi;
}
//------------------------------------------------------------------------------
......@@ -413,7 +351,7 @@ std::string smf_pdu_session::toString() const {
if (ipv6)
s.append("\tPAA IPv6:\t\t\t").append(conv::toString(ipv6_address)).append(
"\n");
s.append("\tDefault EBI:\t\t\t").append(std::to_string(default_bearer.ebi))
s.append("\tDefault QFI:\t\t\t").append(std::to_string(default_qfi.qfi))
.append("\n");
s.append("\tSEID:\t\t\t").append(std::to_string(seid)).append("\n");
......@@ -452,15 +390,93 @@ pdn_type_t smf_pdu_session::get_pdn_type() const {
//------------------------------------------------------------------------------
void smf_pdu_session::get_qos_rules_to_be_synchronised(
std::vector<QOSRulesIE> &qos_rules) const {
std::vector<QOSRulesIE> &rules) const {
for (auto it : qos_rules_to_be_synchronised) {
if (qos_rules.count(it) > 0)
rules.push_back(qos_rules.at(it));
}
}
// for (std::map<uint8_t, smf_qos_flow>::iterator it = qos_flows.begin();
// it != qos_flows.end(); ++it) {
for (auto it : qos_flows) {
for (auto rule : it.second.qos_rules_to_be_synchronised) {
QOSRulesIE qos_rule = it.second.qos_rules.at(rule);
qos_rules.push_back(qos_rule);
//------------------------------------------------------------------------------
void smf_pdu_session::get_qos_rules(pfcp::qfi_t qfi,
std::vector<QOSRulesIE> &rules) const {
for (auto it : qos_rules) {
if (it.first == qfi.qfi)
rules.push_back(qos_rules.at(it.first));
}
}
//------------------------------------------------------------------------------
bool smf_pdu_session::get_default_qos_rule(QOSRulesIE &qos_rule) const {
Logger::smf_app().info("Get default QoS Rule this PDU Session (ID %d)",
pdu_session_id);
for (auto it : qos_rules) {
if (it.second.dqrbit == THE_QOS_RULE_IS_DEFAULT_QOS_RULE) {
qos_rule = it.second;
return true;
}
}
return false;
}
//------------------------------------------------------------------------------
bool smf_pdu_session::get_qos_rule(uint8_t rule_id,
QOSRulesIE &qos_rule) const {
Logger::smf_app().info("Find QoS Rule with Rule Id %d", (uint8_t) rule_id);
if (qos_rules.count(rule_id) > 0) {
qos_rule = qos_rules.at(rule_id);
}
return false;
}
//------------------------------------------------------------------------------
void smf_pdu_session::update_qos_rule(QOSRulesIE qos_rule) {
Logger::smf_app().info("Update QoS Rule with Rule Id %d",
(uint8_t) qos_rule.qosruleidentifer);
uint8_t rule_id = qos_rule.qosruleidentifer;
if ((rule_id >= QOS_RULE_IDENTIFIER_FIRST )
and (rule_id <= QOS_RULE_IDENTIFIER_LAST )) {
if (qos_rules.count(rule_id) > 0) {
qos_rules.erase(rule_id);
qos_rules.insert(std::pair<uint8_t, QOSRulesIE>(rule_id, qos_rule));
//marked to be synchronised with UE
qos_rules_to_be_synchronised.push_back(rule_id);
Logger::smf_app().trace("smf_pdu_session::update_qos_rule(%d) success",
rule_id);
} else {
Logger::smf_app().error(
"smf_pdu_session::update_qos_rule(%d) failed, rule does not existed",
rule_id);
}
} else {
Logger::smf_app().error(
"smf_pdu_session::update_qos_rule(%d) failed, invalid Rule Id",
rule_id);
}
}
//------------------------------------------------------------------------------
void smf_pdu_session::add_qos_rule(QOSRulesIE qos_rule) {
Logger::smf_app().info("Add QoS Rule with Rule Id %d",
(uint8_t) qos_rule.qosruleidentifer);
uint8_t rule_id = qos_rule.qosruleidentifer;
if ((rule_id >= QOS_RULE_IDENTIFIER_FIRST )
and (rule_id <= QOS_RULE_IDENTIFIER_LAST )) {
if (qos_rules.count(rule_id) > 0) {
Logger::smf_app().error(
"smf_pdu_session::add_qos_rule(%d) failed, rule existed", rule_id);
} else {
qos_rules.insert(std::pair<uint8_t, QOSRulesIE>(rule_id, qos_rule));
Logger::smf_app().trace("smf_pdu_session::add_qos_rule(%d) success",
rule_id);
}
} else {
Logger::smf_app().error(
"smf_pdu_session::add_qos_rule(%d) failed, invalid Rule Id", rule_id);
}
}
......@@ -620,7 +636,7 @@ void smf_context::get_default_qos_rule(QOSRulesIE &qos_rule,
Logger::smf_app().info("Get default QoS rule (PDU session type %d)",
pdu_session_type);
//see section 9.11.4.13 @ 3GPP TS 24.501 and section 5.7.1.4 @ 3GPP TS 23.501
qos_rule.qosruleidentifer = 0x01;
qos_rule.qosruleidentifer = 0x01; //be updated later on
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)
......@@ -638,16 +654,16 @@ void smf_context::get_default_qos_rule(QOSRulesIE &qos_rule,
qos_rule.packetfilterlist.create_modifyandadd_modifyandreplace[0]
.packetfiltercontents.component_type = QOS_RULE_MATCHALL_TYPE;
//qos_rule.packetfilterlist.create_modifyandadd_modifyandreplace[0].packetfiltercontents.component_value = bfromcstralloc(2, "\0");
qos_rule.qosruleprecedence = 1;
qos_rule.qosruleprecedence = 0xff;
}
if (pdu_session_type == PDU_SESSION_TYPE_E_UNSTRUCTURED) {
qos_rule.numberofpacketfilters = 0;
qos_rule.qosruleprecedence = 1;
qos_rule.qosruleprecedence = 0xff;
}
qos_rule.segregation = SEGREGATION_NOT_REQUESTED;
qos_rule.qosflowidentifer = 60; //TODO: default value
qos_rule.qosflowidentifer = 6; //TODO: default value
Logger::smf_app().debug(
"Default QoSRules: %x %x %x %x %x %x %x %x %x",
......@@ -668,20 +684,21 @@ void smf_context::get_default_qos_rule(QOSRulesIE &qos_rule,
//------------------------------------------------------------------------------
void smf_context::get_default_qos_flow_description(
QOSFlowDescriptionsContents &qos_flow_description,
uint8_t pdu_session_type) {
uint8_t pdu_session_type, const pfcp::qfi_t &qfi) {
//TODO, update according to PDU Session type
Logger::smf_app().info(
"Get default QoS Flow Description (PDU session type %d)",
pdu_session_type);
qos_flow_description.qfi = 60;
qos_flow_description.qfi = qfi.qfi;
qos_flow_description.operationcode = CREATE_NEW_QOS_FLOW_DESCRIPTION;
qos_flow_description.e = PARAMETERS_LIST_IS_INCLUDED;
qos_flow_description.numberofparameters = 3;
qos_flow_description.numberofparameters = 1;
qos_flow_description.parameterslist = (ParametersList*) calloc(
3, sizeof(ParametersList));
qos_flow_description.parameterslist[0].parameteridentifier =
PARAMETER_IDENTIFIER_5QI;
qos_flow_description.parameterslist[0].parametercontents._5qi = 60; //TODO: ??
qos_flow_description.parameterslist[0].parametercontents._5qi = qfi.qfi;
/*
qos_flow_description.parameterslist[1].parameteridentifier =
PARAMETER_IDENTIFIER_GFBR_UPLINK;
qos_flow_description.parameterslist[1].parametercontents
......@@ -696,16 +713,15 @@ void smf_context::get_default_qos_flow_description(
GFBRORMFBR_VALUE_IS_INCREMENTED_IN_MULTIPLES_OF_1MBPS;
qos_flow_description.parameterslist[2].parametercontents
.gfbrormfbr_uplinkordownlink.value = 0x10;
*/
Logger::smf_app().debug(
"Default Qos Flow Description: %x %x %x %x %x %x %x %x %x %x %x %x",
qos_flow_description.qfi,
qos_flow_description.operationcode,
qos_flow_description.e,
qos_flow_description.numberofparameters,
"Default Qos Flow Description: %x %x %x %x %x %x",
qos_flow_description.qfi, qos_flow_description.operationcode,
qos_flow_description.e, qos_flow_description.numberofparameters,
qos_flow_description.parameterslist[0].parameteridentifier,
qos_flow_description.parameterslist[0].parametercontents._5qi,
qos_flow_description.parameterslist[1].parameteridentifier,
qos_flow_description.parameterslist[0].parametercontents._5qi
/* qos_flow_description.parameterslist[1].parameteridentifier,
qos_flow_description.parameterslist[1].parametercontents
.gfbrormfbr_uplinkordownlink.uint,
qos_flow_description.parameterslist[1].parametercontents
......@@ -714,7 +730,8 @@ void smf_context::get_default_qos_flow_description(
qos_flow_description.parameterslist[2].parametercontents
.gfbrormfbr_uplinkordownlink.uint,
qos_flow_description.parameterslist[2].parametercontents
.gfbrormfbr_uplinkordownlink.value);
.gfbrormfbr_uplinkordownlink.value
*/);
}
//------------------------------------------------------------------------------
......@@ -1033,7 +1050,6 @@ void smf_context::handle_pdu_session_create_sm_context_request(
switch (sp->pdn_type.pdn_type) {
case PDN_TYPE_E_IPV4: {
if (!pco_ids.ci_ipv4_address_allocation_via_dhcpv4) { //use SM NAS signalling
//use NAS signalling
//static or dynamic address allocation
bool paa_res = false; //how to define static or dynamic
//depend of subscription information: staticIpAddress in DNN Configuration
......@@ -1151,7 +1167,7 @@ void smf_context::handle_pdu_session_create_sm_context_request(
"PDU Session Establishment Request: Create SM Context Request procedure failed");
remove_procedure(proc);
//Set cause to error to trigger PDU session establishment reject (step 10)
//sm_context_resp->res.set_cause(UNKNOWN_ERROR);
sm_context_resp->res.set_cause(REMOTE_PEER_NOT_RESPONDING); //TODO: check cause
}
} else { //if request is rejected
......@@ -1185,16 +1201,6 @@ void smf_context::handle_pdu_session_create_sm_context_request(
//clear the created context??
//TODO:
/*
for (auto it : sm_context_resp->res.bearer_contexts_to_be_created) {
gtpv2c::bearer_context_created_within_create_session_response bcc = {};
cause_t bcc_cause = {.cause_value = NO_RESOURCES_AVAILABLE, .pce = 0, .bce = 0, .cs = 0};
bcc.set(it.eps_bearer_id);
bcc.set(bcc_cause);
//sm_context_resp->res.add_bearer_context_created(bcc);
}
*/
//Create PDU Session Establishment Reject and embedded in Namf_Communication_N1N2MessageTransfer Request
Logger::smf_app().debug("Create PDU Session Establishment Reject");
//TODO: Should check Cause for other cases
......@@ -1391,10 +1397,6 @@ void smf_context::handle_pdu_session_update_sm_context_request(
uint16_t length_of_rule_ie = 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;
pfcp::qfi_t generated_qfi = { .qfi = 0 };
//QOSFlowDescriptions
......@@ -1416,7 +1418,7 @@ void smf_context::handle_pdu_session_update_sm_context_request(
for (int i = 0; i < number_of_flow_descriptions; i++) {
if (qos_flow_description[i].qfi == NO_QOS_FLOW_IDENTIFIER_ASSIGNED) {
//TODO: generate new QFI
generated_qfi.qfi = 77; //hardcoded for now
generated_qfi.qfi = (uint8_t) 77; //hardcoded for now
qos_flow_description_content = qos_flow_description[i];
qos_flow_description_content.qfi = generated_qfi.qfi;
break;
......@@ -1427,29 +1429,32 @@ void smf_context::handle_pdu_session_update_sm_context_request(
int i = 0;
int length_of_rule = 0;
while (length_of_rule_ie > 0) {
QOSRulesIE qos_rules_ie = { };
qos_rules_ie = decoded_nas_msg.plain.sm
.pdu_session_modification_request.qosrules.qosrulesie[i];
uint8_t rule_id = { 0 };
QOSRulesIE qos_rule = { };
pfcp::qfi_t qfi = { };
smf_qos_flow qos_flow = { };
length_of_rule = qos_rules_ie[i].LengthofQoSrule;
length_of_rule = qos_rules_ie.LengthofQoSrule;
//If UE requested a new GBR flow
if ((qos_rules_ie[i].ruleoperationcode == CREATE_NEW_QOS_RULE)
and (qos_rules_ie[i].segregation == SEGREGATION_REQUESTED)) {
if ((qos_rules_ie.ruleoperationcode == CREATE_NEW_QOS_RULE)
and (qos_rules_ie.segregation == SEGREGATION_REQUESTED)) {
//Add a new QoS Flow
if (qos_rules_ie[i].qosruleidentifer
== NO_QOS_RULE_IDENTIFIER_ASSIGNED) {
if (qos_rules_ie.qosruleidentifer == NO_QOS_RULE_IDENTIFIER_ASSIGNED) {
//Generate a new QoS rule
sp.get()->generate_qos_rule_id(rule_id);
Logger::smf_app().info("Create a new QoS rule (rule Id %d)",
rule_id);
qos_rules_ie[i].qosruleidentifer = rule_id;
qos_rules_ie.qosruleidentifer = rule_id;
}
sp.get()->add_qos_rule(qos_rules_ie);
qfi.qfi = generated_qfi.qfi;
qos_flow.qfi = generated_qfi.qfi;
qos_flow.add_qos_rule(qos_rules_ie[i]);
//set qos_profile from qos_flow_description_content
qos_flow.qos_profile = { };
......@@ -1497,7 +1502,7 @@ void smf_context::handle_pdu_session_update_sm_context_request(
Logger::smf_app().debug("Add new QoS Flow with new QRI");
//mark this rule to be synchronised with the UE
qos_flow.update_qos_rule(qos_rules_ie[i]);
sp.get()->update_qos_rule(qos_rules_ie);
//Add new QoS flow
sp.get()->add_qos_flow(qos_flow);
......@@ -1511,23 +1516,24 @@ void smf_context::handle_pdu_session_update_sm_context_request(
} else { //update existing QRI
Logger::smf_app().debug("Update existing QRI");
qfi.qfi = qos_rules_ie[i].qosflowidentifer;
sp.get()->get_qos_flow(qfi, qos_flow);
qos_flow.update_qos_rule(qos_rules_ie[i]);
qfi.qfi = qos_rules_ie.qosflowidentifer;
if (sp.get()->get_qos_flow(qfi, qos_flow)) {
sp.get()->update_qos_rule(qos_rules_ie);
//update QoS flow
sp.get()->add_qos_flow(qos_flow);
//ADD QoS Flow to be updated
qos_flow_context_updated qcu = { };
qcu.set_qfi(pfcp::qfi_t(qos_flow.qfi));
//qcu.set_ul_fteid(flow.ul_fteid);
//qcu.set_dl_fteid(flow.dl_fteid);
qcu.set_ul_fteid(qos_flow.ul_fteid);
qcu.set_dl_fteid(qos_flow.dl_fteid);
qcu.set_qos_profile(qos_flow.qos_profile);
sm_context_resp_pending->res.add_qos_flow_context_updated(qcu);
}
}
length_of_rule_ie -= (length_of_rule + 3); // 2 for Length of QoS rules IE and 1 for QoS rule identifier
i++;
}
//TODO: MappedEPSBearerContexts
......@@ -1589,7 +1595,6 @@ void smf_context::handle_pdu_session_update_sm_context_request(
sm_context_resp_pending->session_procedure_type = procedure_type;
//don't need to create a procedure to update UPF
free_wrapper((void**) &qos_rules_ie);
free_wrapper((void**) &qos_flow_description);
}
break;
......@@ -1728,52 +1733,6 @@ void smf_context::handle_pdu_session_update_sm_context_request(
//Release the resources related to this PDU Session (in Procedure)
//find DNN context
/* std::shared_ptr<dnn_context> sd = { };
if ((!find_dnn_context(sm_context_req_msg.get_snssai(),
sm_context_req_msg.get_dnn(), sd))
or (nullptr == sd.get())) {
Logger::smf_app().warn(
"Could not find the context for this PDU session");
//create PDU Session Release Reject and send to UE
problem_details.setCause(
pdu_session_application_error_e2str[PDU_SESSION_APPLICATION_ERROR_CONTEXT_NOT_FOUND]);
smContextUpdateError.setError(problem_details);
refToBinaryData.setContentId(N1_SM_CONTENT_ID);
smContextUpdateError.setN1SmMsg(refToBinaryData);
smf_n1_n2_inst.create_n1_sm_container(
sm_context_req_msg, PDU_SESSION_RELEASE_REJECT, n1_sm_msg,
cause_value_5gsm_e::CAUSE_111_PROTOCOL_ERROR_UNSPECIFIED);
smf_app_inst->convert_string_2_hex(n1_sm_msg, n1_sm_msg_hex);
smf_n11_inst->send_pdu_session_update_sm_context_response(
smreq->http_response, smContextUpdateError,
Pistache::Http::Code::Not_Found, n1_sm_msg_hex);
return;
}
//find PDU Session
std::shared_ptr<smf_pdu_session> sp;
if ((!sd.get()->find_pdu_session(
sm_context_req_msg.get_pdu_session_id(), sp))
or (nullptr == sp.get())) {
Logger::smf_app().warn(
"Could not find the context for this PDU session");
//create PDU Session Release Reject and send to UE
problem_details.setCause(
pdu_session_application_error_e2str[PDU_SESSION_APPLICATION_ERROR_CONTEXT_NOT_FOUND]);
smContextUpdateError.setError(problem_details);
refToBinaryData.setContentId(N1_SM_CONTENT_ID);
smContextUpdateError.setN1SmMsg(refToBinaryData);
smf_n1_n2_inst.create_n1_sm_container(
sm_context_req_msg, PDU_SESSION_RELEASE_REJECT, n1_sm_msg,
cause_value_5gsm_e::CAUSE_43_INVALID_PDU_SESSION_IDENTITY);
smf_app_inst->convert_string_2_hex(n1_sm_msg, n1_sm_msg_hex);
smf_n11_inst->send_pdu_session_update_sm_context_response(
smreq->http_response, smContextUpdateError,
Pistache::Http::Code::Not_Found, n1_sm_msg_hex);
return;
}
*/
//get the associated QoS flows: to be used for PFCP Session Modification procedure
std::vector<smf_qos_flow> qos_flows;
sp.get()->get_qos_flows(qos_flows);
......@@ -1894,7 +1853,6 @@ void smf_context::handle_pdu_session_update_sm_context_request(
problem_details.setCause(
pdu_session_application_error_e2str[PDU_SESSION_APPLICATION_ERROR_N2_SM_ERROR]);
smContextUpdateError.setError(problem_details);
//TODO: need to verify with/without N1 SM
refToBinaryData.setContentId(N1_SM_CONTENT_ID);
smContextUpdateError.setN1SmMsg(refToBinaryData);
//PDU Session Establishment Reject
......@@ -1989,7 +1947,6 @@ void smf_context::handle_pdu_session_update_sm_context_request(
smreq->http_response, smContextUpdateError,
Pistache::Http::Code::Forbidden);
return;
}
//see section 8.2.3 (PDU Session Resource Modify) @3GPP TS 38.413
......@@ -2260,6 +2217,46 @@ void smf_context::handle_pdu_session_release_sm_context_request(
}
//------------------------------------------------------------------------------
void smf_context::handle_pdu_session_modification_network_requested(
std::shared_ptr<itti_nx_trigger_pdu_session_modification> itti_msg) {
Logger::smf_app().info(
"Handle a PDU Session Modification Request (SMF-Requested)");
pdu_session_modification_network_requested sm_context_msg = itti_msg->msg;
smf_n1_n2 smf_n1_n2_inst = { };
oai::smf_server::model::SmContextUpdateError smContextUpdateError = { };
oai::smf_server::model::SmContextUpdatedData smContextUpdatedData = { };
oai::smf_server::model::ProblemDetails problem_details = { };
oai::smf_server::model::RefToBinaryData refToBinaryData = { };
std::string n1_sm_msg, n1_sm_msg_hex;
std::string n2_sm_info, n2_sm_info_hex;
//Step 1. get DNN, SMF PDU session context. At this stage, dnn_context and pdu_session must be existed
std::shared_ptr<dnn_context> sd = { };
std::shared_ptr<smf_pdu_session> sp = { };
bool find_dnn = find_dnn_context(sm_context_msg.get_snssai(),
sm_context_msg.get_dnn(), sd);
bool find_pdu = false;
if (find_dnn) {
find_pdu = sd.get()->find_pdu_session(sm_context_msg.get_pdu_session_id(),
sp);
}
if (!find_dnn or !find_pdu) {
//error, send reply to AMF with error code "Context Not Found"
Logger::smf_app().warn("DNN or PDU session context does not exist!");
return;
}
//prepare
// Step 1. verify if dnn context, pdu context exist
// Step 2. prepare information for N1N2MessageTransfer to send to AMF
// Step 3. Send itti to N11 for sending N1N2MessageTranfer
}
//------------------------------------------------------------------------------
void smf_context::insert_dnn_subscription(
const snssai_t &snssai,
......@@ -2360,35 +2357,6 @@ bool dnn_context::find_pdu_session(
return false;
}
/*
//------------------------------------------------------------------------------
void dnn_context::create_or_update_qos_rule(QOSRulesIE &qos_rule,
pfcp::qfi_t qfi,
pdu_session_id_t pdu_session_id) {
//TODO, update according to PDU Session type
Logger::smf_app().info("Create or Update QoS Rule for PDU Session Id %d",
pdu_session_id);
uint8_t rule_id = { };
//get smd_pdu_session
std::shared_ptr<smf_pdu_session> sp = { };
bool find_pdn = find_pdu_session(pdu_session_id, sp);
if (nullptr == sp.get()) {
Logger::smf_app().warn(
"Could not retrieve the corresponding SMF PDU Session context!");
}
smf_qos_flow qos_flow = { };
sp.get()->get_qos_flow(qfi, qos_flow);
qos_flow.update_qos_rule(qos_rule);
//update QoS flow
sp.get()->add_qos_flow(qos_flow);
}
*/
//------------------------------------------------------------------------------
void dnn_context::insert_pdu_session(std::shared_ptr<smf_pdu_session> &sp) {
std::unique_lock<std::recursive_mutex> lock(m_context);
......
......@@ -78,8 +78,6 @@ class smf_qos_flow {
far_id_ul = { };
far_id_dl = { };
released = false;
qos_rules_to_be_synchronised = {};
qos_rules = {};
qos_profile = {};
}
......@@ -97,26 +95,14 @@ class smf_qos_flow {
pfcp::pdr_id_t pdr_id_ul;
pfcp::pdr_id_t pdr_id_dl;
pfcp::precedence_t precedence;
//pfcp::pdi pdi;
// may use std::optional ? (fragment memory)
std::pair<bool, pfcp::far_id_t> far_id_ul;
std::pair<bool, pfcp::far_id_t> far_id_dl;
bool released; // finally seems necessary, TODO try to find heuristic ?
void get_default_qos_rule(QOSRulesIE &qos_rule) const;
void get_qos_rule(uint8_t rule_id, QOSRulesIE &qos_rule) const;
void update_qos_rule(QOSRulesIE qos_rule);
void add_qos_rule(QOSRulesIE qos_rule);
pdu_session_id_t pdu_session_id;
//rule_id <-> qos_rule
std::map<uint8_t, QOSRulesIE> qos_rules;
//std::vector<QOSRulesIE> qos_rules;
std::vector<uint8_t> qos_rules_to_be_synchronised;
//QoS profile
qos_profile_t qos_profile;
//cause
uint8_t cause_value;
qos_profile_t qos_profile; //QoS profile
uint8_t cause_value; //cause
};
......@@ -137,6 +123,7 @@ class smf_pdu_session : public std::enable_shared_from_this<smf_pdu_session> {
up_fseid = { };
qos_flows.clear();
released = false;
default_qfi.qfi = NO_QOS_FLOW_IDENTIFIER_ASSIGNED ;
pdu_session_status = pdu_session_status_e::PDU_SESSION_INACTIVE;
timer_T3590 = ITTI_INVALID_TIMER_ID;
timer_T3591 = ITTI_INVALID_TIMER_ID;
......@@ -152,8 +139,8 @@ class smf_pdu_session : public std::enable_shared_from_this<smf_pdu_session> {
bool get_qos_flow(const pfcp::far_id_t &far_id, smf_qos_flow &q);
bool get_qos_flow(const pfcp::qfi_t &qfi, smf_qos_flow &q);
void add_qos_flow(smf_qos_flow &flow);
smf_qos_flow& get_qos_flow(const pfcp::qfi_t &qfi);
void get_qos_flows(std::vector<smf_qos_flow> &flows);
void set_default_qos_flow(const pfcp::qfi_t &qfi);
bool find_qos_flow(const pfcp::pdr_id_t &pdr_id, smf_qos_flow &flow);
bool has_qos_flow(const pfcp::pdr_id_t &pdr_id, pfcp::qfi_t &qfi);
......@@ -195,10 +182,28 @@ class smf_pdu_session : public std::enable_shared_from_this<smf_pdu_session> {
void generate_qos_rule_id(uint8_t &rule_id);
void release_qos_rule_id(const uint8_t &rule_id);
pdn_type_t get_pdn_type() const;
void get_qos_rules_to_be_synchronised(std::vector<QOSRulesIE> &qos_rules) const;
/*
* Get list of QoS rules associated with a given QFI
* @param [pfcp::qfi_t] qfi
* @param [std::vector<QOSRulesIE> &] rules
* @void
*/
void get_qos_rules(pfcp::qfi_t qfi,
std::vector<QOSRulesIE> &rules) const;
/*
* Get default QoS Rule associated with this PDU Session
* @param [QOSRulesIE &] qos_rule
* @void
*/
bool get_default_qos_rule(QOSRulesIE &qos_rule) const;
bool get_qos_rule(uint8_t rule_id, QOSRulesIE &qos_rule) const;
void update_qos_rule(QOSRulesIE qos_rule);
void add_qos_rule(QOSRulesIE qos_rule);
pdn_type_t get_pdn_type() const;
bool ipv4; // IP Address(es): IPv4 address and/or IPv6 prefix
bool ipv6; // IP Address(es): IPv4 address and/or IPv6 prefix
......@@ -223,7 +228,11 @@ class smf_pdu_session : public std::enable_shared_from_this<smf_pdu_session> {
std::string amf_id;
// QFI <-> QoS Flow
std::map<uint8_t, smf_qos_flow> qos_flows;
//pdu session status
pfcp::qfi_t default_qfi;
// QFI <-> QoS Rules
std::map<uint8_t, QOSRulesIE> qos_rules;
std::vector<uint8_t> qos_rules_to_be_synchronised;
std::vector<uint8_t> qos_rules_to_be_removed;
pdu_session_status_e pdu_session_status;
timer_id_t timer_T3590;
timer_id_t timer_T3591;
......@@ -363,6 +372,9 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
void handle_pdu_session_release_sm_context_request(
std::shared_ptr<itti_n11_release_sm_context_request> smreq);
void handle_pdu_session_modification_network_requested(
std::shared_ptr<itti_nx_trigger_pdu_session_modification> msg);
/*
* Find DNN context with name
* @param [const std::string&] dnn
......@@ -456,7 +468,8 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
void get_default_qos_flow_description(
QOSFlowDescriptionsContents &qos_flow_description,
uint8_t pdu_session_type);
uint8_t pdu_session_type,
const pfcp::qfi_t &qfi);
void get_session_ambr(SessionAMBR &session_ambr, const snssai_t &snssai,
const std::string &dnn);
......
......@@ -51,8 +51,15 @@ void qos_flow_context_updated::set_dl_fteid(const fteid_t &teid) {
}
//-----------------------------------------------------------------------------
void qos_flow_context_updated::set_qos_rule(const QOSRulesIE &rule) {
qos_rule = rule;
void qos_flow_context_updated::add_qos_rule(const QOSRulesIE &rule) {
uint8_t rule_id = rule.qosruleidentifer;
if ((rule_id >= QOS_RULE_IDENTIFIER_FIRST )
and (rule_id <= QOS_RULE_IDENTIFIER_LAST )) {
qos_rules.erase(rule_id);
qos_rules.insert(std::pair<uint8_t, QOSRulesIE>(rule_id, rule));
Logger::smf_app().trace("qos_flow_context_updated::add_qos_rule(%d) success",
rule_id);
}
}
void qos_flow_context_updated::set_qos_profile(const qos_profile_t &profile) {
......@@ -567,3 +574,72 @@ uint8_t pdu_session_release_sm_context_response::get_cause() {
return m_cause;
}
//-----------------------------------------------------------------------------
void pdu_session_modification_network_requested::set_cause(uint8_t cause) {
m_cause = cause;
}
//-----------------------------------------------------------------------------
uint8_t pdu_session_modification_network_requested::get_cause() {
return m_cause;
}
//-----------------------------------------------------------------------------
void pdu_session_modification_network_requested::set_http_code(
Pistache::Http::Code code) {
m_code = code;
}
//-----------------------------------------------------------------------------
Pistache::Http::Code pdu_session_modification_network_requested::get_http_code() {
return m_code;
}
//-----------------------------------------------------------------------------
std::string pdu_session_modification_network_requested::get_n2_sm_information() const {
return m_n2_sm_information;
}
//-----------------------------------------------------------------------------
void pdu_session_modification_network_requested::set_n2_sm_information(
std::string const &value) {
m_n2_sm_information = value;
m_n2_sm_info_is_set = true;
}
//-----------------------------------------------------------------------------
std::string pdu_session_modification_network_requested::get_n1_sm_message() const {
return m_n1_sm_message;
}
//-----------------------------------------------------------------------------
void pdu_session_modification_network_requested::set_n1_sm_message(
std::string const &value) {
m_n1_sm_message = value;
m_n1_sm_msg_is_set = true;
}
//-----------------------------------------------------------------------------
bool pdu_session_modification_network_requested::n1_sm_msg_is_set() const {
return m_n1_sm_msg_is_set;
}
//-----------------------------------------------------------------------------
bool pdu_session_modification_network_requested::n2_sm_info_is_set() const {
return m_n2_sm_info_is_set;
}
//-----------------------------------------------------------------------------
void pdu_session_modification_network_requested::set_amf_url(
std::string const &value) {
amf_url = value;
}
//-----------------------------------------------------------------------------
std::string pdu_session_modification_network_requested::get_amf_url() const {
return amf_url;
}
......@@ -53,6 +53,7 @@ typedef enum {
PDU_SESSION_UPDATE_SM_CONTEXT_RESPONSE,
PDU_SESSION_RELEASE_SM_CONTEXT_REQUEST,
PDU_SESSION_RELEASE_SM_CONTEXT_RESPONSE,
PDU_SESSION_MODIFICATION_SMF_REQUESTED,
PDU_SESSION_MSG_TYPE_MAX
} pdu_session_msg_type_t;
......@@ -67,7 +68,7 @@ class qos_flow_context_updated {
qfi(),
ul_fteid(),
dl_fteid(),
qos_rule(),
// qos_rule(),
qos_profile(),
to_be_removed(false) {
}
......@@ -76,14 +77,15 @@ class qos_flow_context_updated {
void set_qfi(const pfcp::qfi_t &q);
void set_ul_fteid(const fteid_t &teid);
void set_dl_fteid(const fteid_t &teid);
void set_qos_rule(const QOSRulesIE &rule);
void add_qos_rule (const QOSRulesIE &rule);
void set_qos_profile(const qos_profile_t &profile);
void set_priority_level(uint8_t p);
uint8_t cause_value;
pfcp::qfi_t qfi;
fteid_t ul_fteid;
fteid_t dl_fteid;
QOSRulesIE qos_rule;
// QOSRulesIE qos_rule;
std::map <uint8_t, QOSRulesIE> qos_rules;
qos_profile_t qos_profile;
bool to_be_removed;
};
......@@ -580,6 +582,56 @@ class pdu_session_release_sm_context_response : public pdu_session_msg {
uint8_t m_cause;
};
//---------------------------------------------------------------------------------------
class pdu_session_modification_network_requested : public pdu_session_msg {
public:
pdu_session_modification_network_requested()
:
pdu_session_msg(PDU_SESSION_MODIFICATION_SMF_REQUESTED) {
m_n1_sm_msg_is_set = false;
m_n2_sm_info_is_set = false;
m_cause = 0;
m_code = { };
m_supi = { };
}
pdu_session_modification_network_requested(supi_t supi, pdu_session_id_t pdi,
std::string dnn, snssai_t snssai)
:
pdu_session_msg(PDU_SESSION_MODIFICATION_SMF_REQUESTED, supi, pdi, dnn,
snssai) {
m_n1_sm_msg_is_set = false;
m_n2_sm_info_is_set = false;
m_cause = 0;
m_code = { };
}
void set_cause(uint8_t cause);
uint8_t get_cause();
void set_http_code(Pistache::Http::Code code);
Pistache::Http::Code get_http_code();
std::string get_n2_sm_information() const;
void set_n2_sm_information(std::string const &value);
std::string get_n1_sm_message() const;
void set_n1_sm_message(std::string const &value);
bool n1_sm_msg_is_set() const;
bool n2_sm_info_is_set() const;
void set_amf_url(std::string const &value);
std::string get_amf_url() const;
nlohmann::json n1n2_message_transfer_data; //N1N2MessageTransferReqData from oai::amf::model
private:
std::string m_n1_sm_message; //N1 SM message after decoding
bool m_n1_sm_msg_is_set;
std::string m_n2_sm_information; //N2 SM info after decoding
bool m_n2_sm_info_is_set;
uint8_t m_cause;
Pistache::Http::Code m_code;
supi_t m_supi;
std::string m_supi_prefix;
std::string amf_url;
};
}
#endif
......@@ -178,41 +178,17 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg &msg,
//authorized QoS rules of the PDU session: QOSRules (Section 6.2.5@3GPP TS 24.501)
//(Section 6.4.1.3@3GPP TS 24.501 V16.1.0) Make sure that the number of the packet filters used in the authorized QoS rules of the PDU Session does not
// exceed the maximum number of packet filters supported by the UE for the PDU session
sm_msg->pdu_session_establishment_accept.qosrules.lengthofqosrulesie = 1;
sm_msg->pdu_session_establishment_accept.qosrules.lengthofqosrulesie = qos_flow.qos_rules.size();
sm_msg->pdu_session_establishment_accept.qosrules.qosrulesie =
(QOSRulesIE*) calloc(1, sizeof(QOSRulesIE));
sm_msg->pdu_session_establishment_accept.qosrules.qosrulesie[0]
.qosruleidentifer = qos_flow.qos_rule.qosruleidentifer;
sm_msg->pdu_session_establishment_accept.qosrules.qosrulesie[0]
.ruleoperationcode = qos_flow.qos_rule.ruleoperationcode;
sm_msg->pdu_session_establishment_accept.qosrules.qosrulesie[0].dqrbit =
qos_flow.qos_rule.dqrbit;
sm_msg->pdu_session_establishment_accept.qosrules.qosrulesie[0]
.numberofpacketfilters = qos_flow.qos_rule.numberofpacketfilters;
//1st rule
sm_msg->pdu_session_establishment_accept.qosrules.qosrulesie[0]
.packetfilterlist.create_modifyandadd_modifyandreplace =
(Create_ModifyAndAdd_ModifyAndReplace*) calloc(
1, sizeof(Create_ModifyAndAdd_ModifyAndReplace));
sm_msg->pdu_session_establishment_accept.qosrules.qosrulesie[0]
.packetfilterlist.create_modifyandadd_modifyandreplace
->packetfilterdirection = qos_flow.qos_rule.packetfilterlist
.create_modifyandadd_modifyandreplace->packetfilterdirection;
sm_msg->pdu_session_establishment_accept.qosrules.qosrulesie[0]
.packetfilterlist.create_modifyandadd_modifyandreplace
->packetfilteridentifier = qos_flow.qos_rule.packetfilterlist
.create_modifyandadd_modifyandreplace->packetfilteridentifier;
sm_msg->pdu_session_establishment_accept.qosrules.qosrulesie[0]
.packetfilterlist.create_modifyandadd_modifyandreplace
->packetfiltercontents.component_type = qos_flow.qos_rule
.packetfilterlist.create_modifyandadd_modifyandreplace
->packetfiltercontents.component_type;
sm_msg->pdu_session_establishment_accept.qosrules.qosrulesie[0]
.qosruleprecedence = qos_flow.qos_rule.qosruleprecedence;
sm_msg->pdu_session_establishment_accept.qosrules.qosrulesie[0]
.segregation = qos_flow.qos_rule.segregation;
sm_msg->pdu_session_establishment_accept.qosrules.qosrulesie[0]
.qosflowidentifer = qos_flow.qfi.qfi;
(QOSRulesIE*) calloc(qos_flow.qos_rules.size(), sizeof(QOSRulesIE));
int i = 0;
for (auto rule: qos_flow.qos_rules) {
sm_msg->pdu_session_establishment_accept.qosrules.qosrulesie[i]
.qosruleidentifer = rule.second.qosruleidentifer;
memcpy(&sm_msg->pdu_session_establishment_accept.qosrules.qosrulesie[i], &rule.second, sizeof(QOSRulesIE));
i++;
}
//SessionAMBR
//TODO: get from subscription DB
......@@ -316,7 +292,8 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg &msg,
sc.get()->get_default_qos_flow_description(
sm_msg->pdu_session_establishment_accept.qosflowdescriptions
.qosflowdescriptionscontents[0],
sm_context_res.get_pdu_session_type());
sm_context_res.get_pdu_session_type(),
qos_flow.qfi);
}
//ExtendedProtocolConfigurationOptions
......@@ -504,7 +481,6 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg &msg,
return;
}
//Fill the content of PDU Session Establishment Request message with hardcoded values (to be completed)
//PTI
sm_msg->header.procedure_transaction_identity = sm_context_res.get_pti()
.procedure_transaction_id;
......@@ -532,10 +508,9 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg &msg,
sm_msg->pdu_session_modification_command.qosrules.lengthofqosrulesie =
qos_rules.size();
sm_msg->pdu_session_modification_command.qosrules.qosrulesie =
(QOSRulesIE*) calloc(1, sizeof(QOSRulesIE));
(QOSRulesIE*) calloc(qos_rules.size(), sizeof(QOSRulesIE));
for (int i = 0; i < qos_rules.size(); i++) {
sm_msg->pdu_session_modification_command.qosrules.qosrulesie[i] =
qos_rules[i];
memcpy (&sm_msg->pdu_session_modification_command.qosrules.qosrulesie[i], &qos_rules[i], sizeof(QOSRulesIE));
}
//MappedEPSBearerContexts
......@@ -555,7 +530,9 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg &msg,
sc.get()->get_default_qos_flow_description(
sm_msg->pdu_session_modification_command.qosflowdescriptions
.qosflowdescriptionscontents[0],
sm_context_res.get_pdu_session_type());
sm_context_res.get_pdu_session_type(),
qos_rules[0].qosflowidentifer
);
}
//Encode NAS message
......@@ -571,15 +548,11 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg &msg,
nas_msg_str = n1Message;
//free memory
free_wrapper(
(void**) &sm_msg->pdu_session_modification_command.qosrules.qosrulesie[0]
.packetfilterlist.create_modifyandadd_modifyandreplace);
free_wrapper(
(void**) &sm_msg->pdu_session_modification_command.qosrules.qosrulesie);
free_wrapper(
(void**) &sm_msg->pdu_session_modification_command.qosflowdescriptions
.qosflowdescriptionscontents);
}
break;
......
......@@ -97,7 +97,7 @@ int n4_session_restore_procedure::run() {
int session_create_sm_context_procedure::run(
std::shared_ptr<itti_n11_create_sm_context_request> sm_context_req,
std::shared_ptr<itti_n11_create_sm_context_response> sm_context_resp,
std::shared_ptr<smf::smf_context> pc) {
std::shared_ptr<smf::smf_context> sc) {
Logger::smf_app().info("[SMF Procedure] Create SM Context Request");
// TODO check if compatible with ongoing procedures if any
......@@ -113,7 +113,7 @@ int session_create_sm_context_procedure::run(
n11_trigger = sm_context_req;
n11_triggered_pending = sm_context_resp;
uint64_t seid = smf_app_inst->generate_seid();
ppc->set_seid(seid);
sps->set_seid(seid);
itti_n4_session_establishment_request *n4_ser =
new itti_n4_session_establishment_request(TASK_SMF_APP, TASK_SMF_N4);
n4_ser->seid = 0;
......@@ -133,7 +133,7 @@ int session_create_sm_context_procedure::run(
//-------------------
pfcp::fseid_t cp_fseid = { };
smf_cfg.get_pfcp_fseid(cp_fseid);
cp_fseid.seid = ppc->seid;
cp_fseid.seid = sps->seid;
n4_ser->pfcp_ies.set(cp_fseid);
//*******************
......@@ -150,7 +150,7 @@ int session_create_sm_context_procedure::run(
// forwarding_parameters IEs
pfcp::destination_interface_t destination_interface = { };
ppc->generate_far_id(far_id);
sps->generate_far_id(far_id);
apply_action.forw = 1;
//wys-test-add
......@@ -199,6 +199,7 @@ int session_create_sm_context_procedure::run(
source_interface.interface_value = pfcp::INTERFACE_VALUE_ACCESS;
local_fteid.ch = 1;
//TODO required?: local_fteid.v4 = 1;
//local_fteid.chid = 1;
xgpp_conv::paa_to_pfcp_ue_ip_address(sm_context_resp->res.get_paa(),
......@@ -206,29 +207,28 @@ int session_create_sm_context_procedure::run(
// DOIT simple
// shall uniquely identify the PDR among all the PDRs configured for that PFCP session.
ppc->generate_pdr_id(pdr_id);
sps->generate_pdr_id(pdr_id);
//get the default QoS profile
subscribed_default_qos_t default_qos = { };
std::shared_ptr<session_management_subscription> ss = { };
pc.get()->get_default_qos(sm_context_req->req.get_snssai(),
sc.get()->get_default_qos(sm_context_req->req.get_snssai(),
sm_context_req->req.get_dnn(), default_qos);
//Default QoS Flow - Non GBR, qfi = 5qi
qfi.qfi = default_qos._5qi;
Logger::smf_app().info("session_create_sm_context_procedure default qfi %d",
qfi.qfi);
//packet detection information
//Packet detection information
pdi.set(source_interface); //source interface
pdi.set(local_fteid); // CN tunnel info
pdi.set(ue_ip_address); //UE IP address
//TODO: Network Instance (no need in this version)
pdi.set(local_fteid); // CN tunnel info
//TODO: Packet Filter Set
//TODO: Application ID
pdi.set(qfi); //QoS Flow ID
//TODO:
//Network Instance (no need in this version)
//Packet Filter Set
//Application ID
//QoS Flow ID
//Ethernet PDU Session Information
//Framed Route Information
//TODO: Ethernet PDU Session Information
//TODO: Framed Route Information
outer_header_removal.outer_header_removal_description =
OUTER_HEADER_REMOVAL_GTPU_UDP_IPV4;
......@@ -254,33 +254,34 @@ int session_create_sm_context_procedure::run(
//TODO: verify whether N4 SessionID should be included in PDR and FAR (Section 5.8.2.11@3GPP TS 23.501)
// Have to backup far id and pdr id
smf_qos_flow q = { };
q.far_id_ul.first = true;
q.far_id_ul.second = far_id;
q.pdr_id_ul = pdr_id;
q.pdu_session_id = sm_context_req->req.get_pdu_session_id();
// Create default QoS (Non-GBR) and associate far id and pdr id to this flow
smf_qos_flow flow = { };
flow.far_id_ul.first = true;
flow.far_id_ul.second = far_id;
flow.pdr_id_ul = pdr_id;
flow.pdu_session_id = sm_context_req->req.get_pdu_session_id();
//default QoS profile
q.qfi = default_qos._5qi;
q.qos_profile._5qi = default_qos._5qi;
q.qos_profile.arp = default_qos.arp;
q.qos_profile.priority_level = default_qos.priority_level;
flow.qfi = default_qos._5qi;
flow.qos_profile._5qi = default_qos._5qi;
flow.qos_profile.arp = default_qos.arp;
flow.qos_profile.priority_level = default_qos.priority_level;
//assign default QoS rule for this
//assign default QoS rule for this flow
QOSRulesIE qos_rule = { };
pc.get()->get_default_qos_rule(qos_rule,
sc.get()->get_default_qos_rule(qos_rule,
sm_context_req->req.get_pdu_session_type());
uint8_t rule_id = { 0 };
ppc->generate_qos_rule_id(rule_id);
sps->generate_qos_rule_id(rule_id);
qos_rule.qosruleidentifer = rule_id;
qos_rule.qosflowidentifer = q.qfi.qfi;
q.add_qos_rule(qos_rule);
qos_rule.qosflowidentifer = flow.qfi.qfi;
sps->add_qos_rule(qos_rule);
smf_qos_flow q2 = q;
ppc->add_qos_flow(q2);
smf_qos_flow flow2 = flow;
sps->add_qos_flow(flow2);
sps->set_default_qos_flow(flow.qfi);
// for finding procedure when receiving response
smf_app_inst->set_seid_2_smf_context(cp_fseid.seid, pc);
smf_app_inst->set_seid_2_smf_context(cp_fseid.seid, sc);
Logger::smf_app().info("Sending ITTI message %s to task TASK_SMF_N4",
n4_ser->get_msg_name());
......@@ -307,7 +308,7 @@ void session_create_sm_context_procedure::handle_itti_msg(
pfcp::cause_t cause = { };
resp.pfcp_ies.get(cause);
if (cause.cause_value == pfcp::CAUSE_VALUE_REQUEST_ACCEPTED) {
resp.pfcp_ies.get(ppc->up_fseid);
resp.pfcp_ies.get(sps->up_fseid);
n11_triggered_pending->res.set_cause(REQUEST_ACCEPTED);
}
......@@ -315,17 +316,17 @@ void session_create_sm_context_procedure::handle_itti_msg(
pfcp::pdr_id_t pdr_id = { };
pfcp::far_id_t far_id = { };
if (it.get(pdr_id)) {
smf_qos_flow q = { };
if (ppc->get_qos_flow(pdr_id, q)) {
smf_qos_flow flow = { };
if (sps->get_qos_flow(pdr_id, flow)) {
pfcp::fteid_t local_up_fteid = { };
if (it.get(local_up_fteid)) {
//set tunnel id
xgpp_conv::pfcp_to_core_fteid(local_up_fteid, q.ul_fteid);
xgpp_conv::pfcp_to_core_fteid(local_up_fteid, flow.ul_fteid);
//TODO: should be updated to 5G N3/N9 interface
q.ul_fteid.interface_type = S1_U_SGW_GTP_U; //UPF's N3 interface
flow.ul_fteid.interface_type = S1_U_SGW_GTP_U; //UPF's N3 interface
//Update Qos Flow
smf_qos_flow q2 = q;
ppc->add_qos_flow(q2);
smf_qos_flow flow2 = flow;
sps->add_qos_flow(flow2);
}
} else {
Logger::smf_app().error("Could not get QoS Flow for created_pdr %d",
......@@ -345,30 +346,35 @@ void session_create_sm_context_procedure::handle_itti_msg(
qfi.qfi = default_qos._5qi;
//TODO: how about pdu_session_id??
smf_qos_flow q = { };
//flow_updated info will be used to construct N1,N2 container
qos_flow_context_updated flow_updated = { };
smf_qos_flow flow = { };
QOSRulesIE qos_rule = { };
qos_flow_context_updated qos_flow = { }; //default flow, so Non-GBR, TODO: //we can use smf_qos_flow instead!
qos_flow.set_cause(REQUEST_ACCEPTED);
if (not ppc->get_qos_flow(qfi, q)) {
qos_flow.set_cause(SYSTEM_FAILURE);
flow_updated.set_cause(REQUEST_ACCEPTED);
if (not sps->get_qos_flow(qfi, flow)) {
flow_updated.set_cause(SYSTEM_FAILURE);
} else {
if (q.ul_fteid.is_zero()) {
qos_flow.set_cause(SYSTEM_FAILURE);
if (flow.ul_fteid.is_zero()) {
flow_updated.set_cause(SYSTEM_FAILURE);
} else {
qos_flow.set_ul_fteid(q.ul_fteid); //tunnel info
flow_updated.set_ul_fteid(flow.ul_fteid); //tunnel info
}
if (sps->get_default_qos_rule(qos_rule)) {
flow_updated.add_qos_rule(qos_rule);
// qos_rule.qosruleidentifer = 2;
// flow_updated.add_qos_rule(qos_rule);
}
q.get_default_qos_rule(qos_rule);
qos_flow.set_qos_rule(qos_rule); //set default QoS rule
}
qos_flow.set_qfi(qfi);
flow_updated.set_qfi(qfi);
qos_profile_t profile = { };
profile.arp = default_qos.arp;
qos_flow.set_qos_profile(profile);
flow_updated.set_qos_profile(profile);
//qos_flow.set_arp(default_qos.arp);
qos_flow.set_priority_level(default_qos.priority_level);
flow_updated.set_priority_level(default_qos.priority_level);
//TODO: Set RQA (optional)
n11_triggered_pending->res.set_qos_flow_context(qos_flow);
n11_triggered_pending->res.set_qos_flow_context(flow_updated);
//fill content for N1N2MessageTransfer (including N1, N2 SM)
......@@ -483,7 +489,7 @@ void session_create_sm_context_procedure::handle_itti_msg(
int session_update_sm_context_procedure::run(
std::shared_ptr<itti_n11_update_sm_context_request> sm_context_req,
std::shared_ptr<itti_n11_update_sm_context_response> sm_context_resp,
std::shared_ptr<smf::smf_context> pc) {
std::shared_ptr<smf::smf_context> sc) {
//Handle SM update sm context request
//first try to reuse from CUPS....
//The SMF initiates an N4 Session Modification procedure with the UPF. The SMF provides AN Tunnel Info to the UPF as well as the corresponding forwarding rules
......@@ -505,10 +511,10 @@ int session_update_sm_context_procedure::run(
n11_trigger = sm_context_req;
n11_triggered_pending = sm_context_resp;
uint64_t seid = smf_app_inst->generate_seid();
ppc->set_seid(seid);
sps->set_seid(seid);
itti_n4_session_modification_request *n4_ser =
new itti_n4_session_modification_request(TASK_SMF_APP, TASK_SMF_N4);
n4_ser->seid = ppc->up_fseid.seid;
n4_ser->seid = sps->up_fseid.seid;
n4_ser->trxn_id = this->trxn_id;
n4_ser->r_endpoint = endpoint(up_node_id.u1.ipv4_address, pfcp::default_port);
n4_triggered = std::shared_ptr<itti_n4_session_modification_request>(n4_ser);
......@@ -532,8 +538,8 @@ int session_update_sm_context_procedure::run(
//PFCP Session Modification to delete AN Tunnel info
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
smf_qos_flow flow = { };
if (!sps->get_qos_flow(qfi, flow)) { //no QoS flow found
Logger::smf_app().error(
"Update SM Context procedure: could not found QoS flow with QFI %d",
qfi.qfi);
......@@ -548,34 +554,34 @@ int session_update_sm_context_procedure::run(
pfcp::far_id_t far_id = { };
pfcp::pdr_id_t pdr_id = { };
//if FAR DL exist -> remove it
if ((qos_flow.far_id_dl.first) && (qos_flow.far_id_dl.second.far_id)) {
if ((flow.far_id_dl.first) && (flow.far_id_dl.second.far_id)) {
Logger::smf_app().debug(
"Update SM Context procedure: send a request to remove FAR DL at UPF");
// Remove FAR
far_id.far_id = qos_flow.far_id_dl.second.far_id;
far_id.far_id = flow.far_id_dl.second.far_id;
pfcp::remove_far remove_far = { };
remove_far.set(qos_flow.far_id_dl.second);
remove_far.set(flow.far_id_dl.second);
n4_ser->pfcp_ies.set(remove_far);
send_n4 = true;
//qos_flow.far_id_dl.first = true;
}
//remove PDR DL if exist
if (qos_flow.pdr_id_dl.rule_id) {
if (flow.pdr_id_dl.rule_id) {
Logger::smf_app().debug(
"Update SM Context procedure: send a request to remove PDR DL at UPF");
//Remove PDR DL
pdr_id.rule_id = qos_flow.pdr_id_dl.rule_id;
pdr_id.rule_id = flow.pdr_id_dl.rule_id;
pfcp::remove_pdr remove_pdr = { };
remove_pdr.set(qos_flow.pdr_id_dl);
remove_pdr.set(flow.pdr_id_dl);
n4_ser->pfcp_ies.set(remove_pdr);
send_n4 = true;
}
// may be modified
smf_qos_flow qos_flow2 = qos_flow;
ppc->add_qos_flow(qos_flow2);
smf_qos_flow flow2 = flow;
sps->add_qos_flow(flow2);
qos_flow_context_updated qcu = { };
qcu.set_cause(REQUEST_ACCEPTED);
......@@ -596,8 +602,8 @@ int session_update_sm_context_procedure::run(
sm_context_req_msg.get_dl_fteid(dl_fteid); //eNB's fteid
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
smf_qos_flow flow = { };
if (!sps->get_qos_flow(qfi, flow)) { //no QoS flow found
Logger::smf_app().error(
"Update SM Context procedure: could not found QoS flow with QFI %d",
qfi.qfi);
......@@ -610,7 +616,7 @@ int session_update_sm_context_procedure::run(
}
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 == flow.dl_fteid) and (not flow.released)) {
Logger::smf_app().debug(
"Update SM Context procedure: QFI %d dl_fteid unchanged",
qfi.qfi);
......@@ -619,17 +625,17 @@ int session_update_sm_context_procedure::run(
qcu.set_qfi(qfi);
n11_triggered_pending->res.add_qos_flow_context_updated(qcu);
continue;
} else if ((qos_flow.far_id_dl.first)
&& (qos_flow.far_id_dl.second.far_id)) {
} else if ((flow.far_id_dl.first)
&& (flow.far_id_dl.second.far_id)) {
Logger::smf_app().debug("Update SM Context procedure: Update FAR DL");
// Update FAR
far_id.far_id = qos_flow.far_id_dl.second.far_id;
far_id.far_id = flow.far_id_dl.second.far_id;
pfcp::update_far update_far = { };
pfcp::apply_action_t apply_action = { };
pfcp::outer_header_creation_t outer_header_creation = { };
pfcp::update_forwarding_parameters update_forwarding_parameters = { };
update_far.set(qos_flow.far_id_dl.second);
update_far.set(flow.far_id_dl.second);
outer_header_creation.outer_header_creation_description =
OUTER_HEADER_CREATION_GTPU_UDP_IPV4;
outer_header_creation.teid = dl_fteid.teid_gre_key;
......@@ -643,7 +649,7 @@ int session_update_sm_context_procedure::run(
n4_ser->pfcp_ies.set(update_far);
send_n4 = true;
qos_flow.far_id_dl.first = true;
flow.far_id_dl.first = true;
} else {
Logger::smf_app().debug("Update SM Context procedure: Create FAR DL");
......@@ -665,7 +671,7 @@ int session_update_sm_context_procedure::run(
//pfcp::traffic_endpoint_id_t linked_traffic_endpoint_id_t = {};
//pfcp::proxying_t proxying = {};
ppc->generate_far_id(far_id);
sps->generate_far_id(far_id);
apply_action.forw = 1;
destination_interface.interface_value = pfcp::INTERFACE_VALUE_ACCESS; // ACCESS is for downlink, CORE for uplink
......@@ -686,11 +692,11 @@ int session_update_sm_context_procedure::run(
send_n4 = true;
qos_flow.far_id_dl.first = true;
qos_flow.far_id_dl.second = far_id;
flow.far_id_dl.first = true;
flow.far_id_dl.second = far_id;
}
if (not qos_flow.pdr_id_dl.rule_id) {
if (not flow.pdr_id_dl.rule_id) {
Logger::smf_app().debug("Update SM Context procedure, Create PDR DL");
//-------------------
// IE create_pdr
......@@ -718,19 +724,19 @@ int session_update_sm_context_procedure::run(
source_interface.interface_value = pfcp::INTERFACE_VALUE_CORE;
//local_fteid.from_core_fteid(qos_flow.qos_flow.dl_fteid);
if (ppc->ipv4) {
if (sps->ipv4) {
ue_ip_address.v4 = 1;
ue_ip_address.ipv4_address.s_addr = ppc->ipv4_address.s_addr;
ue_ip_address.ipv4_address.s_addr = sps->ipv4_address.s_addr;
}
if (ppc->ipv6) {
if (sps->ipv6) {
ue_ip_address.v6 = 1;
ue_ip_address.ipv6_address = ppc->ipv6_address;
ue_ip_address.ipv6_address = sps->ipv6_address;
}
// DOIT simple
// shall uniquely identify the PDR among all the PDRs configured for that PFCP session.
ppc->generate_pdr_id(pdr_id);
precedence.precedence = qos_flow.precedence.precedence; //TODO: should be verified
sps->generate_pdr_id(pdr_id);
precedence.precedence = flow.precedence.precedence; //TODO: should be verified
pdi.set(source_interface);
//pdi.set(local_fteid);
......@@ -746,17 +752,17 @@ int session_update_sm_context_procedure::run(
send_n4 = true;
qos_flow.pdr_id_dl = pdr_id;
flow.pdr_id_dl = pdr_id;
} else {
Logger::smf_app().debug(
"Update SM Context procedure: Update FAR, qos_flow.pdr_id_dl.rule_id %d",
qos_flow.pdr_id_dl.rule_id);
flow.pdr_id_dl.rule_id);
// Update FAR
far_id.far_id = qos_flow.far_id_ul.second.far_id;
far_id.far_id = flow.far_id_ul.second.far_id;
pfcp::update_far update_far = { };
pfcp::apply_action_t apply_action = { };
update_far.set(qos_flow.far_id_ul.second);
update_far.set(flow.far_id_ul.second);
apply_action.forw = 1;
update_far.set(apply_action);
......@@ -764,15 +770,15 @@ int session_update_sm_context_procedure::run(
send_n4 = true;
qos_flow.far_id_dl.first = true;
flow.far_id_dl.first = true;
}
// after a release flows
if (not qos_flow.ul_fteid.is_zero()) {
if (not flow.ul_fteid.is_zero()) {
}
// may be modified
smf_qos_flow qos_flow2 = qos_flow;
ppc->add_qos_flow(qos_flow2);
smf_qos_flow flow2 = flow;
sps->add_qos_flow(flow2);
qos_flow_context_updated qcu = { };
qcu.set_cause(REQUEST_ACCEPTED);
......@@ -786,8 +792,8 @@ int session_update_sm_context_procedure::run(
case session_management_procedures_type_e::PDU_SESSION_RELEASE_UE_REQUESTED_STEP1: {
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
smf_qos_flow flow = { };
if (!sps->get_qos_flow(qfi, flow)) { //no QoS flow found
Logger::smf_app().error(
"Update SM Context procedure: could not found QoS flow with QFI %d",
qfi.qfi);
......@@ -800,11 +806,11 @@ int session_update_sm_context_procedure::run(
}
//for DL
if (qos_flow.far_id_dl.first) {
if (flow.far_id_dl.first) {
pfcp::update_far far = { };
pfcp::far_id_t far_id = { };
far_id.far_id = qos_flow.far_id_dl.second.far_id;
far_id.far_id = flow.far_id_dl.second.far_id;
// apply_action.buff = 1;
pfcp::apply_action_t apply_action = { };
apply_action.nocp = 1;
......@@ -819,14 +825,14 @@ int session_update_sm_context_procedure::run(
} else {
Logger::smf_app().info(
"Update SM Context procedure, could not get FAR ID of QoS Flow ID %d",
qos_flow.qfi.qfi);
flow.qfi.qfi);
}
//for UL
if (qos_flow.far_id_ul.first) {
if (flow.far_id_ul.first) {
pfcp::update_far far = { };
pfcp::far_id_t far_id = { };
far_id.far_id = qos_flow.far_id_ul.second.far_id;
far_id.far_id = flow.far_id_ul.second.far_id;
pfcp::apply_action_t apply_action = { };
apply_action.drop = 1;
......@@ -838,9 +844,9 @@ int session_update_sm_context_procedure::run(
}
//update in the PDU Session
qos_flow.release_qos_flow();
smf_qos_flow qos_flow2 = qos_flow;
ppc->add_qos_flow(qos_flow2);
flow.release_qos_flow();
smf_qos_flow flow2 = flow;
sps->add_qos_flow(flow2);
}
}
......@@ -922,39 +928,39 @@ void session_update_sm_context_procedure::handle_itti_msg(
it.first);
for (auto it : qos_flow_context_to_be_updateds) {
smf_qos_flow qos_flow = { };
if (!ppc->get_qos_flow(it.second.qfi, qos_flow)) { //no QoS flow found
smf_qos_flow flow = { };
if (!sps->get_qos_flow(it.second.qfi, flow)) { //no QoS flow found
Logger::smf_app().error(
"Update SM Context procedure: could not found QoS flow with QFI %d",
it.first);
continue;
}
//if FAR DL exist -> remove it
if ((qos_flow.far_id_dl.first)
&& (qos_flow.far_id_dl.second.far_id)) {
if ((flow.far_id_dl.first)
&& (flow.far_id_dl.second.far_id)) {
Logger::smf_app().debug(
"Update SM Context procedure: FAR DL %d has been removed",
qos_flow.far_id_dl.second.far_id);
qos_flow.far_id_dl.first = false;
qos_flow.far_id_dl.second.far_id = 0;
flow.far_id_dl.second.far_id);
flow.far_id_dl.first = false;
flow.far_id_dl.second.far_id = 0;
}
//remove PDR DL if exist
if (qos_flow.pdr_id_dl.rule_id) {
if (flow.pdr_id_dl.rule_id) {
Logger::smf_app().debug(
"Update SM Context procedure: PDR DL %d has been removed",
qos_flow.pdr_id_dl.rule_id);
qos_flow.pdr_id_dl.rule_id = 0;
flow.pdr_id_dl.rule_id);
flow.pdr_id_dl.rule_id = 0;
}
// Update QoS Flow
smf_qos_flow qos_flow2 = qos_flow;
ppc->add_qos_flow(qos_flow2);
smf_qos_flow flow2 = flow;
sps->add_qos_flow(flow2);
qos_flow_context_updated qcu = { };
qcu.set_cause(REQUEST_ACCEPTED);
qcu.set_qfi(pfcp::qfi_t(it.first));
qcu.set_ul_fteid(qos_flow.ul_fteid);
qcu.set_qos_profile(qos_flow.qos_profile);
qcu.set_ul_fteid(flow.ul_fteid);
qcu.set_qos_profile(flow.qos_profile);
n11_triggered_pending->res.add_qos_flow_context_updated(qcu);
}
......@@ -983,7 +989,7 @@ void session_update_sm_context_procedure::handle_itti_msg(
pfcp::pdr_id_t pdr_id = { };
if (it_created_pdr.get(pdr_id)) {
smf_qos_flow flow = { };
if (ppc->get_qos_flow(pdr_id, flow)) {
if (sps->get_qos_flow(pdr_id, flow)) {
Logger::smf_app().debug("QoS Flow, qfi %d", flow.qfi.qfi);
for (auto it : qos_flow_context_to_be_updateds) {
flow.dl_fteid = dl_fteid;
......@@ -1003,7 +1009,7 @@ void session_update_sm_context_procedure::handle_itti_msg(
flow.released = false;
smf_qos_flow flow2 = flow;
ppc->add_qos_flow(flow2);
sps->add_qos_flow(flow2);
qos_flow_context_updated qcu = { };
qcu.set_cause(REQUEST_ACCEPTED);
......@@ -1029,13 +1035,13 @@ void session_update_sm_context_procedure::handle_itti_msg(
pfcp::far_id_t far_id = { };
if (it_update_far.get(far_id)) {
smf_qos_flow flow = { };
if (ppc->get_qos_flow(far_id, flow)) {
if (sps->get_qos_flow(far_id, flow)) {
//for (auto qfi: list_of_qfis_to_be_modified){
for (auto it : qos_flow_context_to_be_updateds) {
if (it.first == flow.qfi.qfi) {
flow.dl_fteid = dl_fteid;
smf_qos_flow flow2 = flow;
ppc->add_qos_flow(flow2);
sps->add_qos_flow(flow2);
qos_flow_context_updated qcu = { };
qcu.set_cause(REQUEST_ACCEPTED);
......@@ -1082,7 +1088,7 @@ void session_update_sm_context_procedure::handle_itti_msg(
Logger::smf_app().info(
"PDU Session Update SM Context (PDU Session Release) accepted by UPF");
//clear the resources including addresses allocated to this Session and associated QoS flows
ppc->deallocate_ressources(n11_trigger.get()->req.get_dnn()); //TODO: for IPv6 (only for Ipv4 for the moment)
sps->deallocate_ressources(n11_trigger.get()->req.get_dnn()); //TODO: for IPv6 (only for Ipv4 for the moment)
}
}
......@@ -1133,7 +1139,7 @@ void session_update_sm_context_procedure::handle_itti_msg(
n11_triggered_pending->res.set_n1_sm_message(n1_sm_msg_hex);
//N2 SM Information
smf_n1_n2_inst.create_n2_sm_information(
n11_triggered_pending->res, 1, n2_sm_info_type_e::PDU_RES_MOD_REQ,
n11_triggered_pending->res, 1, n2_sm_info_type_e::PDU_RES_MOD_RSP,
n2_sm_info);
smf_app_inst->convert_string_2_hex(n2_sm_info, n2_sm_info_hex);
n11_triggered_pending->res.set_n2_sm_information(n2_sm_info_hex);
......@@ -1142,7 +1148,7 @@ void session_update_sm_context_procedure::handle_itti_msg(
n11_triggered_pending->res.sm_context_updated_data =
sm_context_updated_data;
n11_triggered_pending->res.sm_context_updated_data["n2InfoContainer"]["smInfo"]["n2InfoContent"]["ngapIeType"] =
"PDU_RES_MOD_REQ"; //NGAP message
"PDU_RES_MOD_RSP"; //NGAP message
}
break;
......@@ -1155,10 +1161,10 @@ void session_update_sm_context_procedure::handle_itti_msg(
n11_triggered_pending->res.get_cause();
//Update PDU session status to ACTIVE
ppc->set_pdu_session_status(pdu_session_status_e::PDU_SESSION_ACTIVE);
sps->set_pdu_session_status(pdu_session_status_e::PDU_SESSION_ACTIVE);
//set UpCnxState to DEACTIVATED
ppc->set_upCnx_state(upCnx_state_e::UPCNX_STATE_ACTIVATED);
sps->set_upCnx_state(upCnx_state_e::UPCNX_STATE_ACTIVATED);
}
break;
......@@ -1189,7 +1195,7 @@ void session_update_sm_context_procedure::handle_itti_msg(
//TODO: verify whether cause is needed (as in 23.502 but not in 3GPP TS 29.502)
//Update upCnxState to ACTIVATING
ppc->set_upCnx_state(upCnx_state_e::UPCNX_STATE_ACTIVATING);
sps->set_upCnx_state(upCnx_state_e::UPCNX_STATE_ACTIVATING);
}
break;
......@@ -1232,7 +1238,7 @@ void session_update_sm_context_procedure::handle_itti_msg(
n11_triggered_pending->res.set_n1_sm_message(n1_sm_msg_hex);
//include N2 SM Resource Release Request only when User Plane connection is activated
if (ppc->get_upCnx_state() == upCnx_state_e::UPCNX_STATE_ACTIVATED) {
if (sps->get_upCnx_state() == upCnx_state_e::UPCNX_STATE_ACTIVATED) {
//N2 SM Information
smf_n1_n2_inst.create_n2_sm_information(
n11_triggered_pending->res, 1, n2_sm_info_type_e::PDU_RES_REL_CMD,
......@@ -1255,16 +1261,16 @@ void session_update_sm_context_procedure::handle_itti_msg(
}
//Update PDU session status to PDU_SESSION_INACTIVE_PENDING
ppc->set_pdu_session_status(
sps->set_pdu_session_status(
pdu_session_status_e::PDU_SESSION_INACTIVE_PENDING);
//set UpCnxState to DEACTIVATED
ppc->set_upCnx_state(upCnx_state_e::UPCNX_STATE_DEACTIVATED);
sps->set_upCnx_state(upCnx_state_e::UPCNX_STATE_DEACTIVATED);
//TODO: To be completed
//TODO: start timer T3592 (see Section 6.3.3@3GPP TS 24.501)
//get smf_pdu_session and set the corresponding timer
ppc->timer_T3592 = itti_inst->timer_setup(
sps->timer_T3592 = itti_inst->timer_setup(
T3591_TIMER_VALUE_SEC, 0, TASK_SMF_APP, TASK_SMF_APP_TRIGGER_T3592,
n11_trigger->req.get_pdu_session_id());
......@@ -1342,10 +1348,10 @@ int session_release_sm_context_procedure::run(
n11_trigger = sm_context_req;
n11_triggered_pending = sm_context_res;
uint64_t seid = smf_app_inst->generate_seid();
sp->set_seid(seid);
sps->set_seid(seid);
itti_n4_session_deletion_request *n4_ser =
new itti_n4_session_deletion_request(TASK_SMF_APP, TASK_SMF_N4);
n4_ser->seid = sp->up_fseid.seid;
n4_ser->seid = sps->up_fseid.seid;
n4_ser->trxn_id = this->trxn_id;
n4_ser->r_endpoint = endpoint(up_node_id.u1.ipv4_address, pfcp::default_port);
n4_triggered = std::shared_ptr<itti_n4_session_deletion_request>(n4_ser);
......@@ -1382,7 +1388,7 @@ void session_release_sm_context_procedure::handle_itti_msg(
if (cause.cause_value == CAUSE_VALUE_REQUEST_ACCEPTED) {
Logger::smf_app().info("PDU Session Release SM Context accepted by UPF");
//clear the resources including addresses allocated to this Session and associated QoS flows
sp->deallocate_ressources(n11_trigger.get()->req.get_dnn()); //TODO: for IPv6 (only for Ipv4 for the moment)
sps->deallocate_ressources(n11_trigger.get()->req.get_dnn()); //TODO: for IPv6 (only for Ipv4 for the moment)
smf_n11_inst->send_pdu_session_release_sm_context_response(
n11_triggered_pending->http_response, Pistache::Http::Code::No_Content);
......
......@@ -38,6 +38,7 @@
#include "itti_msg_n11.hpp"
#include "itti_msg_n4.hpp"
#include "itti_msg_n4_restore.hpp"
#include "itti_msg_nx.hpp"
#include "msg_pfcp.hpp"
#include "msg_gtpv2c.hpp"
#include "uint_generator.hpp"
......@@ -111,10 +112,10 @@ class n4_session_restore_procedure : public smf_procedure {
class session_create_sm_context_procedure : public smf_procedure {
public:
explicit session_create_sm_context_procedure(
std::shared_ptr<smf_pdu_session> &sppc)
std::shared_ptr<smf_pdu_session> &ps)
:
smf_procedure(),
ppc(sppc),
sps(ps),
n4_triggered(),
n11_triggered_pending(),
n11_trigger() {
......@@ -122,14 +123,13 @@ class session_create_sm_context_procedure : public smf_procedure {
int run(std::shared_ptr<itti_n11_create_sm_context_request> req,
std::shared_ptr<itti_n11_create_sm_context_response> resp,
std::shared_ptr<smf::smf_context> pc);
std::shared_ptr<smf::smf_context> sc);
void handle_itti_msg(itti_n4_session_establishment_response &resp,
std::shared_ptr<smf::smf_context> pc);
std::shared_ptr<smf::smf_context> sc);
std::shared_ptr<itti_n4_session_establishment_request> n4_triggered;
std::shared_ptr<smf_pdu_session> ppc;
std::shared_ptr<smf::smf_context> pc;
std::shared_ptr<smf_pdu_session> sps;
std::shared_ptr<itti_n11_create_sm_context_request> n11_trigger;
std::shared_ptr<itti_n11_create_sm_context_response> n11_triggered_pending;
......@@ -139,10 +139,10 @@ class session_create_sm_context_procedure : public smf_procedure {
class session_update_sm_context_procedure : public smf_procedure {
public:
explicit session_update_sm_context_procedure(
std::shared_ptr<smf_pdu_session> &sppc)
std::shared_ptr<smf_pdu_session> &ps)
:
smf_procedure(),
ppc(sppc),
sps(ps),
n4_triggered(),
n11_triggered_pending(),
n11_trigger(),
......@@ -162,8 +162,7 @@ class session_update_sm_context_procedure : public smf_procedure {
std::shared_ptr<smf::smf_context> sc);
std::shared_ptr<itti_n4_session_modification_request> n4_triggered;
std::shared_ptr<smf_pdu_session> ppc;
std::shared_ptr<smf::smf_context> pc;
std::shared_ptr<smf_pdu_session> sps;
std::shared_ptr<itti_n11_update_sm_context_request> n11_trigger;
std::shared_ptr<itti_n11_update_sm_context_response> n11_triggered_pending;
......@@ -176,10 +175,10 @@ class session_update_sm_context_procedure : public smf_procedure {
class session_release_sm_context_procedure : public smf_procedure {
public:
explicit session_release_sm_context_procedure(
std::shared_ptr<smf_pdu_session> &sps)
std::shared_ptr<smf_pdu_session> &ps)
:
smf_procedure(),
sp(sps),
sps(ps),
n4_triggered(),
n11_triggered_pending(),
n11_trigger() {
......@@ -198,8 +197,7 @@ class session_release_sm_context_procedure : public smf_procedure {
std::shared_ptr<smf::smf_context> sc);
std::shared_ptr<itti_n4_session_deletion_request> n4_triggered;
std::shared_ptr<smf_pdu_session> sp;
std::shared_ptr<smf::smf_context> sc;
std::shared_ptr<smf_pdu_session> sps;
std::shared_ptr<itti_n11_release_sm_context_request> n11_trigger;
std::shared_ptr<itti_n11_release_sm_context_response> n11_triggered_pending;
......
......@@ -282,7 +282,7 @@ void send_pdu_session_update_sm_context_establishment(
nlohmann::json pdu_session_update_request;
//encode PDU Session Resource Setup Response Transfer IE
/*
00 03 e0 ac 0a 05 01 00 00 00 01 00 3c
00 03 e0 ac 0a 05 01 00 00 00 01 00 06
*/
size_t buffer_size = 128;
char *buffer = (char*) calloc(1, buffer_size);
......@@ -298,8 +298,8 @@ void send_pdu_session_update_sm_context_establishment(
ENCODE_U8(buffer + size, 0x00, size); //00
ENCODE_U8(buffer + size, 0x00, size); //00
ENCODE_U8(buffer + size, 0x01, size); //01
ENCODE_U8(buffer + size, 0x00, size); //Associated QoS Flow 00 3c
ENCODE_U8(buffer + size, 0x3c, size); //QFI: 60
ENCODE_U8(buffer + size, 0x00, size); //Associated QoS Flow 00 06
ENCODE_U8(buffer + size, 0x06, size); //QFI: 06
std::cout << "Buffer: " << std::endl;
for (int i = 0; i < size; i++) {
......@@ -409,7 +409,7 @@ void send_pdu_session_modification_request_step1(std::string smf_ip_address) {
ENCODE_U8(buffer + size, 0x00, size); //_5GSMCause
ENCODE_U8(buffer + size, 0x7a, size); //QoS Rules IE
ENCODE_U8(buffer + size, 0x00, size); //QoS Rules length
ENCODE_U8(buffer + size, 0x09, size); //QoS Rules length
ENCODE_U8(buffer + size, 0x12, size); //QoS Rules length
ENCODE_U8(buffer + size, 0x01, size); //QoS Rules rule id
ENCODE_U8(buffer + size, 0x00, size); //QoS Rules rule length
ENCODE_U8(buffer + size, 0x06, size); //QoS Rules rule length
......@@ -418,10 +418,17 @@ void send_pdu_session_modification_request_step1(std::string smf_ip_address) {
ENCODE_U8(buffer + size, 0x01, size); //QoS Rules filter 1 length
ENCODE_U8(buffer + size, 0x01, size); //QoS Rules
ENCODE_U8(buffer + size, 0x01, size); //QoS Rules
ENCODE_U8(buffer + size, 0x3c, size); //QoS Rules
ENCODE_U8(buffer + size, 0x06, size); //QoS Rules
ENCODE_U8(buffer + size, 0x02, size); //QoS Rules rule id
ENCODE_U8(buffer + size, 0x00, size); //QoS Rules rule length
ENCODE_U8(buffer + size, 0x06, size); //QoS Rules rule length
ENCODE_U8(buffer + size, 0x21, size); //QoS Rules
ENCODE_U8(buffer + size, 0x31, size); //QoS Rules
ENCODE_U8(buffer + size, 0x01, size); //QoS Rules filter 1 length
ENCODE_U8(buffer + size, 0x01, size); //QoS Rules
ENCODE_U8(buffer + size, 0x01, size); //QoS Rules
ENCODE_U8(buffer + size, 0x06, size); //QoS Rules
// ENCODE_U8(buffer + size, 0x00, size); //MaximumNumberOfSupportedPacketFilters
// ENCODE_U8(buffer + size, 0x01, size); //MaximumNumberOfSupportedPacketFilters
std::cout << "Buffer: " << std::endl;
for (int i = 0; i < size; i++) {
......@@ -522,16 +529,7 @@ void send_pdu_session_modification_request_step2(std::string smf_ip_address) {
ENCODE_U8(buffer + size, 0x00, size); //Gtp-teid: 01000000
ENCODE_U8(buffer + size, 0x01, size); //Gtp-teid: 01000000
ENCODE_U8(buffer + size, 0x00, size); //QoSFlowAddorModifyResponseList
ENCODE_U8(buffer + size, 0x78, size); //60: QFI
/*
struct Ngap_UPTransportLayerInformation *dL_NGU_UP_TNLInformation;
struct Ngap_UPTransportLayerInformation *uL_NGU_UP_TNLInformation;
struct Ngap_QosFlowAddOrModifyResponseList *qosFlowAddOrModifyResponseList;
struct Ngap_QosFlowPerTNLInformationList *additionalDLQosFlowPerTNLInformation;
struct Ngap_QosFlowListWithCause *qosFlowFailedToAddOrModifyList;
struct Ngap_ProtocolExtensionContainer *iE_Extensions;
*/
ENCODE_U8(buffer + size, 0x0c, size); //60: QFI
std::cout << "Buffer: " << std::endl;
for (int i = 0; i < size; i++) {
......@@ -1050,7 +1048,7 @@ void send_pdu_session_update_sm_context_ue_service_request_step2(
nlohmann::json service_requests;
//encode PDU Session Resource Setup Response Transfer IE
/*
00 03 e0 ac 0a 05 01 00 00 00 01 00 3c
00 03 e0 ac 0a 05 01 00 00 00 01 00 06
*/
size_t buffer_size = 128;
char *buffer = (char*) calloc(1, buffer_size);
......@@ -1066,8 +1064,8 @@ void send_pdu_session_update_sm_context_ue_service_request_step2(
ENCODE_U8(buffer + size, 0x00, size); //00
ENCODE_U8(buffer + size, 0x00, size); //00
ENCODE_U8(buffer + size, 0x01, size); //01
ENCODE_U8(buffer + size, 0x00, size); //Associated QoS Flow 00 3c
ENCODE_U8(buffer + size, 0x3c, size); //QFI: 60
ENCODE_U8(buffer + size, 0x00, size); //Associated QoS Flow 00 06
ENCODE_U8(buffer + size, 0x06, size); //QFI: 06
std::cout << "Buffer: " << std::endl;
for (int i = 0; i < size; i++) {
......@@ -1265,7 +1263,6 @@ int main(int argc, char *argv[]) {
usleep(200000);
send_pdu_session_release_complete(smf_ip_address);
usleep(200000);
//Release SM context
//send_release_sm_context_request(smf_ip_address);
return 0;
......
......@@ -46,7 +46,7 @@ void SessionManagementSubscriptionDataRetrievalApiImpl::get_sm_data(const std::s
jsonData["singleNssai"]["sd"] = 123;
jsonData["dnnConfigurations"]["default"]["pduSessionTypes"]["defaultSessionType"] = "IPV4";
jsonData["dnnConfigurations"]["default"]["sscModes"]["defaultSscMode"] = "SSC_MODE_1";
jsonData["dnnConfigurations"]["default"]["5gQosProfile"]["5qi"] = 60;
jsonData["dnnConfigurations"]["default"]["5gQosProfile"]["5qi"] = 6;
jsonData["dnnConfigurations"]["default"]["5gQosProfile"]["arp"]["priorityLevel"] = 1;
jsonData["dnnConfigurations"]["default"]["5gQosProfile"]["arp"]["preemptCap"] = "NOT_PREEMPT";
jsonData["dnnConfigurations"]["default"]["5gQosProfile"]["arp"]["preemptVuln"] = "NOT_PREEMPTABLE";
......@@ -55,7 +55,7 @@ void SessionManagementSubscriptionDataRetrievalApiImpl::get_sm_data(const std::s
jsonData["dnnConfigurations"]["carrier.com"]["pduSessionTypes"]["defaultSessionType"] = "IPV4";
jsonData["dnnConfigurations"]["carrier.com"]["sscModes"]["defaultSscMode"] = "SSC_MODE_1";
jsonData["dnnConfigurations"]["carrier.com"]["5gQosProfile"]["5qi"] = 61;
jsonData["dnnConfigurations"]["carrier.com"]["5gQosProfile"]["5qi"] = 7;
jsonData["dnnConfigurations"]["carrier.com"]["5gQosProfile"]["arp"]["priorityLevel"] = 1;
jsonData["dnnConfigurations"]["carrier.com"]["5gQosProfile"]["arp"]["preemptCap"] = "NOT_PREEMPT";
jsonData["dnnConfigurations"]["carrier.com"]["5gQosProfile"]["arp"]["preemptVuln"] = "NOT_PREEMPTABLE";
......
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