From 960dc473c5b57042a5c97b4adb8833f55df097f6 Mon Sep 17 00:00:00 2001
From: Tien-Thinh Nguyen <Tien-Thinh.nguyen@eurecom.fr>
Date: Sun, 17 May 2020 14:44:30 +0200
Subject: [PATCH] fix issue for loading Subscription Data from the
 configuration filke

---
 etc/smf.conf                |  4 +-
 src/smf_app/smf_app.cpp     | 86 ++++++++++++++++++-------------------
 src/smf_app/smf_config.cpp  | 23 +++++++---
 src/smf_app/smf_config.hpp  |  1 +
 src/smf_app/smf_context.cpp | 52 ++++++++++++++++------
 src/smf_app/smf_context.hpp | 19 +++++++-
 src/smf_app/smf_n1_n2.cpp   |  4 ++
 7 files changed, 121 insertions(+), 68 deletions(-)

diff --git a/etc/smf.conf b/etc/smf.conf
index 8dc1afc7..4158ee6c 100644
--- a/etc/smf.conf
+++ b/etc/smf.conf
@@ -109,10 +109,10 @@ SMF =
       USE_LOCAL_CONFIGURATION = "yes";
       SESSION_MANAGEMENT_SUBSCRIPTION_LIST = (
          { NSSAI_SST = 222; NSSAI_SD = "123", DNN = "default", DEFAULT_SESSION_TYPE = "IPV4", DEFAULT_SSC_MODE = 1, 
-           QOS_PROFILE_5QI = 6, QOS_PROFILE_ARP_PRIORITY_LEVEL = 1, QOS_PROFILE_ARP_PREEMPTCAP = "NOT_PREEMPT", 
+           QOS_PROFILE_5QI = 6, QOS_PROFILE_PRIORITY_LEVEL = 1, QOS_PROFILE_ARP_PRIORITY_LEVEL = 1, QOS_PROFILE_ARP_PREEMPTCAP = "NOT_PREEMPT", 
            QOS_PROFILE_ARP_PREEMPTVULN = "NOT_PREEMPTABLE", SESSION_AMBR_UL = "20Mbps", SESSION_AMBR_DL = "22Mbps"},
          { NSSAI_SST = 222; NSSAI_SD = "123", DNN = "carrier.com", DEFAULT_SESSION_TYPE = "IPV4", DEFAULT_SSC_MODE = 1, 
-           QOS_PROFILE_5QI = 7, QOS_PROFILE_ARP_PRIORITY_LEVEL = 1, QOS_PROFILE_ARP_PREEMPTCAP = "NOT_PREEMPT", 
+           QOS_PROFILE_5QI = 7, QOS_PROFILE_PRIORITY_LEVEL = 1, QOS_PROFILE_ARP_PRIORITY_LEVEL = 1, QOS_PROFILE_ARP_PREEMPTCAP = "NOT_PREEMPT", 
            QOS_PROFILE_ARP_PREEMPTVULN = "NOT_PREEMPTABLE", SESSION_AMBR_UL = "10Mbps", SESSION_AMBR_DL = "11Mbps"}
         );                 
     };   
diff --git a/src/smf_app/smf_app.cpp b/src/smf_app/smf_app.cpp
index 78584a1a..9791f161 100755
--- a/src/smf_app/smf_app.cpp
+++ b/src/smf_app/smf_app.cpp
@@ -648,56 +648,56 @@ void smf_app::handle_pdu_session_create_sm_context_request(
   }
 
   //Step 6. retrieve Session Management Subscription data from UDM if not available (step 4, section 4.3.2 3GPP TS 23.502)
-  //TODO: Test with UDM (TESTER)
   std::string dnn_selection_mode = smreq->req.get_dnn_selection_mode();
-  if (not use_local_configuration_subscription_data(dnn_selection_mode)
-      && not is_supi_dnn_snssai_subscription_data(supi, dnn, snssai)) {
-    //uses a dummy UDM to test this part
+  //if the Session Management Subscription data is not available, get from configuration file or UDM
+  if (not sc.get()->is_dnn_snssai_subscription_data(dnn, snssai)) {
     Logger::smf_app().debug(
-        "Retrieve Session Management Subscription data from the UDM");
+        "The Session Management Subscription data is not available");
+
     session_management_subscription *s = new session_management_subscription(
         snssai);
     std::shared_ptr<session_management_subscription> subscription =
         std::shared_ptr<session_management_subscription>(s);
-    if (smf_n10_inst->get_sm_data(supi64, dnn, snssai, subscription)) {
-      //update dnn_context with subscription info
-      sc.get()->insert_dnn_subscription(snssai, subscription);
+
+    if (not use_local_configuration_subscription_data(dnn_selection_mode)) {
+      Logger::smf_app().debug(
+          "Retrieve Session Management Subscription data from the UDM");
+      if (smf_n10_inst->get_sm_data(supi64, dnn, snssai, subscription)) {
+        //update dnn_context with subscription info
+        sc.get()->insert_dnn_subscription(snssai, subscription);
+      } else {
+        // Cannot retrieve information from UDM, reject PDU session establishment
+        Logger::smf_app().warn(
+            "Received PDU_SESSION_CREATESMCONTEXT_REQUEST, couldn't retrieve the Session Management Subscription from UDM, ignore message!");
+        problem_details.setCause(
+            pdu_session_application_error_e2str[PDU_SESSION_APPLICATION_ERROR_SUBSCRIPTION_DENIED]);
+        smContextCreateError.setError(problem_details);
+        refToBinaryData.setContentId(N1_SM_CONTENT_ID);
+        smContextCreateError.setN1SmMsg(refToBinaryData);
+        //PDU Session Establishment Reject, with cause "29 User authentication or authorization failed"
+        smf_n1_n2_inst.create_n1_sm_container(
+            smreq->req,
+            PDU_SESSION_ESTABLISHMENT_REJECT,
+            n1_sm_message,
+            cause_value_5gsm_e::CAUSE_29_USER_AUTHENTICATION_OR_AUTHORIZATION_FAILED);
+        smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_message_hex);
+        //Send response (PDU Session Establishment Reject) to AMF
+        smf_n11_inst->send_pdu_session_create_sm_context_response(
+            smreq->http_response, smContextCreateError,
+            Pistache::Http::Code::Forbidden, n1_sm_message_hex);
+        return;
+      }
     } else {
-      // Cannot retrieve information from UDM, reject PDU session establishment
-      Logger::smf_app().warn(
-          "Received PDU_SESSION_CREATESMCONTEXT_REQUEST, couldn't retrieve the Session Management Subscription from UDM, ignore message!");
-      problem_details.setCause(
-          pdu_session_application_error_e2str[PDU_SESSION_APPLICATION_ERROR_SUBSCRIPTION_DENIED]);
-      smContextCreateError.setError(problem_details);
-      refToBinaryData.setContentId(N1_SM_CONTENT_ID);
-      smContextCreateError.setN1SmMsg(refToBinaryData);
-      //PDU Session Establishment Reject, with cause "29 User authentication or authorization failed"
-      smf_n1_n2_inst.create_n1_sm_container(
-          smreq->req,
-          PDU_SESSION_ESTABLISHMENT_REJECT,
-          n1_sm_message,
-          cause_value_5gsm_e::CAUSE_29_USER_AUTHENTICATION_OR_AUTHORIZATION_FAILED);
-      smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_message_hex);
-      //Send response (PDU Session Establishment Reject) to AMF
-      smf_n11_inst->send_pdu_session_create_sm_context_response(
-          smreq->http_response, smContextCreateError,
-          Pistache::Http::Code::Forbidden, n1_sm_message_hex);
-      return;
-    }
-  } else {
-    //use local configuration
-    Logger::smf_app().debug(
-        "Retrieve Session Management Subscription data from local configuration");
-    session_management_subscription *s = new session_management_subscription(
-        snssai);
-    std::shared_ptr<session_management_subscription> subscription =
-        std::shared_ptr<session_management_subscription>(s);
-    if (get_session_management_subscription_data(supi64, dnn, snssai,
-                                                 subscription)) {
-      //update dnn_context with subscription info
-      sc.get()->insert_dnn_subscription(snssai, subscription);
-    }
+      //use local configuration
+      Logger::smf_app().debug(
+          "Retrieve Session Management Subscription data from local configuration");
+      if (get_session_management_subscription_data(supi64, dnn, snssai,
+                                                   subscription)) {
+        //update dnn_context with subscription info
+        sc.get()->insert_dnn_subscription(snssai, subscription);
+      }
 
+    }
   }
 
   // Step 7. generate a SMF context Id and store the corresponding information in a map (SM_Context_ID, (supi, dnn, nssai, pdu_session_id))
@@ -1003,7 +1003,7 @@ bool smf_app::scid_2_smf_context(const scid_t &scid,
 bool smf_app::use_local_configuration_subscription_data(
     const std::string &dnn_selection_mode) {
   //TODO: should be implemented
-  return true;  //get Session Management Subscription from UDM
+  return smf_cfg.local_configuration;
 }
 
 //------------------------------------------------------------------------------
diff --git a/src/smf_app/smf_config.cpp b/src/smf_app/smf_config.cpp
index 356111f0..916b8ee5 100644
--- a/src/smf_app/smf_config.cpp
+++ b/src/smf_app/smf_config.cpp
@@ -580,13 +580,14 @@ int smf_config::load(const string &config_file) {
       const Setting &session_management_subscription_cfg =
           session_management_subscription_list_cfg[i];
 
-      unsigned int nssai_sst = { 0 };
+      unsigned int nssai_sst = 0;
       string nssai_sd = { };
       string dnn = { };
       string default_session_type = { };
-      unsigned int default_ssc_mode = { 0 };
-      unsigned int qos_profile_5qi = { 0 };
-      unsigned int qos_profile_arp_priority_level = { };
+      unsigned int default_ssc_mode = 0;
+      unsigned int qos_profile_5qi = 0;
+      unsigned int qos_profile_priority_level = 0;
+      unsigned int qos_profile_arp_priority_level = 0;
       string qos_profile_arp_preemptcap = { };
       string qos_profile_arp_preemptvuln = { };
       string session_ambr_ul = { };
@@ -608,6 +609,9 @@ int smf_config::load(const string &config_file) {
       session_management_subscription_cfg.lookupValue(
       SMF_CONFIG_STRING_QOS_PROFILE_5QI,
                                                       qos_profile_5qi);
+      session_management_subscription_cfg.lookupValue(
+          SMF_CONFIG_STRING_QOS_PROFILE_PRIORITY_LEVEL,
+          qos_profile_priority_level);
       session_management_subscription_cfg.lookupValue(
           SMF_CONFIG_STRING_QOS_PROFILE_ARP_PRIORITY_LEVEL,
           qos_profile_arp_priority_level);
@@ -621,7 +625,8 @@ int smf_config::load(const string &config_file) {
       SMF_CONFIG_STRING_SESSION_AMBR_UL,
                                                       session_ambr_ul);
       session_management_subscription_cfg.lookupValue(
-      SMF_CONFIG_STRING_SESSION_AMBR_DL, session_ambr_dl);
+      SMF_CONFIG_STRING_SESSION_AMBR_DL,
+                                                      session_ambr_dl);
 
       session_management_subscription[i].single_nssai.sST = nssai_sst;
       session_management_subscription[i].single_nssai.sD = nssai_sd;
@@ -629,6 +634,8 @@ int smf_config::load(const string &config_file) {
       session_management_subscription[i].dnn = dnn;
       session_management_subscription[i].ssc_mode = default_ssc_mode;
       session_management_subscription[i].default_qos._5qi = qos_profile_5qi;
+      session_management_subscription[i].default_qos.priority_level =
+          qos_profile_priority_level;
       session_management_subscription[i].default_qos.arp.priority_level =
           qos_profile_arp_priority_level;
       session_management_subscription[i].default_qos.arp.preempt_cap =
@@ -788,10 +795,12 @@ void smf_config::display() {
       Logger::smf_app().info(
           "        " SMF_CONFIG_STRING_QOS_PROFILE_5QI ":  %d",
           session_management_subscription[i].default_qos._5qi);
-
+      Logger::smf_app().info(
+           "        " SMF_CONFIG_STRING_QOS_PROFILE_PRIORITY_LEVEL ":  %d",
+           session_management_subscription[i].default_qos.priority_level);
       Logger::smf_app().info(
           "        " SMF_CONFIG_STRING_QOS_PROFILE_ARP_PRIORITY_LEVEL ":  %d",
-          session_management_subscription[i].default_qos.priority_level);
+          session_management_subscription[i].default_qos.arp.priority_level);
       Logger::smf_app().info(
           "        " SMF_CONFIG_STRING_QOS_PROFILE_ARP_PREEMPTCAP ":  %s",
           session_management_subscription[i].default_qos.arp.preempt_cap.c_str());
diff --git a/src/smf_app/smf_config.hpp b/src/smf_app/smf_config.hpp
index c66ca647..2d018234 100644
--- a/src/smf_app/smf_config.hpp
+++ b/src/smf_app/smf_config.hpp
@@ -125,6 +125,7 @@
 #define SMF_CONFIG_STRING_DEFAULT_SESSION_TYPE                   "DEFAULT_SESSION_TYPE"
 #define SMF_CONFIG_STRING_DEFAULT_SSC_MODE                       "DEFAULT_SSC_MODE"
 #define SMF_CONFIG_STRING_QOS_PROFILE_5QI                        "QOS_PROFILE_5QI"
+#define SMF_CONFIG_STRING_QOS_PROFILE_PRIORITY_LEVEL             "QOS_PROFILE_PRIORITY_LEVEL"
 #define SMF_CONFIG_STRING_QOS_PROFILE_ARP_PRIORITY_LEVEL         "QOS_PROFILE_ARP_PRIORITY_LEVEL"
 #define SMF_CONFIG_STRING_QOS_PROFILE_ARP_PREEMPTCAP             "QOS_PROFILE_ARP_PREEMPTCAP"
 #define SMF_CONFIG_STRING_QOS_PROFILE_ARP_PREEMPTVULN            "QOS_PROFILE_ARP_PREEMPTVULN"
diff --git a/src/smf_app/smf_context.cpp b/src/smf_app/smf_context.cpp
index 4d32f0d7..79dc584f 100644
--- a/src/smf_app/smf_context.cpp
+++ b/src/smf_app/smf_context.cpp
@@ -454,18 +454,15 @@ void smf_pdu_session::update_qos_rule(const QOSRulesIE &qos_rule) {
       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("Update QoS rule (%d) success",
-                              rule_id);
+      Logger::smf_app().trace("Update QoS rule (%d) success", rule_id);
     } else {
       Logger::smf_app().error(
-          "Update QoS Rule (%d) failed, rule does not existed",
-          rule_id);
+          "Update QoS Rule (%d) failed, rule does not existed", rule_id);
     }
 
   } else {
-    Logger::smf_app().error(
-        "Update QoS rule (%d) failed, invalid Rule Id",
-        rule_id);
+    Logger::smf_app().error("Update QoS rule (%d) failed, invalid Rule Id",
+                            rule_id);
   }
 }
 
@@ -518,7 +515,8 @@ void smf_pdu_session::add_qos_rule(const QOSRulesIE &qos_rule) {
 
 //------------------------------------------------------------------------------
 void session_management_subscription::insert_dnn_configuration(
-    std::string dnn, std::shared_ptr<dnn_configuration_t> &dnn_configuration) {
+    const std::string &dnn,
+    std::shared_ptr<dnn_configuration_t> &dnn_configuration) {
   dnn_configurations.insert(
       std::pair<std::string, std::shared_ptr<dnn_configuration_t>>(
           dnn, dnn_configuration));
@@ -526,13 +524,24 @@ void session_management_subscription::insert_dnn_configuration(
 
 //------------------------------------------------------------------------------
 void session_management_subscription::find_dnn_configuration(
-    std::string dnn, std::shared_ptr<dnn_configuration_t> &dnn_configuration) {
+    const std::string &dnn,
+    std::shared_ptr<dnn_configuration_t> &dnn_configuration) const {
   Logger::smf_app().info("Find DNN configuration with DNN %s", dnn.c_str());
   if (dnn_configurations.count(dnn) > 0) {
     dnn_configuration = dnn_configurations.at(dnn);
   }
 }
 
+//------------------------------------------------------------------------------
+bool session_management_subscription::dnn_configuration(
+    const std::string &dnn) const {
+  if (dnn_configurations.count(dnn) > 0) {
+    return true;
+  } else {
+    return false;
+  }
+}
+
 //------------------------------------------------------------------------------
 void smf_context::insert_procedure(std::shared_ptr<smf_procedure> &sproc) {
   std::unique_lock<std::recursive_mutex> lock(m_context);
@@ -876,8 +885,6 @@ void smf_context::get_session_ambr(SessionAMBR &session_ambr,
 void smf_context::get_session_ambr(
     Ngap_PDUSessionAggregateMaximumBitRate_t &session_ambr,
     const snssai_t &snssai, const std::string &dnn) {
-  Logger::smf_app().debug(
-      "Get AMBR info from the subscription information (DNN %s)", dnn.c_str());
 
   std::shared_ptr<session_management_subscription> ss = { };
   std::shared_ptr<dnn_configuration_t> sdc = { };
@@ -898,9 +905,9 @@ void smf_context::get_session_ambr(
 
     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());
+          "Default AMBR info from the DNN configuration, uplink %s, downlink %s",
+          (sdc.get()->session_ambr).uplink.c_str(),
+          (sdc.get()->session_ambr).downlink.c_str());
       //Downlink
       size_t leng_of_session_ambr_dl =
           (sdc.get()->session_ambr).downlink.length();
@@ -958,6 +965,9 @@ void smf_context::get_session_ambr(
                     session_ambr.pDUSessionAggregateMaximumBitRateUL.buf);
   }
 
+  Logger::smf_app().debug(
+      "Get AMBR info from the subscription information (DNN %s), uplink %d downlink %d",
+      dnn.c_str(), bit_rate_ul, bit_rate_dl);
 }
 
 //------------------------------------------------------------------------------
@@ -2410,6 +2420,20 @@ void smf_context::insert_dnn_subscription(
                          (uint8_t) snssai.sST);
 }
 
+//------------------------------------------------------------------------------
+bool smf_context::is_dnn_snssai_subscription_data(std::string &dnn,
+                                                  snssai_t &snssai) {
+  if (dnn_subscriptions.count((uint8_t) snssai.sST) > 0) {
+    std::shared_ptr<session_management_subscription> ss = dnn_subscriptions.at(
+        (uint8_t) snssai.sST);
+    if (ss.get()->dnn_configuration(dnn))
+      return true;
+    else
+      return false;
+  }
+  return false;
+}
+
 //------------------------------------------------------------------------------
 bool smf_context::find_dnn_subscription(
     const snssai_t &snssai,
diff --git a/src/smf_app/smf_context.hpp b/src/smf_app/smf_context.hpp
index 3166e4de..b6cf3989 100644
--- a/src/smf_app/smf_context.hpp
+++ b/src/smf_app/smf_context.hpp
@@ -441,7 +441,7 @@ class session_management_subscription {
    * @return void
    */
   void insert_dnn_configuration(
-      std::string dnn, std::shared_ptr<dnn_configuration_t> &dnn_configuration);
+      const std::string &dnn, std::shared_ptr<dnn_configuration_t> &dnn_configuration);
 
   /*
    * Find a DNN configuration
@@ -450,7 +450,14 @@ class session_management_subscription {
    * @return void
    */
   void find_dnn_configuration(
-      std::string dnn, std::shared_ptr<dnn_configuration_t> &dnn_configuration);
+      const std::string &dnn, std::shared_ptr<dnn_configuration_t> &dnn_configuration) const;
+
+  /*
+   * Verify whether DNN configuration with a given DNN exist
+   * @param [std::string &] dnn
+   * @return bool: return true if the configuration exist, otherwise return false
+   */
+  bool dnn_configuration(const std::string &dnn) const;
 
  private:
   snssai_t single_nssai;
@@ -654,6 +661,14 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
       const snssai_t &snssai,
       std::shared_ptr<session_management_subscription> &ss);
 
+  /*
+   * Verify whether a subscription data exist with a given dnn and snssai
+   * @param [std::string &] dnn: DNN
+   * @param [const snssai_t&] snssai: single NSSAI
+   *@return bool: Return true if a subscription data corresponding with dnn and snssai exist, otherwise return false
+   */
+  bool is_dnn_snssai_subscription_data(std::string &dnn, snssai_t &snssai);
+
   /*
    * Find a session management subscription from a SMF context
    * @param [const snssai_t&] snssai
diff --git a/src/smf_app/smf_n1_n2.cpp b/src/smf_app/smf_n1_n2.cpp
index f7c000c3..6b663d40 100644
--- a/src/smf_app/smf_n1_n2.cpp
+++ b/src/smf_app/smf_n1_n2.cpp
@@ -872,6 +872,10 @@ void smf_n1_n2::create_n2_sm_information(pdu_session_msg &msg,
           ngap_QosFlowSetupRequestItem);
       ASN_SEQUENCE_ADD(&ngap_IEs->protocolIEs.list, qosFlowSetupRequestList);
 
+      Logger::smf_app().info(
+          "QoS parameters: QFI %d, ARP priority level %d, qos_flow.qos_profile.arp.preempt_cap %s, qos_flow.qos_profile.arp.preempt_vuln %s",
+          qos_flow.qfi.qfi, qos_flow.qos_profile.arp.priority_level,qos_flow.qos_profile.arp.preempt_cap.c_str(), qos_flow.qos_profile.arp.preempt_vuln.c_str());
+
       //encode
       size_t buffer_size = BUF_LEN;
       char *buffer = (char*) calloc(1, buffer_size);
-- 
GitLab