diff --git a/etc/smf.conf b/etc/smf.conf
index 60dc214922f3ba2de7bb60da40d4e84642ce2f19..08a45a7dc42bf563560ca53a03846a7b63070832 100644
--- a/etc/smf.conf
+++ b/etc/smf.conf
@@ -73,8 +73,8 @@ SMF =
 
     APN_LIST = (
        # IPV4_POOL, IPV6_POOL are index in IPV4_LIST, IPV6_LIST, PDN_TYPE choice in {IPv4, IPv6, IPv4v6}
-      {APN_NI = "carrier.com"; PDN_TYPE = "IPv4"; IPV4_POOL  = 0; IPV6_POOL = -1},
-      {APN_NI = "apn1"; PDN_TYPE = "IPv4"; IPV4_POOL = 1; IPV6_POOL = -1},
+      {APN_NI = "default"; PDN_TYPE = "IPv4"; IPV4_POOL  = 0; IPV6_POOL = -1},
+      {APN_NI = "carrier.com"; PDN_TYPE = "IPv4"; IPV4_POOL = 1; IPV6_POOL = -1},
       {APN_NI = "apn2"; PDN_TYPE = "IPv4"; IPV4_POOL = 2; IPV6_POOL = -1},
       {APN_NI = "apn3"; PDN_TYPE = "IPv4"; IPV4_POOL = 3; IPV6_POOL = -1},
       {APN_NI = "apn4"; PDN_TYPE = "IPv4"; IPV4_POOL = 4; IPV6_POOL = -1}
diff --git a/src/api-server/impl/SMContextsCollectionApiImpl.cpp b/src/api-server/impl/SMContextsCollectionApiImpl.cpp
index aba49d98e386c69c3b98614ca2ef06b33478e802..e6fa48c890ef0587d29fcc2d050967e39d4c9a85 100755
--- a/src/api-server/impl/SMContextsCollectionApiImpl.cpp
+++ b/src/api-server/impl/SMContextsCollectionApiImpl.cpp
@@ -103,7 +103,7 @@ void SMContextsCollectionApiImpl::post_sm_contexts(
       smContextCreateData.getSNssai().getSst(),
       smContextCreateData.getSNssai().getSd().c_str());
   snssai_t snssai(smContextCreateData.getSNssai().getSst(),
-                  smContextCreateData.getSNssai().getSd().c_str());
+                  smContextCreateData.getSNssai().getSd());
   sm_context_req_msg.set_snssai(snssai);
 
   //PDU session ID
diff --git a/src/smf_app/smf_app.cpp b/src/smf_app/smf_app.cpp
index e5c2a61aaddc08f359c2e9a8f00ba5b4c926ebda..dedd3ea51345e6241eff7f6d6bb99d5bd3105b2f 100755
--- a/src/smf_app/smf_app.cpp
+++ b/src/smf_app/smf_app.cpp
@@ -459,7 +459,7 @@ void smf_app::handle_pdu_session_create_sm_context_request(
   oai::smf_server::model::SmContextCreateError smContextCreateError = { };
   oai::smf_server::model::ProblemDetails problem_details = { };
   oai::smf_server::model::RefToBinaryData refToBinaryData = { };
-  std::string n1_sm_message, n1_sm_message_hex;  //N1 SM container
+  std::string n1_sm_message, n1_sm_message_hex;
   smf_n1_n2 smf_n1_n2_inst = { };
   nas_message_t decoded_nas_msg = { };
 
@@ -467,46 +467,37 @@ void smf_app::handle_pdu_session_create_sm_context_request(
   std::string n1_sm_msg = smreq->req.get_n1_sm_message();
   memset(&decoded_nas_msg, 0, sizeof(nas_message_t));
 
-  pdu_session_create_sm_context_request context_req_msg = smreq->req;
-
   int decoder_rc = smf_n1_n2_inst.decode_n1_sm_container(decoded_nas_msg,
                                                          n1_sm_msg);
   if (decoder_rc != RETURNok) {
-    //error, should send reply to AMF with error code!!
+    //error, send reply to AMF with PDU Session Establishment Reject
     Logger::smf_app().warn("N1 SM container cannot be decoded correctly!");
     problem_details.setCause(
         pdu_session_application_error_e2str[PDU_SESSION_APPLICATION_ERROR_N1_SM_ERROR]);
     smContextCreateError.setError(problem_details);
     refToBinaryData.setContentId(N1_SM_CONTENT_ID);
     smContextCreateError.setN1SmMsg(refToBinaryData);
-    //PDU Session Establishment Reject
-    //24.501: response with a 5GSM STATUS message including cause "#95 Semantically incorrect message"
     smf_n1_n2_inst.create_n1_sm_container(
-        context_req_msg, PDU_SESSION_ESTABLISHMENT_REJECT, n1_sm_message,
+        smreq->req, PDU_SESSION_ESTABLISHMENT_REJECT, n1_sm_message,
         cause_value_5gsm_e::CAUSE_95_SEMANTICALLY_INCORRECT_MESSAGE);
     smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_message_hex);
-    //Send response 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;
   }
 
   Logger::smf_app().debug(
-      "NAS header information: extended protocol discriminator %d, security headertype %d",
+      "NAS information: Extended Protocol Discriminator %d, Security Header Type %d, Message Type %d",
       decoded_nas_msg.header.extended_protocol_discriminator,
-      decoded_nas_msg.header.security_header_type);
+      decoded_nas_msg.header.security_header_type,
+      decoded_nas_msg.plain.sm.header.message_type);
 
   //Extended protocol discriminator (Mandatory)
   smreq->req.set_epd(decoded_nas_msg.header.extended_protocol_discriminator);
-
-  //Message type (Mandatory) (PDU SESSION ESTABLISHMENT REQUEST message identity)
-  Logger::smf_app().debug("NAS header information, Message Type %d",
-                          decoded_nas_msg.plain.sm.header.message_type);
+  //Message type (Mandatory)
   smreq->req.set_message_type(decoded_nas_msg.plain.sm.header.message_type);
-
-  //Integrity protection maximum data rate (Mandatory)
-  //TODO:
-
+  //TODO: Integrity protection maximum data rate (Mandatory)
   //PDU session type (Optional)
   smreq->req.set_pdu_session_type(PDU_SESSION_TYPE_E_IPV4);  //set default value
   if (decoded_nas_msg.plain.sm.header.message_type
@@ -535,8 +526,8 @@ void smf_app::handle_pdu_session_create_sm_context_request(
   uint8_t message_type = decoded_nas_msg.plain.sm.header.message_type;
   std::string request_type = smreq->req.get_request_type();
   Logger::smf_app().info(
-      "Handle a PDU Session Create SM Context Request message from AMF, supi " SUPI_64_FMT ", dnn %s, snssai_sst %d",
-      supi64, dnn.c_str(), snssai.sST);
+      "Handle a PDU Session Create SM Context Request message from AMF, supi " SUPI_64_FMT ", dnn %s, snssai_sst %d, snssai_sd %s",
+      supi64, dnn.c_str(), snssai.sST, snssai.sD.c_str());
 
   //If no DNN information from UE, set to default value
   if (dnn.length() == 0) {
@@ -554,19 +545,17 @@ void smf_app::handle_pdu_session_create_sm_context_request(
     smContextCreateError.setError(problem_details);
     refToBinaryData.setContentId(N1_SM_CONTENT_ID);
     smContextCreateError.setN1SmMsg(refToBinaryData);
-    //PDU Session Establishment Reject
-    //(24.501 (section 7.3.1)) NAS N1 SM message: response with a 5GSM STATUS message including cause "#81 Invalid PTI value"
+    //PDU Session Establishment Reject including cause "#81 Invalid PTI value" (section 7.3.1 @3GPP TS 24.501)
     smf_n1_n2_inst.create_n1_sm_container(
-        context_req_msg, PDU_SESSION_ESTABLISHMENT_REJECT, n1_sm_message,
+        smreq->req, PDU_SESSION_ESTABLISHMENT_REJECT, n1_sm_message,
         cause_value_5gsm_e::CAUSE_81_INVALID_PTI_VALUE);
     smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_message_hex);
-    //Send response 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;
   }
-
-  context_req_msg.set_pti(pti);
+  smreq->req.set_pti(pti);
 
   //check pdu session id
   if ((pdu_session_id == PDU_SESSION_IDENTITY_UNASSIGNED )
@@ -589,12 +578,11 @@ void smf_app::handle_pdu_session_create_sm_context_request(
     //PDU Session Establishment Reject
     //(24.501 (section 7.4)) implementation dependent->do similar to UE: response with a 5GSM STATUS message including cause "#98 message type not compatible with protocol state."
     smf_n1_n2_inst.create_n1_sm_container(
-        context_req_msg,
+        smreq->req,
         PDU_SESSION_ESTABLISHMENT_REJECT,
         n1_sm_message,
-        cause_value_5gsm_e::CAUSE_98_MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE);  //TODO: should define 5GSM cause in 24.501
+        cause_value_5gsm_e::CAUSE_98_MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE);
     smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_message_hex);
-    //Send response to AMF
     smf_n11_inst->send_pdu_session_create_sm_context_response(
         smreq->http_response, smContextCreateError,
         Pistache::Http::Code::Forbidden, n1_sm_message_hex);
@@ -625,10 +613,9 @@ void smf_app::handle_pdu_session_create_sm_context_request(
     smContextCreateError.setN1SmMsg(refToBinaryData);
     //PDU Session Establishment Reject, 24.501 cause "#27 Missing or unknown DNN"
     smf_n1_n2_inst.create_n1_sm_container(
-        context_req_msg, PDU_SESSION_ESTABLISHMENT_REJECT, n1_sm_message,
+        smreq->req, PDU_SESSION_ESTABLISHMENT_REJECT, n1_sm_message,
         cause_value_5gsm_e::CAUSE_27_MISSING_OR_UNKNOWN_DNN);
     smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_message_hex);
-    //Send response to AMF
     smf_n11_inst->send_pdu_session_create_sm_context_response(
         smreq->http_response, smContextCreateError,
         Pistache::Http::Code::Forbidden, n1_sm_message_hex);
@@ -683,8 +670,7 @@ void smf_app::handle_pdu_session_create_sm_context_request(
       //update dnn_context with subscription info
       sc.get()->insert_dnn_subscription(snssai, subscription);
     } else {
-      // Cannot retrieve information from UDM,
-      //Not accept to establish a PDU session
+      // 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(
@@ -692,9 +678,9 @@ void smf_app::handle_pdu_session_create_sm_context_request(
       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"?
+      //PDU Session Establishment Reject, with cause "29 User authentication or authorization failed"
       smf_n1_n2_inst.create_n1_sm_container(
-          context_req_msg,
+          smreq->req,
           PDU_SESSION_ESTABLISHMENT_REJECT,
           n1_sm_message,
           cause_value_5gsm_e::CAUSE_29_USER_AUTHENTICATION_OR_AUTHORIZATION_FAILED);
@@ -723,8 +709,6 @@ void smf_app::handle_pdu_session_create_sm_context_request(
   Logger::smf_app().debug("Generated a SCID " SCID_FMT " ", scid);
 
   //Step 8. let the context handle the message
-  //in this step, SMF will send N4 Session Establishment/Modification to UPF (step 10a, section 4.3.2 3GPP 23.502)
-  //SMF, then, sends response to AMF
   sc.get()->handle_pdu_session_create_sm_context_request(smreq);
 
 }
@@ -744,7 +728,6 @@ void smf_app::handle_pdu_session_update_sm_context_request(
   try {
     scid = std::stoi(smreq->scid);
   } catch (const std::exception &err) {
-    //TODO: send PDUSession_SMUpdateContext Response to AMF with CAUSE: invalid context
     Logger::smf_app().warn(
         "Received a PDU Session Update SM Context Request, couldn't retrieve the corresponding SMF context, ignore message!");
     problem_details.setCause(
@@ -772,19 +755,12 @@ void smf_app::handle_pdu_session_update_sm_context_request(
     return;
   }
 
-  supi_t supi = scf.get()->supi;
-  std::string dnn = scf.get()->dnn;
-  pdu_session_id_t pdu_session_id = scf.get()->pdu_session_id;
-  snssai_t nssai = scf.get()->nssai;
-
   //Step 2. store supi, dnn, nssai  in itti_n11_update_sm_context_request to be processed later on
-  supi64_t supi64 = smf_supi_to_u64(supi);
-  smreq->req.set_supi(supi);
-  smreq->req.set_dnn(dnn);
-  smreq->req.set_snssai(nssai);
-  smreq->req.set_pdu_session_id(pdu_session_id);
-
-  pdu_session_update_sm_context_request context_req_msg = smreq->req;
+  supi64_t supi64 = smf_supi_to_u64(scf.get()->supi);
+  smreq->req.set_supi(scf.get()->supi);
+  smreq->req.set_dnn(scf.get()->dnn);
+  smreq->req.set_snssai(scf.get()->nssai);
+  smreq->req.set_pdu_session_id(scf.get()->pdu_session_id);
 
   //Step 2. find the smf context
   std::shared_ptr<smf_context> sc = { };
@@ -809,10 +785,9 @@ void smf_app::handle_pdu_session_update_sm_context_request(
   //get dnn context
   std::shared_ptr<dnn_context> sd = { };
 
-  if (!sc.get()->find_dnn_context(scf.get()->nssai, dnn, sd)) {
+  if (!sc.get()->find_dnn_context(scf.get()->nssai, scf.get()->dnn, sd)) {
     if (nullptr == sd.get()) {
-      //Error, DNN context doesn't exist
-      // send PDUSession_SMUpdateContext Response to AMF
+      //Error, DNN context doesn't exist, send PDUSession_SMUpdateContext Response to AMF
       Logger::smf_app().warn(
           "Received PDU Session Update SM Context Request, couldn't retrieve the corresponding SMF context, ignore message!");
       problem_details.setCause(
diff --git a/src/smf_app/smf_context.cpp b/src/smf_app/smf_context.cpp
index c9024fe7de18287aac1f25ea310abeac636fa127..c31ff26967f1171c612cd67f11bba7f3232f66f0 100644
--- a/src/smf_app/smf_context.cpp
+++ b/src/smf_app/smf_context.cpp
@@ -47,6 +47,7 @@
 extern "C" {
 #include "Ngap_PDUSessionResourceSetupResponseTransfer.h"
 #include "Ngap_PDUSessionResourceModifyResponseTransfer.h"
+#include "Ngap_PDUSessionResourceReleaseResponseTransfer.h"
 #include "Ngap_GTPTunnel.h"
 #include "Ngap_AssociatedQosFlowItem.h"
 #include "Ngap_QosFlowAddOrModifyResponseList.h"
@@ -289,7 +290,7 @@ void smf_pdu_session::deallocate_ressources(const std::string &apn) {
   if (ipv4) {
     paa_dynamic::get_instance().release_paa(apn, ipv4_address);
   }
-  clear(); //including qos_flows.clear()
+  clear();  //including qos_flows.clear()
   Logger::smf_app().info(
       "Resources associated with this PDU Session have been released");
 }
@@ -826,7 +827,7 @@ void smf_context::handle_pdu_session_create_sm_context_request(
     std::shared_ptr<itti_n11_create_sm_context_request> smreq) {
   Logger::smf_app().info(
       "Handle a PDU Session Create SM Context Request message from AMF");
-  pdu_session_create_sm_context_request sm_context_req_msg = smreq->req;
+
   oai::smf_server::model::SmContextCreateError smContextCreateError = { };
   oai::smf_server::model::ProblemDetails problem_details = { };
   oai::smf_server::model::RefToBinaryData refToBinaryData = { };
@@ -835,12 +836,12 @@ void smf_context::handle_pdu_session_create_sm_context_request(
   bool request_accepted = true;
 
   //Step 1. get necessary information
-  std::string dnn = sm_context_req_msg.get_dnn();
-  snssai_t snssai = sm_context_req_msg.get_snssai();
-  std::string request_type = sm_context_req_msg.get_request_type();
-  supi_t supi = sm_context_req_msg.get_supi();
+  std::string dnn = smreq->req.get_dnn();
+  snssai_t snssai = smreq->req.get_snssai();
+  std::string request_type = smreq->req.get_request_type();
+  supi_t supi = smreq->req.get_supi();
   supi64_t supi64 = smf_supi_to_u64(supi);
-  uint32_t pdu_session_id = sm_context_req_msg.get_pdu_session_id();
+  uint32_t pdu_session_id = smreq->req.get_pdu_session_id();
 
   //Step 2. check the validity of the UE request, if valid send PDU Session Accept, otherwise send PDU Session Reject to AMF
   if (!verify_sm_context_request(smreq)) {
@@ -852,9 +853,8 @@ void smf_context::handle_pdu_session_create_sm_context_request(
     smContextCreateError.setError(problem_details);
     refToBinaryData.setContentId(N1_SM_CONTENT_ID);
     smContextCreateError.setN1SmMsg(refToBinaryData);
-    //PDU Session Establishment Reject
     smf_n1_n2_inst.create_n1_sm_container(
-        sm_context_req_msg,
+        smreq->req,
         PDU_SESSION_ESTABLISHMENT_REJECT,
         n1_sm_message,
         cause_value_5gsm_e::CAUSE_29_USER_AUTHENTICATION_OR_AUTHORIZATION_FAILED);
@@ -875,11 +875,14 @@ void smf_context::handle_pdu_session_create_sm_context_request(
   std::shared_ptr<itti_n11_create_sm_context_response> sm_context_resp_pending =
       std::shared_ptr<itti_n11_create_sm_context_response>(sm_context_resp);
   sm_context_resp->res.set_supi(supi);
-  sm_context_resp->res.set_supi_prefix(sm_context_req_msg.get_supi_prefix());
+  sm_context_resp->res.set_supi_prefix(smreq->req.get_supi_prefix());
   sm_context_resp->res.set_cause(REQUEST_ACCEPTED);
   sm_context_resp->res.set_pdu_session_id(pdu_session_id);
   sm_context_resp->res.set_snssai(snssai);
   sm_context_resp->res.set_dnn(dnn);
+  sm_context_resp->res.set_pdu_session_type(
+      smreq->req.get_pdu_session_type());
+  sm_context_resp->res.set_pti(smreq->req.get_pti());
   sm_context_resp->set_scid(smreq->scid);
 
   //Step 3. find pdu_session
@@ -908,11 +911,10 @@ void smf_context::handle_pdu_session_create_sm_context_request(
 
   if (nullptr == sp.get()) {
     Logger::smf_app().debug("Create a new PDN connection!");
-    //create a new pdu session
     sp = std::shared_ptr<smf_pdu_session>(new smf_pdu_session());
-    sp.get()->pdn_type.pdn_type = sm_context_req_msg.get_pdu_session_type();
+    sp.get()->pdn_type.pdn_type = smreq->req.get_pdu_session_type();
     sp.get()->pdu_session_id = pdu_session_id;
-    sp.get()->amf_id = sm_context_req_msg.get_serving_nf_id();  //amf id
+    sp.get()->amf_id = smreq->req.get_serving_nf_id();  //amf id
     sd->insert_pdu_session(sp);
   } else {
     Logger::smf_app().debug("PDN connection is already existed!");
@@ -948,7 +950,6 @@ void smf_context::handle_pdu_session_create_sm_context_request(
           .ci_ip_address_allocation_via_nas_signalling = 0,
           .ci_ipv4_address_allocation_via_dhcpv4 = 0,
           .ci_ipv4_link_mtu_request = 0 };
-
   //smf_app_inst->process_pco_request(extended_protocol_options, pco_resp, pco_ids);
 
   //Step 7. Address allocation based on PDN type
@@ -1014,7 +1015,7 @@ void smf_context::handle_pdu_session_create_sm_context_request(
       smContextCreateError.setN1SmMsg(refToBinaryData);
       //PDU Session Establishment Reject
       smf_n1_n2_inst.create_n1_sm_container(
-          sm_context_req_msg, PDU_SESSION_ESTABLISHMENT_REJECT, n1_sm_message,
+          smreq->req, PDU_SESSION_ESTABLISHMENT_REJECT, n1_sm_message,
           cause_value_5gsm_e::CAUSE_28_UNKNOWN_PDU_SESSION_TYPE);
       smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_msg_hex);
       smf_n11_inst->send_pdu_session_create_sm_context_response(
@@ -1050,10 +1051,9 @@ void smf_context::handle_pdu_session_create_sm_context_request(
     //	std::string smContextRef = sm_context_req_msg.get_supi_prefix() + "-" + smf_supi_to_string(sm_context_req_msg.get_supi());
     std::string smContextRef = std::to_string(smreq->scid);
     //headers: Location: contains the URI of the newly created resource, according to the structure: {apiRoot}/nsmf-pdusession/{apiVersion}/sm-contexts/{smContextRef}
-    std::string uri = sm_context_req_msg.get_api_root() + "/"
+    std::string uri = smreq->req.get_api_root() + "/"
         + smContextRef.c_str();
 
-    //TODO: disable two following lines to test PDU SESSION ESTABLISHMENT ACCEPT
     sm_context_resp->http_response.headers()
         .add<Pistache::Http::Header::Location>(uri);
     smf_n11_inst->send_pdu_session_create_sm_context_response(
@@ -1276,6 +1276,15 @@ void smf_context::handle_pdu_session_update_sm_context_request(
          */
 
         //See section 6.4.2 - UE-requested PDU Session modification procedure@ 3GPP TS 24.501
+        //PDU Session Identity
+        //check if the PDU Session Release Command is already sent for this message (see section 6.3.3.5 @3GPP TS 24.501)
+        if (sp.get()->get_pdu_session_status() == pdu_session_status_e::PDU_SESSION_INACTIVE_PENDING) {
+          //Ignore the message
+          Logger::smf_app().info("A PDU Session Release Command has been sent for this session (session ID %d), ignore the message!",
+                      decoded_nas_msg.plain.sm.header.pdu_session_identity);
+          return;
+        }
+
         //PTI
         Logger::smf_app().info(
             "PTI %d",
@@ -1436,6 +1445,30 @@ void smf_context::handle_pdu_session_update_sm_context_request(
             != decoded_nas_msg.plain.sm.header.pdu_session_identity) {
           //TODO: PDU Session ID mismatch
         }
+        //Abnormal cases in network side (see section 6.4.3.6 @3GPP TS 24.501)
+        if (sp.get()->get_pdu_session_status() == pdu_session_status_e::PDU_SESSION_INACTIVE) {
+          Logger::smf_app().warn("PDU Session status: INACTIVE, send PDU Session Release Reject to UE!");
+          problem_details.setCause(
+              pdu_session_application_error_e2str[PDU_SESSION_APPLICATION_ERROR_NETWORK_FAILURE]); //TODO: which cause?
+          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::Forbidden, n1_sm_msg_hex);
+        }
+        //Abnormal cases in network side (see section 6.3.3.5 @3GPP TS 24.501)
+        if (sp.get()->get_pdu_session_status() == pdu_session_status_e::PDU_SESSION_INACTIVE_PENDING) {
+          //Ignore the message
+          Logger::smf_app().info("A PDU Session Release Command has been sent for this session (session ID %d), ignore the message!",
+                      decoded_nas_msg.plain.sm.header.pdu_session_identity);
+          return;
+        }
+
         //PTI
         Logger::smf_app().info(
             "PTI %d",
@@ -1449,19 +1482,27 @@ void smf_context::handle_pdu_session_update_sm_context_request(
         //5GSM Cause
         //Extended Protocol Configuration Options
 
-        //Release the resources related to this PDU Session
-        //The SMF releases the IP address / Prefix(es) that were allocated to the PDU Session and releases the
-        //corresponding User Plane resources
-
-        //SMF releases the IP address / Prefix(es) that were allocated to the PDU Session
+        //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())) {
-          //TODO: error cannot find the associated DNN context
+          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::Forbidden, n1_sm_msg_hex);
           return;
         }
 
@@ -1470,7 +1511,21 @@ void smf_context::handle_pdu_session_update_sm_context_request(
         if ((!sd.get()->find_pdu_session(
             sm_context_req_msg.get_pdu_session_id(), ss))
             or (nullptr == ss.get())) {
-          //TODO: error cannot find the corresponding PDU Session
+          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::Forbidden, n1_sm_msg_hex);
+          return;
         }
 
         //get the associated QoS flows: to be used for PFCP Session Modification procedure
@@ -1482,8 +1537,6 @@ void smf_context::handle_pdu_session_update_sm_context_request(
 
         //need to update UPF accordingly
         update_upf = true;
-
-        //TODO:
       }
         break;
 
@@ -1522,8 +1575,7 @@ void smf_context::handle_pdu_session_update_sm_context_request(
         itti_inst->timer_remove(sp.get()->timer_T3592);
 
         //send response to AMF
-        //Verify, do we need this?
-        oai::smf_server::model::SmContextCreatedData smContextCreatedData;
+        oai::smf_server::model::SmContextCreatedData smContextCreatedData; //Verify, do we need this?
         smf_n11_inst->send_pdu_session_create_sm_context_response(
             smreq->http_response, smContextCreatedData,
             Pistache::Http::Code::Ok);
@@ -1755,15 +1807,30 @@ void smf_context::handle_pdu_session_update_sm_context_request(
         procedure_type =
             session_management_procedures_type_e::PDU_SESSION_RELEASE_UE_REQUESTED_STEP2;
         //TODO: SMF does nothing (Step 7, section 4.3.4.2@3GPP TS 23.502)
-        //SMF send response to AMF
-
-        //Verify, do we need this?
-        oai::smf_server::model::SmContextCreatedData smContextCreatedData;
+        //Ngap_PDUSessionResourceReleaseResponseTransfer
+        std::shared_ptr<Ngap_PDUSessionResourceReleaseResponseTransfer_t> decoded_msg =
+            std::make_shared<Ngap_PDUSessionResourceReleaseResponseTransfer_t>();
+        int decode_status = smf_n1_n2_inst.decode_n2_sm_information(
+            decoded_msg, n2_sm_information);
+        if (decode_status == RETURNerror) {
+          Logger::smf_api_server().warn("asn_decode failed");
+          //send error to AMF
+          Logger::smf_app().warn(
+              "Decode N2 SM (Ngap_PDUSessionResourceReleaseResponseTransfer) failed!");
+          problem_details.setCause(
+              pdu_session_application_error_e2str[PDU_SESSION_APPLICATION_ERROR_N2_SM_ERROR]);
+          smContextUpdateError.setError(problem_details);
+          smf_n11_inst->send_pdu_session_update_sm_context_response(
+              smreq->http_response, smContextUpdateError,
+              Pistache::Http::Code::Forbidden);
+          return;
+        }
 
+        //SMF send response to AMF
+        oai::smf_server::model::SmContextCreatedData smContextCreatedData;  //Verify, do we need this?
         smf_n11_inst->send_pdu_session_create_sm_context_response(
             smreq->http_response, smContextCreatedData,
             Pistache::Http::Code::Ok);
-
       }
         break;
 
@@ -1823,7 +1890,7 @@ void smf_context::handle_pdu_session_update_sm_context_request(
       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::Forbidden, n1_sm_msg_hex);
+          Pistache::Http::Code::Forbidden);
       return;
 
     }
diff --git a/src/smf_app/smf_n11.cpp b/src/smf_app/smf_n11.cpp
index 90b7d3eadd70668b61b51c3c685d04b33efebf00..f61b111e524e4e5747164aaf2ee4eb0ec2ce2b1c 100644
--- a/src/smf_app/smf_n11.cpp
+++ b/src/smf_app/smf_n11.cpp
@@ -44,6 +44,10 @@
 #include "smf_config.hpp"
 #include "smf_n1_n2.hpp"
 
+extern "C" {
+#include "dynamic_memory_check.h"
+}
+
 using namespace Pistache::Http;
 using namespace Pistache::Http::Mime;
 
@@ -124,152 +128,63 @@ void smf_n11::send_n1n2_message_transfer_request(
     std::shared_ptr<itti_n11_create_sm_context_response> sm_context_res) {
   //Transfer N1/N2 message via AMF by using N_amf_Communication_N1N2MessageTransfer (see TS29518_Namf_Communication.yaml)
   //TODO: use RestSDK for client, use curl to send data for the moment
+
   Logger::smf_n11().debug("Send Communication_N1N2MessageTransfer to AMF");
 
   smf_n1_n2 smf_n1_n2_inst = { };
+  std::string n1_message = sm_context_res->res.get_n1_sm_message();
+  std::string json_part = sm_context_res->res.n1n2_message_transfer_data.dump();
+  std::string boundary = "----Boundary";
+  std::string body;
 
-  pdu_session_create_sm_context_response context_res_msg = sm_context_res->res;
-  std::string n1_message = context_res_msg.get_n1_sm_message();
-
-  /*
-   ENABLE THIS TO TEST NAS PDU SESSION ESTABLISHMENT ACCEPT
-   Don't forget to disable Http_response in SMF CONTEXT
-
-   std::string json_part = context_res_msg.n1n2_message_transfer_data.dump();
-   std::string boundary = "----Boundary";
-   std::string body;
-
-   create_multipart_related_content(body, json_part, boundary, n1_message, multipart_related_content_part_e::NAS);
-   sm_context_res->http_response.headers().add<Pistache::Http::Header::ContentType>(Pistache::Http::Mime::MediaType("multipart/related; boundary=" + boundary));
-   sm_context_res->http_response.send(Pistache::Http::Code::Ok, body);
-   */
-
-  /*
-   //format string as hex
-   unsigned char *msg_hex  = smf_app_inst->format_string_as_hex(n1_message);
-
-   string CRLF = "\r\n";
-   body.append("--" + boundary + CRLF);
-   body.append("Content-Type: application/json" + CRLF);
-   body.append(CRLF);
-   body.append(json_part + CRLF);
-
-   body.append("--" + boundary + CRLF);
-   //NAS
-   body.append("Content-Type: application/vnd.3gpp.5gnas"+  CRLF + "Content-Id: n1SmMsg" + CRLF);
-
-   body.append(CRLF);
-   body.append(std::string((char *)msg_hex, n1_message.length()/2) + CRLF);
-   body.append("--" + boundary + "--" + CRLF);
-
-   CURL *curl;
-   CURLcode res;
-
-
-   curl_global_init(CURL_GLOBAL_ALL);
-
-   curl = curl_easy_init();
-   if(curl) {
-   struct curl_slist *headers = nullptr;
-   //headers = curl_slist_append(headers, "charsets: utf-8");
-   headers = curl_slist_append(headers, "content-type: multipart/related; boundary=----Boundary");
-   curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
-   curl_easy_setopt(curl, CURLOPT_URL, context_res_msg.get_amf_url().c_str() );
-
-   curl_easy_setopt(curl, CURLOPT_HTTPGET,1);
-   curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, AMF_CURL_TIMEOUT_MS);
-   //curl_easy_setopt(curl, CURLOPT_INTERFACE, "eno1:sn11"); //Only for testing in all-in-one scenario
-   curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.c_str());
-
-   res = curl_easy_perform(curl);
-
-   if(res != CURLE_OK)
-   fprintf(stderr, "curl_easy_perform() failed: %s\n",
-   curl_easy_strerror(res));
-
-   curl_easy_cleanup(curl);
-   }
-   curl_global_cleanup();
+  //add N2 content if available
+  auto n2_sm_found = sm_context_res->res.n1n2_message_transfer_data.count(
+      "n2InfoContainer");
+  if (n2_sm_found > 0) {
+    std::string n2_message = sm_context_res->res.get_n2_sm_information();
+    //prepare the body content for Curl
+    create_multipart_related_content(body, json_part, boundary, n1_message,
+                                     n2_message);
+  } else {
+    //prepare the body content for Curl
+    create_multipart_related_content(body, json_part, boundary, n1_message,
+                                     multipart_related_content_part_e::NAS);
+  }
 
-   */
-
-  //format string as hex
-  unsigned char *n1_msg_hex = smf_app_inst->format_string_as_hex(n1_message);
+  unsigned int str_len = body.length();
+  char *data = (char*) malloc(str_len + 1);
+  memset(data, 0, str_len + 1);
+  memcpy((void*) data, (void*) body.c_str(), str_len);
 
+  curl_global_init(CURL_GLOBAL_ALL);
   CURL *curl = curl_easy_init();
 
-  //N1N2MessageTransfer Notification URI??
-  std::string json_part = context_res_msg.n1n2_message_transfer_data.dump();
-
-  Logger::smf_n11().debug("Sending message to AMF....");
-
   if (curl) {
     CURLcode res = { };
     struct curl_slist *headers = nullptr;
-    struct curl_slist *slist = nullptr;
-    curl_mime *mime;
-    curl_mime *alt;
-    curl_mimepart *part;
-
     //headers = curl_slist_append(headers, "charsets: utf-8");
-    headers = curl_slist_append(headers, "content-type: multipart/related");
+    headers = curl_slist_append(
+        headers, "content-type: multipart/related; boundary=----Boundary");  //TODO: update Boundary
     curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
-    curl_easy_setopt(curl, CURLOPT_URL, context_res_msg.get_amf_url().c_str());
+    curl_easy_setopt(curl, CURLOPT_URL,
+                     sm_context_res->res.get_amf_url().c_str());
     curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
     curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, AMF_CURL_TIMEOUT_MS);
     curl_easy_setopt(curl, CURLOPT_INTERFACE, smf_cfg.sbi.if_name.c_str());
 
-    mime = curl_mime_init(curl);
-    alt = curl_mime_init(curl);
-
-    //part with N1N2MessageTransferReqData (JsonData)
-    part = curl_mime_addpart(mime);
-    curl_mime_data(part, json_part.c_str(), CURL_ZERO_TERMINATED);
-    curl_mime_type(part, "application/json");
-
-    //N1 SM Container
-    Logger::smf_n11().debug(
-        "Add N1 SM Container (NAS) into the message: %s (bytes %d)",
-        context_res_msg.get_n1_sm_message().c_str(),
-        context_res_msg.get_n1_sm_message().length() / 2);
-    part = curl_mime_addpart(mime);
-    curl_mime_data(part, reinterpret_cast<const char*>(n1_msg_hex),
-                   context_res_msg.get_n1_sm_message().length() / 2);
-    curl_mime_type(part, "application/vnd.3gpp.5gnas");
-    curl_mime_name(
-        part,
-        context_res_msg.n1n2_message_transfer_data["n1MessageContainer"]["n1MessageContent"]["contentId"]
-            .dump().c_str());
-
-    auto n2_sm_found = context_res_msg.n1n2_message_transfer_data.count(
-        "n2InfoContainer");
-    if (n2_sm_found > 0) {
-      std::string n2_message = context_res_msg.get_n2_sm_information();
-      unsigned char *n2_msg_hex = smf_app_inst->format_string_as_hex(
-          n2_message);
-      Logger::smf_n11().debug(
-          "Add N2 SM Information (NGAP) into the message: %s (bytes %d)",
-          n2_message.c_str(), n2_message.length() / 2);
-      part = curl_mime_addpart(mime);
-      curl_mime_data(part, reinterpret_cast<const char*>(n2_msg_hex), 80);  //TODO: n2_message.length()/2 ISSUE need to be solved
-      curl_mime_type(part, "application/vnd.3gpp.ngap");
-      curl_mime_name(
-          part,
-          context_res_msg.n1n2_message_transfer_data["n2InfoContainer"]["smInfo"]["n2InfoContent"]["ngapData"]["contentId"]
-              .dump().c_str());
-    }
-
-    curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
-
     // Response information.
     long httpCode = { 0 };
     std::unique_ptr<std::string> httpData(new std::string());
 
-    // Hook up data handling function.
+    // Hook up data handling function
     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &callback);
     curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get());
 
+    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body.length());
+    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
+
     res = curl_easy_perform(curl);
+
     curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
 
     //get cause from the response
@@ -277,7 +192,7 @@ void smf_n11::send_n1n2_message_transfer_request(
     try {
       response_data = json::parse(*httpData.get());
     } catch (json::exception &e) {
-      Logger::smf_n11().error("Could not get the cause from the response");
+      Logger::smf_n11().warn("Could not get the cause from the response");
       //Set the default Cause
       response_data["cause"] = "504 Gateway Timeout";
     }
@@ -291,7 +206,7 @@ void smf_n11::send_n1n2_message_transfer_request(
     itti_msg->set_response_code(httpCode);
     itti_msg->set_scid(sm_context_res->scid);
     itti_msg->set_cause(response_data["cause"]);
-    if (context_res_msg.get_cause() == REQUEST_ACCEPTED) {
+    if (sm_context_res->res.get_cause() == REQUEST_ACCEPTED) {
       itti_msg->set_msg_type(PDU_SESSION_ESTABLISHMENT_ACCEPT);
     } else {
       itti_msg->set_msg_type(PDU_SESSION_ESTABLISHMENT_REJECT);
@@ -308,9 +223,130 @@ void smf_n11::send_n1n2_message_transfer_request(
 
     curl_slist_free_all(headers);
     curl_easy_cleanup(curl);
-    curl_mime_free(mime);
   }
+  curl_global_cleanup();
+  free_wrapper((void**) &data);
+
+  /*
+   //Curl MIME
+   //format string as hex
+   unsigned char *n1_msg_hex = smf_app_inst->format_string_as_hex(n1_message);
+
+   CURL *curl = curl_easy_init();
 
+   //N1N2MessageTransfer Notification URI??
+   std::string json_part = context_res_msg.n1n2_message_transfer_data.dump();
+
+   Logger::smf_n11().debug("Sending message to AMF....");
+
+   if (curl) {
+   CURLcode res = { };
+   struct curl_slist *headers = nullptr;
+   struct curl_slist *slist = nullptr;
+   curl_mime *mime;
+   curl_mime *alt;
+   curl_mimepart *part;
+
+   //headers = curl_slist_append(headers, "charsets: utf-8");
+   headers = curl_slist_append(headers, "content-type: multipart/related");
+   curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
+   curl_easy_setopt(curl, CURLOPT_URL, context_res_msg.get_amf_url().c_str());
+   curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
+   curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, AMF_CURL_TIMEOUT_MS);
+   curl_easy_setopt(curl, CURLOPT_INTERFACE, smf_cfg.sbi.if_name.c_str());
+
+   mime = curl_mime_init(curl);
+   alt = curl_mime_init(curl);
+
+   //part with N1N2MessageTransferReqData (JsonData)
+   part = curl_mime_addpart(mime);
+   curl_mime_data(part, json_part.c_str(), CURL_ZERO_TERMINATED);
+   curl_mime_type(part, "application/json");
+
+   //N1 SM Container
+   Logger::smf_n11().debug(
+   "Add N1 SM Container (NAS) into the message: %s (bytes %d)",
+   context_res_msg.get_n1_sm_message().c_str(),
+   context_res_msg.get_n1_sm_message().length() / 2);
+   part = curl_mime_addpart(mime);
+   curl_mime_data(part, reinterpret_cast<const char*>(n1_msg_hex),
+   context_res_msg.get_n1_sm_message().length() / 2);
+   curl_mime_type(part, "application/vnd.3gpp.5gnas");
+   curl_mime_name(
+   part,
+   context_res_msg.n1n2_message_transfer_data["n1MessageContainer"]["n1MessageContent"]["contentId"]
+   .dump().c_str());
+
+   auto n2_sm_found = context_res_msg.n1n2_message_transfer_data.count(
+   "n2InfoContainer");
+   if (n2_sm_found > 0) {
+   std::string n2_message = context_res_msg.get_n2_sm_information();
+   unsigned char *n2_msg_hex = smf_app_inst->format_string_as_hex(
+   n2_message);
+   Logger::smf_n11().debug(
+   "Add N2 SM Information (NGAP) into the message: %s (bytes %d)",
+   n2_message.c_str(), n2_message.length() / 2);
+   part = curl_mime_addpart(mime);
+   curl_mime_data(part, reinterpret_cast<const char*>(n2_msg_hex), 80);  //TODO: n2_message.length()/2 ISSUE need to be solved
+   curl_mime_type(part, "application/vnd.3gpp.ngap");
+   curl_mime_name(
+   part,
+   context_res_msg.n1n2_message_transfer_data["n2InfoContainer"]["smInfo"]["n2InfoContent"]["ngapData"]["contentId"]
+   .dump().c_str());
+   }
+
+   curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
+
+   // Response information.
+   long httpCode = { 0 };
+   std::unique_ptr<std::string> httpData(new std::string());
+
+   // Hook up data handling function.
+   curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &callback);
+   curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get());
+
+   res = curl_easy_perform(curl);
+   curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
+
+   //get cause from the response
+   json response_data = { };
+   try {
+   response_data = json::parse(*httpData.get());
+   } catch (json::exception &e) {
+   Logger::smf_n11().error("Could not get the cause from the response");
+   //Set the default Cause
+   response_data["cause"] = "504 Gateway Timeout";
+   }
+   Logger::smf_n11().debug("Response from AMF, Http Code: %d, cause %s",
+   httpCode, response_data["cause"].dump().c_str());
+
+   //send response to APP to process
+   itti_n11_n1n2_message_transfer_response_status *itti_msg =
+   new itti_n11_n1n2_message_transfer_response_status(TASK_SMF_N11,
+   TASK_SMF_APP);
+   itti_msg->set_response_code(httpCode);
+   itti_msg->set_scid(sm_context_res->scid);
+   itti_msg->set_cause(response_data["cause"]);
+   if (context_res_msg.get_cause() == REQUEST_ACCEPTED) {
+   itti_msg->set_msg_type(PDU_SESSION_ESTABLISHMENT_ACCEPT);
+   } else {
+   itti_msg->set_msg_type(PDU_SESSION_ESTABLISHMENT_REJECT);
+   }
+   std::shared_ptr<itti_n11_n1n2_message_transfer_response_status> i =
+   std::shared_ptr<itti_n11_n1n2_message_transfer_response_status>(
+   itti_msg);
+   int ret = itti_inst->send_msg(i);
+   if (RETURNok != ret) {
+   Logger::smf_n11().error(
+   "Could not send ITTI message %s to task TASK_SMF_APP",
+   i->get_msg_name());
+   }
+
+   curl_slist_free_all(headers);
+   curl_easy_cleanup(curl);
+   curl_mime_free(mime);
+   }
+   */
 }
 
 //------------------------------------------------------------------------------
diff --git a/src/smf_app/smf_n1_n2.cpp b/src/smf_app/smf_n1_n2.cpp
index 6cd7c99a5af264770acf1b11e8b60b8b16f30304..c93647e2c79760a63e1ebe76c032725d1f263490 100644
--- a/src/smf_app/smf_n1_n2.cpp
+++ b/src/smf_app/smf_n1_n2.cpp
@@ -109,7 +109,7 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg &msg,
   //Extended Protocol Discriminator
   sm_msg->header.extended_protocol_discriminator =
       EPD_5GS_SESSION_MANAGEMENT_MESSAGES;
-  //Message Type
+  //PDU Session Identity
   sm_msg->header.pdu_session_identity = msg.get_pdu_session_id();
 
   switch (n1_msg_type) {
@@ -131,7 +131,6 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg &msg,
       //get default QoS value
       qos_flow_context_updated qos_flow = { };
       qos_flow = sm_context_res.get_qos_flow_context();
-
       //TODO: to be completed
       //get the default QoS profile and assign to the NAS message
 
@@ -156,7 +155,7 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg &msg,
           sm_msg->header.procedure_transaction_identity,
           sm_msg->header.message_type);
 
-      //Fill the content of PDU Session Establishment Request message
+      //Fill the content of PDU Session Establishment Accept message
       //PDU Session Type
       sm_msg->pdu_session_establishment_accept._pdusessiontype
           .pdu_session_type_value = sm_context_res.get_pdu_session_type();
@@ -277,10 +276,12 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg &msg,
           .get_snssai().sST;
 
       try {
-        sm_msg->pdu_session_establishment_accept.snssai.sd = std::stoi(
-            sm_context_res.get_snssai().sD);
+        sm_msg->pdu_session_establishment_accept.snssai.sd = std::stoul(
+            sm_context_res.get_snssai().sD, nullptr, 16);
       } catch (const std::exception &e) {
-        Logger::smf_app().warn("Error when converting from string to int for snssai.SD, error: %s", e.what());
+        Logger::smf_app().warn(
+            "Error when converting from string to int for snssai.SD, error: %s",
+            e.what());
         //"no SD value associated with the SST"
         sm_msg->pdu_session_establishment_accept.snssai.sd = 0xFFFFFF;
       }
@@ -358,7 +359,7 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg &msg,
       //1 - PDU Session Create SM Context Response (PDU Session Establishment procedure - reject)
       //2 - N1N2MessageTransfer Request (PDU Session Establishment procedure - reject)
       //3-  PDU Session Update SM Context Response (PDU Session Establishment procedure - reject)​
-      //PDU_SESSION_CREATE_SM_CONTEXT_RESPONSE or  PDU_SESSION_CREATE_SM_CONTEXT_REQUEST
+      //PDU_SESSION_CREATE_SM_CONTEXT_RESPONSE or PDU_SESSION_CREATE_SM_CONTEXT_REQUEST
 
       Logger::smf_app().info(
           "PDU_SESSION_ESTABLISHMENT_REJECT, encode starting...");
@@ -386,7 +387,8 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg &msg,
       sm_msg->pdu_session_establishment_reject._5gsmcause =
           static_cast<uint8_t>(sm_cause);
       //Presence
-      sm_msg->pdu_session_establishment_reject.presence = 0x00;
+      sm_msg->pdu_session_establishment_reject.presence =
+      PDU_SESSION_ESTABLISHMENT_REJECT_ALLOWED_SSC_MODE_PRESENCE;  //Should be updated according to the following IEs
       /*
        //GPRSTimer3
        sm_msg->pdu_session_establishment_reject.gprstimer3.unit =
@@ -436,8 +438,6 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg &msg,
               .is_ssc2_allowed,
           sm_msg->pdu_session_establishment_reject.allowedsscmode
               .is_ssc3_allowed);
-      //Logger::smf_app().debug("SM MSG, GPSR Timer3, unit: 0x%x, value: 0x%x",sm_msg->pdu_session_establishment_reject.gprstimer3.unit,sm_msg->pdu_session_establishment_reject.gprstimer3.timeValue);
-      //Logger::smf_app().debug("SM MSG, 5G SM Congestion Re-attempt Indicator: 0x%x",sm_msg->pdu_session_establishment_reject._5gsmcongestionreattemptindicator.abo);
 
       //Encode NAS message
       bytes = nas_message_encode(data, &nas_msg,
@@ -455,7 +455,7 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg &msg,
       break;
 
     case PDU_SESSION_MODIFICATION_COMMAND: {
-      //PDU Session Modification Command is included in the following msgs:
+      //PDU Session Modification Command is included in the following messages:
       //1- PDU Session Update SM Context Response (PDU Session Modification UE-Initiated procedure - step 1)
       //2- N1N2MessageTransfer Request (PDU Session Modification SMF-Requested, step 1 (from SMF to AMF)) ​
 
@@ -469,19 +469,35 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg &msg,
           "PDU_SESSION_MODIFICATION_COMMAND, encode starting...");
 
       //Fill the content of PDU Session Establishment Request message with hardcoded values (to be completed)
-      //Message Type
-      sm_msg->header.message_type = PDU_SESSION_MODIFICATION_COMMAND;
       //PTI
       sm_msg->header.procedure_transaction_identity = sm_context_res.get_pti()
           .procedure_transaction_id;
+      //Message Type
+      sm_msg->header.message_type = PDU_SESSION_MODIFICATION_COMMAND;
       //PDU Session Type
       sm_msg->pdu_session_modification_command.messagetype = sm_context_res
           .get_msg_type();
       //Presence
       sm_msg->pdu_session_modification_command.presence = 0xff;  //TODO: to be updated
       //5GSMCause
-      sm_msg->pdu_session_modification_command._5gsmcause = sm_context_res
-          .get_cause();
+      sm_msg->pdu_session_modification_command._5gsmcause =
+          static_cast<uint8_t>(sm_cause);  //sm_context_res.get_cause();
+
+      /*
+       ExtendedProtocolDiscriminator extendedprotocoldiscriminator;
+       PDUSessionIdentity pdusessionidentity;
+       ProcedureTransactionIdentity proceduretransactionidentity;
+       MessageType messagetype;
+       uint8_t presence;
+       _5GSMCause _5gsmcause;
+       SessionAMBR sessionambr;
+       GPRSTimer gprstimer;
+       AlwaysonPDUSessionIndication alwaysonpdusessionindication;
+       QOSRules qosrules;
+       MappedEPSBearerContexts mappedepsbearercontexts;
+       QOSFlowDescriptions qosflowdescriptions;
+       ExtendedProtocolConfigurationOptions extendedprotocolconfigurationoptions;
+       */
 
       //SessionAMBR
       //TODO: get from subscription DB
@@ -590,7 +606,6 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg &msg,
       //this IE is included in the following message
       //1 - PDU Session Update SM Context Response (PDU Session Release UE-Initiated, step 1)
       //2 - N1N2MessageTransfer Request (PDU Session Release SMF-Requested, step 1)
-      //TODO: to be completed
 
       Logger::smf_app().debug(
           "[Create N1 SM Message] PDU Session Release Command");
@@ -599,26 +614,68 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg &msg,
           static_cast<pdu_session_update_sm_context_response&>(msg);
 
       Logger::smf_app().info("PDU_SESSION_RELEASE_COMMAND, encode starting...");
-      //Fill the content of PDU Session Release Command (with hardcoded values)
-      //Message Type
-      sm_msg->header.message_type = PDU_SESSION_RELEASE_COMMAND;
+      //Fill the content of PDU Session Release Command
+      //PDU Session ID
+      sm_msg->header.pdu_session_identity = sm_context_res.get_pdu_session_id();
       //PTI
       sm_msg->header.procedure_transaction_identity = sm_context_res.get_pti()
           .procedure_transaction_id;
-      //PDU Session Type
-      sm_msg->pdu_session_release_command.messagetype = sm_context_res
-          .get_msg_type();
+      //Message Type
+      sm_msg->header.message_type = PDU_SESSION_RELEASE_COMMAND;
       //5GSMCause
       sm_msg->pdu_session_release_command._5gsmcause =
-          sm_context_res.get_cause();
+          static_cast<uint8_t>(sm_cause);  //sm_context_res.get_cause();
       //Presence
-      sm_msg->pdu_session_modification_command.presence = 0x00;  //TODO: to be updated
-
+      sm_msg->pdu_session_release_command.presence = 0x00;  //TODO: to be updated when adding the following IEs
       //GPRSTimer3
       //EAPMessage
       //_5GSMCongestionReattemptIndicator
       // ExtendedProtocolConfigurationOptions
 
+      Logger::smf_app().debug("SM MSG, 5GSM Cause: 0x%x, %d",
+                              sm_msg->pdu_session_release_command._5gsmcause,
+                              static_cast<uint8_t>(sm_cause));
+
+      //Encode NAS message
+      bytes = nas_message_encode(data, &nas_msg,
+                                 sizeof(data)/*don't know the size*/, nullptr);
+
+      Logger::smf_app().debug("Buffer Data: ");
+      for (int i = 0; i < bytes; i++)
+        printf("%02x ", data[i]);
+      printf(" (bytes %d)\n", bytes);
+
+      std::string n1Message((char*) data, bytes);
+      nas_msg_str = n1Message;
+
+    }
+      break;
+
+    case PDU_SESSION_RELEASE_REJECT: {
+      //This IE is included in the PDU Session Update SM Context Response (PDU Session Release UE-Initiated, step 1)
+
+      Logger::smf_app().debug(
+          "[Create N1 SM Message] PDU Session Release Reject");
+      Logger::smf_app().info("PDU_SESSION_RELEASE_REJECT, encode starting...");
+      pdu_session_update_sm_context_response &sm_context_res =
+          static_cast<pdu_session_update_sm_context_response&>(msg);
+
+      //Fill the content of PDU Session Release Reject
+      //PDU Session ID
+      sm_msg->header.pdu_session_identity = sm_context_res.get_pdu_session_id();
+      //PTI
+      sm_msg->header.procedure_transaction_identity = sm_context_res.get_pti()
+          .procedure_transaction_id;
+      //Message Type
+      sm_msg->header.message_type = PDU_SESSION_RELEASE_REJECT;
+      //5GSMCause
+      sm_msg->pdu_session_release_reject._5gsmcause =
+          static_cast<uint8_t>(sm_cause);  //sm_context_res.get_cause();
+
+      //Presence
+      sm_msg->pdu_session_release_command.presence = 0x00;  //TODO: to be updated when adding the following IE
+      //Extended protocol configuration options
+
       //Encode NAS message
       bytes = nas_message_encode(data, &nas_msg,
                                  sizeof(data)/*don't know the size*/, nullptr);
@@ -1505,3 +1562,33 @@ int smf_n1_n2::decode_n2_sm_information(
 
 }
 
+//---------------------------------------------------------------------------------------------
+int smf_n1_n2::decode_n2_sm_information(
+    std::shared_ptr<Ngap_PDUSessionResourceReleaseResponseTransfer_t> &ngap_IE,
+    std::string &n2_sm_info) {
+  Logger::smf_app().info(
+      "Decode NGAP message (Ngap_PDUSessionResourceReleaseResponseTransfer) from N2 SM Information");
+
+  unsigned int data_len = n2_sm_info.length();
+  unsigned char *data = (unsigned char*) malloc(data_len + 1);
+  memset(data, 0, data_len + 1);
+  memcpy((void*) data, (void*) n2_sm_info.c_str(), data_len);
+
+  //Ngap_PDUSessionResourceModifyResponseTransfer
+  asn_dec_rval_t rc = asn_decode(
+      nullptr, ATS_ALIGNED_CANONICAL_PER,
+      &asn_DEF_Ngap_PDUSessionResourceReleaseResponseTransfer,
+      (void**) &ngap_IE, (void*) data, data_len);
+
+  //free memory
+  free_wrapper((void**) &data);
+
+  if (rc.code != RC_OK) {
+    Logger::smf_api_server().warn("asn_decode failed with code %d", rc.code);
+
+    return RETURNerror ;
+  }
+  return RETURNok ;
+
+}
+
diff --git a/src/smf_app/smf_n1_n2.hpp b/src/smf_app/smf_n1_n2.hpp
index 8f38869971a9a37b077564515d2bcee00e90a7b1..e864c32a17e18f907f5c5510af1b95aea11f1f90 100644
--- a/src/smf_app/smf_n1_n2.hpp
+++ b/src/smf_app/smf_n1_n2.hpp
@@ -56,6 +56,7 @@ extern "C" {
 #include "Ngap_NGAP-PDU.h"
 #include "Ngap_PDUSessionResourceSetupResponseTransfer.h"
 #include "Ngap_PDUSessionResourceModifyResponseTransfer.h"
+#include "Ngap_PDUSessionResourceReleaseResponseTransfer.h"
 }
 
 namespace smf {
@@ -121,6 +122,16 @@ class smf_n1_n2 {
       std::shared_ptr<Ngap_PDUSessionResourceModifyResponseTransfer_t> &ngap_IE,
       std::string &n2_sm_info);
 
+  /*
+   * Decode N2 SM Information Ngap_PDUSessionResourceReleaseResponseTransfer_t
+   * @param [std::shared_ptr<Ngap_PDUSessionResourceReleaseResponseTransfer_t>&] ngap_IE Store decoded NGAP message
+   * @param [std::string&] n2_sm_info N2 SM Information
+   * @return status of the decode process
+   */
+  int decode_n2_sm_information(
+      std::shared_ptr<Ngap_PDUSessionResourceReleaseResponseTransfer_t> &ngap_IE,
+      std::string &n2_sm_info);
+
 };
 
 }  // namespace smf
diff --git a/src/smf_app/smf_procedure.cpp b/src/smf_app/smf_procedure.cpp
index 4b8ab3d32927cc64bb84796977a8e812e4307a56..bdbd1b809582a10a5df1fb5671aeca9de14cae8d 100644
--- a/src/smf_app/smf_procedure.cpp
+++ b/src/smf_app/smf_procedure.cpp
@@ -389,8 +389,7 @@ void session_create_sm_context_procedure::handle_itti_msg(
     Logger::smf_app().debug(
         "Prepare a PDU Session Establishment Accept message and send to UE");
     smf_n1_n2_inst.create_n1_sm_container(n11_triggered_pending->res,
-    PDU_SESSION_ESTABLISHMENT_ACCEPT,
-                                          n1_sm_msg,
+    PDU_SESSION_ESTABLISHMENT_ACCEPT, n1_sm_msg,
                                           cause_value_5gsm_e::CAUSE_0_UNKNOWN);  //TODO: need cause?
     smf_app_inst->convert_string_2_hex(n1_sm_msg, n1_sm_msg_hex);
     n11_triggered_pending->res.set_n1_sm_message(n1_sm_msg_hex);
@@ -1100,6 +1099,7 @@ void session_update_sm_context_procedure::handle_itti_msg(
           cause_value_5gsm_e::CAUSE_26_INSUFFICIENT_RESOURCES);  //TODO: check Cause
       smf_app_inst->convert_string_2_hex(n1_sm_msg, n1_sm_msg_hex);
       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_REL_CMD,
diff --git a/src/test/amf/amf-api-server.cpp b/src/test/amf/amf-api-server.cpp
index e7702800f6c4f7a8f33876f1034e7f8ffba92331..0c5d85fc5890b3a7077b01117447071cb48f8ad3 100644
--- a/src/test/amf/amf-api-server.cpp
+++ b/src/test/amf/amf-api-server.cpp
@@ -127,6 +127,8 @@ int main(int argc, char* argv[]) {
     SubscriptionsCollectionDocumentApiImpl SubscriptionsCollectionDocumentApiserver(router);
     SubscriptionsCollectionDocumentApiserver.init();
 
+    std::cout  << "AMF server is listening on address: " << amf_ip_address.c_str() << std::endl;
+
     httpEndpoint->setHandler(router->handler());
     httpEndpoint->serve();
 
diff --git a/src/test/amf_client/amf-client.cpp b/src/test/amf_client/amf-client.cpp
index 7e1126d829cde3a17810a939669e1b3855f14953..8f6e6536324e677bebe0e79de736521d8c72130b 100644
--- a/src/test/amf_client/amf-client.cpp
+++ b/src/test/amf_client/amf-client.cpp
@@ -1,18 +1,15 @@
-
 #include <curl/curl.h>
 #include <nlohmann/json.hpp>
 #include <iostream>
 #include <string>
 #include <unistd.h>
+#include <stdexcept>
+
 /*
  * To read content of the response from UDM
  */
-static std::size_t callback(
-    const char* in,
-    std::size_t size,
-    std::size_t num,
-    std::string* out)
-{
+static std::size_t callback(const char *in, std::size_t size, std::size_t num,
+                            std::string *out) {
   const std::size_t totalBytes(size * num);
   out->append(in, totalBytes);
   return totalBytes;
@@ -22,35 +19,180 @@ static std::size_t callback(
     *(uint8_t*)(buffer) = value;    \
     size += sizeof(uint8_t)
 
-void send_pdu_session_establishment_request(std::string smf_ip_address)
-{
-  std::cout << "[AMF N11] PDU Session Establishment Request (SM Context Create)"<<std::endl;
+static const char hex_to_ascii_table[16] = { '0', '1', '2', '3', '4', '5', '6',
+    '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', };
+
+static const signed char ascii_to_hex_table[0x100] = { -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1,
+    10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1 };
+
+int ascii_to_hex(uint8_t *dst, const char *h) {
+  const unsigned char *hex = (const unsigned char*) h;
+  unsigned i = 0;
+
+  for (;;) {
+    int high, low;
+
+    while (*hex && isspace(*hex))
+      hex++;
+
+    if (!*hex)
+      return 1;
+
+    high = ascii_to_hex_table[*hex++];
+
+    if (high < 0)
+      return 0;
+
+    while (*hex && isspace(*hex))
+      hex++;
+
+    if (!*hex)
+      return 0;
+
+    low = ascii_to_hex_table[*hex++];
+
+    if (low < 0)
+      return 0;
+
+    dst[i++] = (high << 4) | low;
+  }
+}
+
+enum class multipart_related_content_part_e {
+  JSON = 0,
+  NAS = 1,
+  NGAP = 2
+};
+
+//------------------------------------------------------------------------------
+unsigned char* format_string_as_hex(std::string str) {
+  unsigned int str_len = str.length();
+  char *data = (char*) malloc(str_len + 1);
+  memset(data, 0, str_len + 1);
+  memcpy((void*) data, (void*) str.c_str(), str_len);
+
+  unsigned char *data_hex = (uint8_t*) malloc(str_len / 2 + 1);
+  ascii_to_hex(data_hex, (const char*) data);
+
+  std::cout << "[Format string as Hex] Input string" << str.c_str() << "("
+            << str_len << " bytes)" << std::endl;
+  std::cout << "Data (formatted):" << std::endl;
+
+  for (int i = 0; i < str_len / 2; i++)
+    printf(" %02x ", data_hex[i]);
+  printf("\n");
+
+  //free memory
+  free(data);
+
+  return data_hex;
+
+}
+
+//------------------------------------------------------------------------------
+void create_multipart_related_content(std::string &body, std::string &json_part,
+                                      std::string &boundary,
+                                      std::string &n1_message,
+                                      std::string &n2_message) {
+
+  //format string as hex
+  //unsigned char *n1_msg_hex = format_string_as_hex(n1_message);
+  //unsigned char *n2_msg_hex = format_string_as_hex(n2_message);
+
+  std::string CRLF = "\r\n";
+  body.append("--" + boundary + CRLF);
+  body.append("Content-Type: application/json" + CRLF);
+  body.append(CRLF);
+  body.append(json_part + CRLF);
+
+  body.append("--" + boundary + CRLF);
+  body.append(
+      "Content-Type: application/vnd.3gpp.5gnas" + CRLF + "Content-Id: n1SmMsg"
+          + CRLF);
+  body.append(CRLF);
+  //body.append(std::string((char*) n1_msg_hex, n1_message.length() / 2) + CRLF);
+  body.append(n1_message + CRLF);
+
+  body.append("--" + boundary + CRLF);
+  body.append(
+      "Content-Type: application/vnd.3gpp.ngap" + CRLF + "Content-Id: n2SmMsg"
+          + CRLF);
+  body.append(CRLF);
+  //body.append(std::string((char*) n2_msg_hex, n2_message.length() / 2) + CRLF);
+  body.append(n2_message + CRLF);
+  body.append("--" + boundary + "--" + CRLF);
+}
+
+//------------------------------------------------------------------------------
+void create_multipart_related_content(
+    std::string &body, std::string &json_part, std::string &boundary,
+    std::string &message, multipart_related_content_part_e content_type) {
+
+  //format string as hex
+  //unsigned char *msg_hex = format_string_as_hex(message);
+
+  std::string CRLF = "\r\n";
+  body.append("--" + boundary + CRLF);
+  body.append("Content-Type: application/json" + CRLF);
+  body.append(CRLF);
+  body.append(json_part + CRLF);
+
+  body.append("--" + boundary + CRLF);
+  if (content_type == multipart_related_content_part_e::NAS) {  //NAS
+    body.append(
+        "Content-Type: application/vnd.3gpp.5gnas" + CRLF
+            + "Content-Id: n1SmMsg" + CRLF);
+  } else if (content_type == multipart_related_content_part_e::NGAP) {  //NGAP
+    body.append(
+        "Content-Type: application/vnd.3gpp.ngap" + CRLF + "Content-Id: n2SmMsg"
+            + CRLF);
+  }
+  body.append(CRLF);
+  //body.append(std::string((char*) msg_hex, message.length() / 2) + CRLF);
+  body.append(message + CRLF);
+  body.append("--" + boundary + "--" + CRLF);
+}
+
+//------------------------------------------------------------------------------
+void send_pdu_session_establishment_request(std::string smf_ip_address) {
+  std::cout << "[AMF N11] PDU Session Establishment Request (SM Context Create)"
+            << std::endl;
 
   nlohmann::json pdu_session_establishment_request;
-  //encode
-  // PDU Session Establishment Request
+  //encode PDU Session Establishment Request
   /*
-    0000   2e 01 01 c1 ff ff 91 00 00 00 00 00 00 00 00 00
+   0000   2e 01 01 c1 ff ff 91 00 00 00 00 00 00 00 00 00
    */
   size_t buffer_size = 128;
-  char *buffer = (char *)calloc(1,buffer_size);
-  int  size = 0;
-  ENCODE_U8 (buffer, 0x2e , size); //ExtendedProtocolDiscriminator
-  ENCODE_U8 (buffer+size, 0x01 , size); //PDUSessionIdentity
-  ENCODE_U8 (buffer+size, 0x01 , size); //ProcedureTransactionIdentity
-  ENCODE_U8 (buffer+size, 0xc1 , size); //MessageType - PDU_SESSION_ESTABLISHMENT_REQUEST
-  ENCODE_U8 (buffer+size, 0xff , size); //Integrity Protection Maximum Data Rate
-  ENCODE_U8 (buffer+size, 0xff , size); //Integrity Protection Maximum Data Rate
-  ENCODE_U8 (buffer+size, 0x91 , size); //01 PDU Session Type - Ipv4
-
-  std::cout << "Buffer: "<<std::endl;
-  for(int i=0;i<size;i++)
-  {
+  char *buffer = (char*) calloc(1, buffer_size);
+  int size = 0;
+  ENCODE_U8(buffer, 0x2e, size);  //ExtendedProtocolDiscriminator
+  ENCODE_U8(buffer + size, 0x01, size);  //PDUSessionIdentity
+  ENCODE_U8(buffer + size, 0x01, size);  //ProcedureTransactionIdentity
+  ENCODE_U8(buffer + size, 0xc1, size);  //MessageType - PDU_SESSION_ESTABLISHMENT_REQUEST
+  ENCODE_U8(buffer + size, 0xff, size);  //Integrity Protection Maximum Data Rate
+  ENCODE_U8(buffer + size, 0xff, size);  //Integrity Protection Maximum Data Rate
+  ENCODE_U8(buffer + size, 0x91, size);  //01 PDU Session Type - Ipv4
+
+  std::cout << "Buffer: " << std::endl;
+  for (int i = 0; i < size; i++) {
     printf("%02x ", buffer[i]);
   }
-  std::cout << "Buffer: "<<std::endl;
+  std::cout << "Buffer: " << std::endl;
 
-  //Fill Json part
   std::string url = std::string("http://");
   url.append(smf_ip_address);
   url.append(std::string("/nsmf-pdusession/v2/sm-contexts"));
@@ -59,7 +201,7 @@ void send_pdu_session_establishment_request(std::string smf_ip_address)
   pdu_session_establishment_request["supi"] = "imsi-200000000000001";
   pdu_session_establishment_request["pei"] = "imei-200000000000001";
   pdu_session_establishment_request["gpsi"] = "msisdn-200000000001";
-  pdu_session_establishment_request["dnn"] = "carrier.com";
+  pdu_session_establishment_request["dnn"] = "default";
   pdu_session_establishment_request["sNssai"]["sst"] = 222;
   pdu_session_establishment_request["sNssai"]["sd"] = "0000D4";
   pdu_session_establishment_request["pduSessionId"] = 1;
@@ -68,499 +210,463 @@ void send_pdu_session_establishment_request(std::string smf_ip_address)
   pdu_session_establishment_request["servingNetwork"]["mcc"] = "234";
   pdu_session_establishment_request["servingNetwork"]["mnc"] = "067";
   pdu_session_establishment_request["anType"] = "3GPP_ACCESS";
-  pdu_session_establishment_request["smContextStatusUri"] = "smContextStatusUri";
-  pdu_session_establishment_request["n1SmMsg"]["contentId"] = "n1SmMsg"; // NAS
+  pdu_session_establishment_request["smContextStatusUri"] =
+      "smContextStatusUri";
+  pdu_session_establishment_request["n1SmMsg"]["contentId"] = "n1SmMsg";  // NAS
 
+  std::string body;
+  std::string boundary = "----Boundary";
+  std::string json_part = pdu_session_establishment_request.dump();
+  std::string n1_msg(reinterpret_cast<const char*>(buffer), size);
 
-  CURL *curl = curl_easy_init();
+  create_multipart_related_content(body, json_part, boundary, n1_msg,
+                                   multipart_related_content_part_e::NAS);
 
-  std::string json_part = pdu_session_establishment_request.dump();
+  unsigned char *data = (unsigned char*) malloc(body.length() + 1);
+  memset(data, 0, body.length() + 1);
+  memcpy((void*) data, (void*) body.c_str(), body.length());
 
-  std::cout<< "Sending message to SMF....\n";
-  if(curl) {
-    CURLcode res;
-    struct curl_slist *headers = nullptr;
-    struct curl_slist *slist = nullptr;
-    curl_mime *mime;
-    curl_mime *alt;
-    curl_mimepart *part;
+  curl_global_init(CURL_GLOBAL_ALL);
+  CURL *curl = curl = curl_easy_init();
 
+  if (curl) {
+    CURLcode res = { };
+    struct curl_slist *headers = nullptr;
     //headers = curl_slist_append(headers, "charsets: utf-8");
-    headers = curl_slist_append(headers, "content-type: multipart/related");
+    headers = curl_slist_append(
+        headers, "content-type: multipart/related; boundary=----Boundary");
     curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
     curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
-    curl_easy_setopt(curl, CURLOPT_HTTPGET,1);
+    curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
     curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 100L);
-    //curl_easy_setopt(curl, CURLOPT_INTERFACE, "eno1:amf"); //hardcoded
-
-    mime = curl_mime_init(curl);
-    alt = curl_mime_init(curl);
-
-    //part with N1N2MessageTransferReqData (JsonData)
-    part = curl_mime_addpart(mime);
-    curl_mime_data(part, json_part.c_str(), CURL_ZERO_TERMINATED);
-    curl_mime_type(part, "application/json");
-
-    part = curl_mime_addpart(mime);
-    //curl_mime_data(part, reinterpret_cast<const char*>(n1_msg_hex), CURL_ZERO_TERMINATED);
-    curl_mime_data(part, reinterpret_cast<const char*>(buffer), size);
-    curl_mime_type(part, "application/vnd.3gpp.5gnas");
-    curl_mime_name (part, "n1SmMsg");
-
-    curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
+    //curl_easy_setopt(curl, CURLOPT_INTERFACE, "eno1:amf");  //hardcoded
 
     // Response information.
-    long httpCode(0);
+    long httpCode = { 0 };
     std::unique_ptr<std::string> httpData(new std::string());
 
-    // Hook up data handling function.
     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &callback);
     curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get());
 
+    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body.length());
+    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
+
     res = curl_easy_perform(curl);
+
     curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
 
     //get cause from the response
     nlohmann::json response_data;
-    try{
+    try {
       response_data = nlohmann::json::parse(*httpData.get());
-    } catch (nlohmann::json::exception& e){
-      std::cout << "Could not get the cause from the response" <<std::endl;
-
+    } catch (nlohmann::json::exception &e) {
+      std::cout << "Could not get json data from the response" << std::endl;
     }
-    std::cout << "[AMF N11] PDU session establishment request, response from SMF, Http Code " << httpCode <<std::endl;
+    std::cout
+        << "[AMF N11] PDU session establishment request, response from SMF, Http Code "
+        << httpCode << std::endl;
 
-    curl_slist_free_all(headers);
     curl_easy_cleanup(curl);
-    curl_mime_free(mime);
   }
+  curl_global_cleanup();
+
   free(buffer);
 }
 
-
-void send_pdu_session_update_sm_context_establishment(std::string smf_ip_address)
-{
-  std::cout << "[AMF N11] PDU Session Establishment Request (SM Context Update)"<<std::endl;
+//------------------------------------------------------------------------------
+void send_pdu_session_update_sm_context_establishment(
+    std::string smf_ip_address) {
+  std::cout << "[AMF N11] PDU Session Establishment Request (SM Context Update)"
+            << std::endl;
 
   nlohmann::json pdu_session_update_request;
-
-  //encode
-  //PDU Session Resource Setup Response Transfer IE
+  //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 3c
    */
   size_t buffer_size = 128;
-  char *buffer = (char *)calloc(1,buffer_size);
-  int  size = 0;
-  ENCODE_U8 (buffer, 0x00 , size);
-  ENCODE_U8 (buffer+size, 0x03 , size);
-  ENCODE_U8 (buffer+size, 0xe0 , size);
-  ENCODE_U8 (buffer+size, 0xac , size); //uPTransportLayerInformation IP Addr 172.10.5.1: 172.
-  ENCODE_U8 (buffer+size, 0x0a , size); //10
-  ENCODE_U8 (buffer+size, 0x05 , size); //.5
-  ENCODE_U8 (buffer+size, 0x01 , size); //.1
-  ENCODE_U8 (buffer+size, 0x00 , size); //gTP_TEID 00 00 00 01: 00
-  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
-
-  std::cout << "Buffer: "<<std::endl;
-  for(int i=0;i<2;i++)
-  {
+  char *buffer = (char*) calloc(1, buffer_size);
+  int size = 0;
+  ENCODE_U8(buffer, 0x00, size);
+  ENCODE_U8(buffer + size, 0x03, size);
+  ENCODE_U8(buffer + size, 0xe0, size);
+  ENCODE_U8(buffer + size, 0xac, size);  //uPTransportLayerInformation IP Addr 172.10.5.1: 172.
+  ENCODE_U8(buffer + size, 0x0a, size);  //10
+  ENCODE_U8(buffer + size, 0x05, size);  //.5
+  ENCODE_U8(buffer + size, 0x01, size);  //.1
+  ENCODE_U8(buffer + size, 0x00, size);  //gTP_TEID 00 00 00 01: 00
+  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
+
+  std::cout << "Buffer: " << std::endl;
+  for (int i = 0; i < size; i++) {
     printf("%02x ", buffer[i]);
   }
-  std::cout << "Buffer: "<<std::endl;
+  std::cout << "Buffer: " << std::endl;
 
-  //Fill Json part
   std::string url = std::string("http://");
   url.append(smf_ip_address);
   url.append(std::string("/nsmf-pdusession/v2/sm-contexts/1/modify"));
 
   //Fill the json part
   pdu_session_update_request["n2SmInfoType"] = "PDU_RES_SETUP_RSP";
-  pdu_session_update_request["n2SmInfo"]["contentId"] = "n2SmMsg"; //NGAP
+  pdu_session_update_request["n2SmInfo"]["contentId"] = "n2SmMsg";  //NGAP
 
-  CURL *curl = curl_easy_init();
+  //pdu_session_update_request["n2InfoContainer"]["n2InformationClass"] = "SM";
+  //pdu_session_update_request["n2InfoContainer"]["smInfo"]["n2InfoContent"]["ngapData"]["contentId"] = "n2SmMsg";
+  // pdu_session_update_request["n2InfoContainer"]["smInfo"]["n2InfoContent"]["ngapIeType"] =
+  //   "PDU_RES_SETUP_RSP";  //NGAP message
 
+  std::string body;
+  std::string boundary = "----Boundary";
   std::string json_part = pdu_session_update_request.dump();
+  std::string n2_msg(reinterpret_cast<const char*>(buffer), size);
 
-  std::cout<< "Sending message to SMF....\n";
-  if(curl) {
+  create_multipart_related_content(body, json_part, boundary, n2_msg,
+                                   multipart_related_content_part_e::NGAP);
 
-    CURLcode res;
-    struct curl_slist *headers = nullptr;
-    struct curl_slist *slist = nullptr;
-    curl_mime *mime;
-    curl_mime *alt;
-    curl_mimepart *part;
+  unsigned char *data = (unsigned char*) malloc(body.length() + 1);
+  memset(data, 0, body.length() + 1);
+  memcpy((void*) data, (void*) body.c_str(), body.length());
+
+  curl_global_init(CURL_GLOBAL_ALL);
+  CURL *curl = curl = curl_easy_init();
 
-    headers = curl_slist_append(headers, "charsets: utf-8");
-    headers = curl_slist_append(headers, "content-type: multipart/related");
+  if (curl) {
+    CURLcode res = { };
+    struct curl_slist *headers = nullptr;
+    //headers = curl_slist_append(headers, "charsets: utf-8");
+    headers = curl_slist_append(
+        headers, "content-type: multipart/related; boundary=----Boundary");
     curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
     curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
-    curl_easy_setopt(curl, CURLOPT_HTTPGET,1);
+    curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
     curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 100L);
-    //curl_easy_setopt(curl, CURLOPT_INTERFACE, "eno1:amf"); //hardcoded
-
-
-    mime = curl_mime_init(curl);
-    alt = curl_mime_init(curl);
-
-    //part with N1N2MessageTransferReqData (JsonData)
-    part = curl_mime_addpart(mime);
-    curl_mime_data(part, json_part.c_str(), CURL_ZERO_TERMINATED);
-    curl_mime_type(part, "application/json");
-
-    part = curl_mime_addpart(mime);
-    curl_mime_data(part, reinterpret_cast<const char*>(buffer), size);
-
-    curl_mime_type(part, "application/vnd.3gpp.ngap");
-    curl_mime_name (part, "n2SmMsg");
-
-    curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
+    //curl_easy_setopt(curl, CURLOPT_INTERFACE, "eno1:amf");  //hardcoded
 
     // Response information.
-    long httpCode(0);
+    long httpCode = { 0 };
     std::unique_ptr<std::string> httpData(new std::string());
 
-    // Hook up data handling function.
     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &callback);
     curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get());
 
+    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body.length());
+    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
+
     res = curl_easy_perform(curl);
+
     curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
 
     //get cause from the response
     nlohmann::json response_data;
-    try{
+    try {
       response_data = nlohmann::json::parse(*httpData.get());
-    } catch (nlohmann::json::exception& e){
-      std::cout << "Could not get the cause from the response" <<std::endl;
+    } catch (nlohmann::json::exception &e) {
+      std::cout << "Could not get json data from the response" << std::endl;
       //Set the default Cause
       response_data["cause"] = "504 Gateway Timeout";
+
     }
-    std::cout << "[AMF N11] PDU Session Establishment Request, response from SMF, Http Code " << httpCode << " cause  "<<  response_data["cause"].dump().c_str()<<std::endl;
+    std::cout
+        << "[AMF N11] PDU Session Establishment Request, response from SMF, Http Code "
+        << httpCode << " cause  " << response_data["cause"].dump().c_str()
+        << std::endl;
 
-    curl_slist_free_all(headers);
     curl_easy_cleanup(curl);
-    curl_mime_free(mime);
   }
+  curl_global_cleanup();
+
   free(buffer);
 }
 
+//------------------------------------------------------------------------------
+void send_pdu_session_release_request(std::string smf_ip_address) {
 
-void send_pdu_session_release_request(std::string smf_ip_address)
-{
-  std::cout << "[AMF N11] PDU Session Release Request (SM Context Update)"<<std::endl;
+  std::cout << "[AMF N11] PDU Session Release Request (SM Context Update)"
+            << std::endl;
 
   nlohmann::json pdu_session_release_request;
-  //encode
+  //encode PDU Session Release Request
   /*
-    0000   2e 01 01 d1 00 00 00 00 00 00 00 00 00 00 00 00
+   0000   2e 01 01 d1 00 00 00 00 00 00 00 00 00 00 00 00
    */
   size_t buffer_size = 128;
-  char *buffer = (char *)calloc(1,buffer_size);
-  int  size = 0;
-  ENCODE_U8 (buffer, 0x2e , size); //ExtendedProtocolDiscriminator
-  ENCODE_U8 (buffer+size, 0x01 , size); //PDUSessionIdentity
-  ENCODE_U8 (buffer+size, 0x01 , size); //ProcedureTransactionIdentity
-  ENCODE_U8 (buffer+size, 0xd1 , size); //MessageType
-  ENCODE_U8 (buffer+size, 0x00 , size); //presence
-
-  std::cout << "Buffer: "<<std::endl;
-  for(int i=0;i<size;i++)
-  {
+  char *buffer = (char*) calloc(1, buffer_size);
+  int size = 0;
+  ENCODE_U8(buffer, 0x2e, size);  //ExtendedProtocolDiscriminator
+  ENCODE_U8(buffer + size, 0x01, size);  //PDUSessionIdentity
+  ENCODE_U8(buffer + size, 0x01, size);  //ProcedureTransactionIdentity
+  ENCODE_U8(buffer + size, 0xd1, size);  //MessageType
+  ENCODE_U8(buffer + size, 0x00, size);  //presence
+
+  std::cout << "Buffer: " << std::endl;
+  for (int i = 0; i < size; i++) {
     printf("%02x ", buffer[i]);
   }
-  std::cout << "Buffer: "<<std::endl;
+  std::cout << "Buffer: " << std::endl;
 
-  //Fill Json part
   std::string url = std::string("http://");
   url.append(smf_ip_address);
   url.append(std::string("/nsmf-pdusession/v2/sm-contexts/1/modify"));
 
   //Fill the json part
-  pdu_session_release_request["cause"] = "INSUFFICIENT_UP_RESOURCES"; //need to be updated
-  pdu_session_release_request["n1SmMsg"]["contentId"] = "n1SmMsg"; // NAS
-
-  CURL *curl = curl_easy_init();
+  pdu_session_release_request["cause"] = "INSUFFICIENT_UP_RESOURCES";  //need to be updated
+  pdu_session_release_request["n1SmMsg"]["contentId"] = "n1SmMsg";  // NAS
 
+  std::string body;
+  std::string boundary = "----Boundary";
   std::string json_part = pdu_session_release_request.dump();
+  std::string n1_msg(reinterpret_cast<const char*>(buffer), size);
 
-  std::cout<< "Sending message to SMF....\n";
-  if(curl) {
-    CURLcode res;
-    struct curl_slist *headers = nullptr;
-    struct curl_slist *slist = nullptr;
-    curl_mime *mime;
-    curl_mime *alt;
-    curl_mimepart *part;
+  create_multipart_related_content(body, json_part, boundary, n1_msg,
+                                   multipart_related_content_part_e::NAS);
 
+  unsigned char *data = (unsigned char*) malloc(body.length() + 1);
+  memset(data, 0, body.length() + 1);
+  memcpy((void*) data, (void*) body.c_str(), body.length());
+
+  curl_global_init(CURL_GLOBAL_ALL);
+  CURL *curl = curl = curl_easy_init();
+
+  if (curl) {
+    CURLcode res = { };
+    struct curl_slist *headers = nullptr;
     //headers = curl_slist_append(headers, "charsets: utf-8");
-    headers = curl_slist_append(headers, "content-type: multipart/related");
+    headers = curl_slist_append(
+        headers, "content-type: multipart/related; boundary=----Boundary");
     curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
     curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
-    curl_easy_setopt(curl, CURLOPT_HTTPGET,1);
+    curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
     curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 100L);
-    //curl_easy_setopt(curl, CURLOPT_INTERFACE, "eno1:amf"); //hardcoded
-
-    mime = curl_mime_init(curl);
-    alt = curl_mime_init(curl);
-
-    //part with N1N2MessageTransferReqData (JsonData)
-    part = curl_mime_addpart(mime);
-    curl_mime_data(part, json_part.c_str(), CURL_ZERO_TERMINATED);
-    curl_mime_type(part, "application/json");
-
-    part = curl_mime_addpart(mime);
-    //curl_mime_data(part, reinterpret_cast<const char*>(n1_msg_hex), CURL_ZERO_TERMINATED);
-    curl_mime_data(part, reinterpret_cast<const char*>(buffer), size);
-    curl_mime_type(part, "application/vnd.3gpp.5gnas");
-    //curl_mime_name (part, "n1SmMsg");
-
-    curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
+    //curl_easy_setopt(curl, CURLOPT_INTERFACE, "eno1:amf");  //hardcoded
 
     // Response information.
-    long httpCode(0);
+    long httpCode = { 0 };
     std::unique_ptr<std::string> httpData(new std::string());
 
-    // Hook up data handling function.
     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &callback);
     curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get());
 
+    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body.length());
+    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
+
     res = curl_easy_perform(curl);
+
     curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
 
     //get cause from the response
     nlohmann::json response_data;
-    try{
+    try {
       response_data = nlohmann::json::parse(*httpData.get());
-    } catch (nlohmann::json::exception& e){
-      std::cout << "Could not get the cause from the response" <<std::endl;
-
+    } catch (nlohmann::json::exception &e) {
+      std::cout << "Could not get json data from the response" << std::endl;
     }
-    std::cout << "[AMF N11] PDU Session Release Request, response from SMF, Http Code " << httpCode <<std::endl;
+    std::cout
+        << "[AMF N11] PDU Session Release Request, response from SMF, Http Code "
+        << httpCode << std::endl;
 
-    curl_slist_free_all(headers);
     curl_easy_cleanup(curl);
-    curl_mime_free(mime);
   }
+  curl_global_cleanup();
+
   free(buffer);
 }
 
-void send_pdu_session_release_resource_release_ack(std::string smf_ip_address)
-{
-  std::cout << "[AMF N11] PDU Session Release Ack (Update SM Context): N2 SM - Resource Release Ack"<<std::endl;
+//------------------------------------------------------------------------------
+void send_pdu_session_release_resource_release_ack(
+    std::string smf_ip_address) {
+
+  std::cout
+      << "[AMF N11] PDU Session Release Ack (Update SM Context): N2 SM - Resource Release Ack"
+      << std::endl;
 
   nlohmann::json pdu_session_release_ack;
-  //encode
+  //encode PDU Session Resource Release Response Transfer IE
   size_t buffer_size = 128;
-  char *buffer = (char *)calloc(1,buffer_size);
-  int  size = 0;
-  ENCODE_U8 (buffer, 0x00 , size);
-
+  char *buffer = (char*) calloc(1, buffer_size);
+  int size = 0;
+  ENCODE_U8(buffer, 0x00, size);
 
-  std::cout << "Buffer: "<<std::endl;
-  for(int i=0;i<size;i++)
-  {
+  std::cout << "Buffer: " << std::endl;
+  for (int i = 0; i < size; i++) {
     printf("%02x ", buffer[i]);
   }
-  std::cout << "Buffer: "<<std::endl;
+  std::cout << "Buffer: " << std::endl;
 
-  //Fill Json part
   std::string url = std::string("http://");
   url.append(smf_ip_address);
   url.append(std::string("/nsmf-pdusession/v2/sm-contexts/1/modify"));
 
-  //Fill the json part
-
   //Fill the json part
   pdu_session_release_ack["n2SmInfoType"] = "PDU_RES_REL_RSP";
-  pdu_session_release_ack["n2SmInfo"]["contentId"] = "n2SmMsg"; //NGAP
-
-  CURL *curl = curl_easy_init();
+  pdu_session_release_ack["n2SmInfo"]["contentId"] = "n2SmMsg";  //NGAP
 
+  std::string body;
+  std::string boundary = "----Boundary";
   std::string json_part = pdu_session_release_ack.dump();
+  std::string n2_msg(reinterpret_cast<const char*>(buffer), size);
 
-  std::cout<< "Sending message to SMF....\n";
-  if(curl) {
-    CURLcode res;
-    struct curl_slist *headers = nullptr;
-    struct curl_slist *slist = nullptr;
-    curl_mime *mime;
-    curl_mime *alt;
-    curl_mimepart *part;
+  create_multipart_related_content(body, json_part, boundary, n2_msg,
+                                   multipart_related_content_part_e::NGAP);
+
+  unsigned char *data = (unsigned char*) malloc(body.length() + 1);
+  memset(data, 0, body.length() + 1);
+  memcpy((void*) data, (void*) body.c_str(), body.length());
 
+  curl_global_init(CURL_GLOBAL_ALL);
+  CURL *curl = curl = curl_easy_init();
+
+  if (curl) {
+    CURLcode res = { };
+    struct curl_slist *headers = nullptr;
     //headers = curl_slist_append(headers, "charsets: utf-8");
-    headers = curl_slist_append(headers, "content-type: multipart/related");
+    headers = curl_slist_append(
+        headers, "content-type: multipart/related; boundary=----Boundary");
     curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
     curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
-    curl_easy_setopt(curl, CURLOPT_HTTPGET,1);
+    curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
     curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 100L);
-    //curl_easy_setopt(curl, CURLOPT_INTERFACE, "eno1:amf"); //hardcoded
-
-    mime = curl_mime_init(curl);
-    alt = curl_mime_init(curl);
-
-    //part with N1N2MessageTransferReqData (JsonData)
-    part = curl_mime_addpart(mime);
-    curl_mime_data(part, json_part.c_str(), CURL_ZERO_TERMINATED);
-    curl_mime_type(part, "application/json");
-
-    part = curl_mime_addpart(mime);
-    //curl_mime_data(part, reinterpret_cast<const char*>(n1_msg_hex), CURL_ZERO_TERMINATED);
-    curl_mime_data(part, reinterpret_cast<const char*>(buffer), size);
-    curl_mime_type(part, "application/vnd.3gpp.ngap");
-    curl_mime_name (part, "n2SmMsg");
-
-    curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
+    //curl_easy_setopt(curl, CURLOPT_INTERFACE, "eno1:amf");  //hardcoded
 
     // Response information.
-    long httpCode(0);
+    long httpCode = { 0 };
     std::unique_ptr<std::string> httpData(new std::string());
 
-    // Hook up data handling function.
     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &callback);
     curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get());
 
+    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body.length());
+    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
+
     res = curl_easy_perform(curl);
+
     curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
 
     //get cause from the response
     nlohmann::json response_data;
-    try{
+    try {
       response_data = nlohmann::json::parse(*httpData.get());
-    } catch (nlohmann::json::exception& e){
-      std::cout << "Could not get the cause from the response" <<std::endl;
+    } catch (nlohmann::json::exception &e) {
+      std::cout << "Could not get json data from the response" << std::endl;
 
     }
-    std::cout << "[AMF N11] PDU Session Release Ack, response from SMF, Http Code " << httpCode <<std::endl;
+    std::cout
+        << "[AMF N11] PDU Session Establishment Request, response from SMF, Http Code "
+        << httpCode << std::endl;
 
-    curl_slist_free_all(headers);
     curl_easy_cleanup(curl);
-    curl_mime_free(mime);
   }
+  curl_global_cleanup();
+
   free(buffer);
 }
 
+//------------------------------------------------------------------------------
+void send_pdu_session_release_complete(std::string smf_ip_address) {
 
-
-void send_pdu_session_release_complete(std::string smf_ip_address)
-{
-  std::cout << "[AMF N11] PDU Session Release Complete (Update SM Context): N1 SM - PDU Session Release Complete"<<std::endl;
+  std::cout
+      << "[AMF N11] PDU Session Release Complete (Update SM Context): N1 SM - PDU Session Release Complete"
+      << std::endl;
 
   nlohmann::json pdu_session_release_complete;
-  //encode
+  //encode PDU Session Release Complete
   /*
-    0000   2e 01 01 c1 d4 00 00 00 00 00 00 00 00 00 00 00
+   0000   2e 01 01 c1 d4 00 00 00 00 00 00 00 00 00 00 00
    */
   size_t buffer_size = 128;
-  char *buffer = (char *)calloc(1,buffer_size);
-  int  size = 0;
-  ENCODE_U8 (buffer, 0x2e , size); //ExtendedProtocolDiscriminator
-  ENCODE_U8 (buffer+size, 0x01 , size); //PDUSessionIdentity
-  ENCODE_U8 (buffer+size, 0x01 , size); //ProcedureTransactionIdentity
-  ENCODE_U8 (buffer+size, 0xd4 , size); //MessageType
-  ENCODE_U8 (buffer+size, 0x00 , size); //Cause
-  ENCODE_U8 (buffer+size, 0x00 , size); //Extended protocol configuration options
-
-
-  std::cout << "Buffer: "<<std::endl;
-  for(int i=0;i<size;i++)
-  {
+  char *buffer = (char*) calloc(1, buffer_size);
+  int size = 0;
+  ENCODE_U8(buffer, 0x2e, size);  //ExtendedProtocolDiscriminator
+  ENCODE_U8(buffer + size, 0x01, size);  //PDUSessionIdentity
+  ENCODE_U8(buffer + size, 0x01, size);  //ProcedureTransactionIdentity
+  ENCODE_U8(buffer + size, 0xd4, size);  //MessageType
+  ENCODE_U8(buffer + size, 0x00, size);  //Cause
+  ENCODE_U8(buffer + size, 0x00, size);  //Extended protocol configuration options
+
+  std::cout << "Buffer: " << std::endl;
+  for (int i = 0; i < size; i++) {
     printf("%02x ", buffer[i]);
   }
-  std::cout << "Buffer: "<<std::endl;
+  std::cout << "Buffer: " << std::endl;
 
-  //Fill Json part
   std::string url = std::string("http://");
   url.append(smf_ip_address);
   url.append(std::string("/nsmf-pdusession/v2/sm-contexts/1/modify"));
 
   //Fill the json part
-  pdu_session_release_complete["cause"] = "INSUFFICIENT_UP_RESOURCES"; //need to be updated
-  pdu_session_release_complete["n1SmMsg"]["contentId"] = "n1SmMsg"; // NAS
+  pdu_session_release_complete["cause"] = "INSUFFICIENT_UP_RESOURCES";  //need to be updated
+  pdu_session_release_complete["n1SmMsg"]["contentId"] = "n1SmMsg";  // NAS
 
-  //pdu_session_release_complete["n1MessageContainer"]["n1MessageClass"] = "SM";
-  //pdu_session_release_complete["n1MessageContainer"]["n1MessageContent"]["contentId"] = "n1SmMsg";
+  std::string body;
+  std::string boundary = "----Boundary";
+  std::string json_part = pdu_session_release_complete.dump();
+  std::string n1_msg(reinterpret_cast<const char*>(buffer), size);
 
+  create_multipart_related_content(body, json_part, boundary, n1_msg,
+                                   multipart_related_content_part_e::NAS);
 
-  CURL *curl = curl_easy_init();
+  unsigned char *data = (unsigned char*) malloc(body.length() + 1);
+  memset(data, 0, body.length() + 1);
+  memcpy((void*) data, (void*) body.c_str(), body.length());
 
-  std::string json_part = pdu_session_release_complete.dump();
+  curl_global_init(CURL_GLOBAL_ALL);
+  CURL *curl = curl = curl_easy_init();
 
-  std::cout<< "Sending message to SMF....\n";
-  if(curl) {
-    CURLcode res;
+  if (curl) {
+    CURLcode res = { };
     struct curl_slist *headers = nullptr;
-    struct curl_slist *slist = nullptr;
-    curl_mime *mime;
-    curl_mime *alt;
-    curl_mimepart *part;
-
     //headers = curl_slist_append(headers, "charsets: utf-8");
-    headers = curl_slist_append(headers, "content-type: multipart/related");
+    headers = curl_slist_append(
+        headers, "content-type: multipart/related; boundary=----Boundary");
     curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
     curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
-    curl_easy_setopt(curl, CURLOPT_HTTPGET,1);
+    curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
     curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 100L);
-    //curl_easy_setopt(curl, CURLOPT_INTERFACE, "eno1:amf"); //hardcoded
-
-    mime = curl_mime_init(curl);
-    alt = curl_mime_init(curl);
-
-    //part with N1N2MessageTransferReqData (JsonData)
-    part = curl_mime_addpart(mime);
-    curl_mime_data(part, json_part.c_str(), CURL_ZERO_TERMINATED);
-    curl_mime_type(part, "application/json");
-
-    part = curl_mime_addpart(mime);
-    //curl_mime_data(part, reinterpret_cast<const char*>(n1_msg_hex), CURL_ZERO_TERMINATED);
-    curl_mime_data(part, reinterpret_cast<const char*>(buffer), size);
-    curl_mime_type(part, "application/vnd.3gpp.5gnas");
-    curl_mime_name (part, "n1SmMsg");
-
-    curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
+    //curl_easy_setopt(curl, CURLOPT_INTERFACE, "eno1:amf");  //hardcoded
 
     // Response information.
-    long httpCode(0);
+    long httpCode = { 0 };
     std::unique_ptr<std::string> httpData(new std::string());
 
-    // Hook up data handling function.
     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &callback);
     curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get());
 
+    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body.length());
+    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
+
     res = curl_easy_perform(curl);
+
     curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
 
     //get cause from the response
     nlohmann::json response_data;
-    try{
+    try {
       response_data = nlohmann::json::parse(*httpData.get());
-    } catch (nlohmann::json::exception& e){
-      std::cout << "Could not get the cause from the response" <<std::endl;
-
+    } catch (nlohmann::json::exception &e) {
+      std::cout << "Could not get json data from the response" << std::endl;
     }
-    std::cout << "[AMF N11] PDU Session Release Complete, response from SMF, Http Code " << httpCode <<std::endl;
+    std::cout
+        << "[AMF N11] PDU Session Release Complete, response from SMF, Http Code "
+        << httpCode << std::endl;
 
-    curl_slist_free_all(headers);
     curl_easy_cleanup(curl);
-    curl_mime_free(mime);
   }
+  curl_global_cleanup();
+
   free(buffer);
 }
 
-
-
-int main(int argc, char* argv[])
-{
+//------------------------------------------------------------------------------
+int main(int argc, char *argv[]) {
   std::string smf_ip_address;
 
   if ((argc != 1) && (argc != 3)) {
-    std::cout << "Error: Usage is " <<std::endl;
-    std::cout << "  " << argv[0] << " [ -i www.xxx.yy.zz ]" <<std::endl;
+    std::cout << "Error: Usage is " << std::endl;
+    std::cout << "  " << argv[0] << " [ -i www.xxx.yy.zz ]" << std::endl;
     return -1;
   }
 
@@ -569,15 +675,15 @@ int main(int argc, char* argv[])
   } else {
     int opt = 0;
     while ((opt = getopt(argc, argv, "i:")) != -1) {
-      switch(opt) {
-      case 'i':
-        smf_ip_address.append(optarg);
-        break;
-      default:
-        std::cout << "Error: Usage is " <<std::endl;
-        std::cout << "  " << argv[0] << " [ -i www.xxx.yy.zz ]" <<std::endl;
-        return -1;
-        break;
+      switch (opt) {
+        case 'i':
+          smf_ip_address.append(optarg);
+          break;
+        default:
+          std::cout << "Error: Usage is " << std::endl;
+          std::cout << "  " << argv[0] << " [ -i www.xxx.yy.zz ]" << std::endl;
+          return -1;
+          break;
       }
     }
   }
diff --git a/src/test/inputs/apitest.json b/src/test/inputs/apitest.json
deleted file mode 100644
index 6eb49c51f530c78a521b34a89da93c75f123eb63..0000000000000000000000000000000000000000
--- a/src/test/inputs/apitest.json
+++ /dev/null
@@ -1,45 +0,0 @@
-{ 	
-"jsonData": {
-	"supi": "208931234561000",
-	"pei": "pei",
-	"gpsi": "gpsi", 
-	"pduSessionId": 5, 
-	"dnn": "default",
-	"sNssai": {"sst":1, "sd":123}, 
-	"hplmnSnssai": {"sst":1, "sd": 345}, 
-	"servingNfId": "", 
-	"guami": {"plmnId": {"mcc": "122", "mnc":"13"}, "amfId":"2"}, 
-	"serviceName": "", 
-	"servingNetwork": {"mcc": "122", "mnc":"13"},  
-	"requestType": 1, 
-	"anType": "", 
-	"secondAnType": "",
-	"ratType": "",
-	"presenceInLadn": "",
-	"ueTimeZone": "",
-	"smContextStatusUri": "",
-	"hSmfUri": "",
-	"additionalHsmfUri": [],
-	"oldPduSessionId": 1,
-	"pduSessionsActivateList": [1,2],
-	"ueEpsPdnConnection": "",
-	"hoState": "",
-	"pcfId": "",
-	"nrfUi": "",
-	"supportedFeatures": "",
-	"selMode": "VERIFIED",
-	"udmGroupId": "",
-	"routingIndicator": "",
-	"epsBearerCtxStatus": "",
-	"cpCiotEnabled": true,
-	"invokeNef": true,
-	"maPduIndication": false,
-	"smContextRef": "",
-	"n2SmInfo": {"contentId":"n2SmInfo"},
-	"n1SmMsg": {"contentId":"n1SmMsg"}
- }, 
-        "binaryDataN1SmMessage":"2e031fc100ff93a2390f616263646566406768696a6b2e6c6d",
-	"binaryDataN1SmMessage_full":"00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 02 00 55 00 01 40 00 40 84 3c 25 7f 00 00 01 7f 00 00 01 df b0 96 0c ea 4c f5 4b 00 00 00 00 00 03 00 35 20 bc ec 86 00 00 00 00 00 00 00 00 00 0f 40 21 00 00 01 00 26 00 1a 19 2e 03 1f c1 00 ff 93 a2 39 0f 61 62 63 64 65 66 40 67 68 69 6a 6b 2e 6c 6d"
-}
-
-
diff --git a/src/test/inputs/apitest_full.json b/src/test/inputs/apitest_full.json
deleted file mode 100644
index 8dfc2f38925dc816c2840bfe5199313994aed456..0000000000000000000000000000000000000000
--- a/src/test/inputs/apitest_full.json
+++ /dev/null
@@ -1,52 +0,0 @@
-{ 	
-"jsonData": {
-	"supi": "supi",
-	"pei": "pei",
-	"gpsi": "gpsi", 
-	"pduSessionId": 1, 
-	"dnn": "dnn",
-	"sNssai": {"sst":1, "sd":"sd"}, 
-	"hplmnSnssai": {"sst":1, "sd":"sd"}, 
-	"servingNfId": "", 
-	"guami": {"plmnId": {"mcc": "122", "mnc":"13"}, "amfId":"2"}, 
-	"serviceName": "", 
-	"servingNetwork": {"mcc": "122", "mnc":"13"},  
-	"requestType": "", 
-	"anType": "", 
-	"secondAnType": "",
-	"ratType": "",
-	"presenceInLadn": "",
-	"ueLocation": "",
-	"ueTimeZone": "",
-	"addUeLocation": "",
-	"smContextStatusUri": "",
-	"hSmfUri": "",
-	"additionalHsmfUri": [],
-	"oldPduSessionId": "",
-	"pduSessionsActivateList": [1,2],
-	"ueEpsPdnConnection": "",
-	"hoState": "",
-	"pcfId": "",
-	"nrfUi": "",
-	"supportedFeatures": "",
-	"selMode": "",
-	"backupAmfInfo": [],
-	"traceData": "",
-	"udmGroupId": "",
-	"routingIndicator": "",
-	"epsInterworkingInd": "",
-	"indirectForwardingFlag": "",
-	"targetId": "",
-	"epsBearerCtxStatus": "",
-	"cpCiotEnabled": "",
-	"invokeNef": "",
-	"maPduIndication": "",
-	"smContextRef": "",
-	"n2SmInfo": "",
-	"n1SmMsg": {"contentId":"contentId"}
- }, 
-	"binaryDataN1SmMessage":"binaryDataN1SmMessage",
- 	"binaryDataN2SmInformation": "binaryDataN2SmInformation"
-}
-
-
diff --git a/src/test/inputs/pdu_session_create_request.hex b/src/test/inputs/pdu_session_create_request.hex
deleted file mode 100644
index 5b6c8a0b8af66698e0b6f1173ba3bbc4ca30bfea..0000000000000000000000000000000000000000
--- a/src/test/inputs/pdu_session_create_request.hex
+++ /dev/null
@@ -1,13 +0,0 @@
-00000 00 00 00 00 00 00 00 00
-00008 00 00 00 00 08 00 45 02
-00010 00 55 00 01 40 00 40 84
-00018 3c 25 7f 00 00 01 7f 00
-00020 00 01 df b0 96 0c ea 4c
-00028 f5 4b 00 00 00 00 00 03
-00030 00 35 20 bc ec 86 00 00
-00038 00 00 00 00 00 00 00 0f
-00040 40 21 00 00 01 00 26 00
-00048 1a 19 2e 03 1f c1 00 ff
-00050 93 a2 39 0f 61 62 63 64
-00058 65 66 40 67 68 69 6a 6b
-00060 2e 6c 6d
diff --git a/src/test/inputs/session_management_subscription.json b/src/test/inputs/session_management_subscription.json
deleted file mode 100644
index 82a2c783d89b67d6aec86b28dde2ad039cb58124..0000000000000000000000000000000000000000
--- a/src/test/inputs/session_management_subscription.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-   "singleNssai": {"sst":1, "sd":123}, 
-   "dnnConfigurations": {
-      "default":  {
-         "pduSessionTypes": {"defaultSessionType": "IPV4"} ,
-         "sscModes": {"defaultSscMode": "SSC_MODE_1"} ,
-         "5gQosProfile":  {"5qi": 12345, "arp": {"priorityLevel": 1 , "preemptCap": "NOT_PREEMPT" , "preemptVuln": "NOT_PREEMPTABLE"} },
-         "sessionAmbr": {"uplink": "10Mbps", "downlink":"11Mbps"}
-      }
-   }
-}
diff --git a/src/test/udm/impl/SessionManagementSubscriptionDataRetrievalApiImpl.cpp b/src/test/udm/impl/SessionManagementSubscriptionDataRetrievalApiImpl.cpp
index 309899aa84108d72d1b7df255bf2f8d290c39abb..894e7865f70379fd1082e9d6bc7864277dde6e59 100644
--- a/src/test/udm/impl/SessionManagementSubscriptionDataRetrievalApiImpl.cpp
+++ b/src/test/udm/impl/SessionManagementSubscriptionDataRetrievalApiImpl.cpp
@@ -44,14 +44,23 @@ void SessionManagementSubscriptionDataRetrievalApiImpl::get_sm_data(const std::s
 	nlohmann::json jsonData;
 	jsonData["singleNssai"]["sst"] = 222;
 	jsonData["singleNssai"]["sd"] = 123;
-	jsonData["dnnConfigurations"]["carrier.com"]["pduSessionTypes"]["defaultSessionType"] = "IPV4";
-	jsonData["dnnConfigurations"]["carrier.com"]["sscModes"]["defaultSscMode"] = "SSC_MODE_1";
-	jsonData["dnnConfigurations"]["carrier.com"]["5gQosProfile"]["5qi"] = 60;
-	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";
-	jsonData["dnnConfigurations"]["carrier.com"]["sessionAmbr"]["uplink"] = "10Mbps";
-	jsonData["dnnConfigurations"]["carrier.com"]["sessionAmbr"]["downlink"] = "11Mbps";
+	jsonData["dnnConfigurations"]["default"]["pduSessionTypes"]["defaultSessionType"] = "IPV4";
+	jsonData["dnnConfigurations"]["default"]["sscModes"]["defaultSscMode"] = "SSC_MODE_1";
+	jsonData["dnnConfigurations"]["default"]["5gQosProfile"]["5qi"] = 60;
+	jsonData["dnnConfigurations"]["default"]["5gQosProfile"]["arp"]["priorityLevel"] = 1;
+	jsonData["dnnConfigurations"]["default"]["5gQosProfile"]["arp"]["preemptCap"] = "NOT_PREEMPT";
+	jsonData["dnnConfigurations"]["default"]["5gQosProfile"]["arp"]["preemptVuln"] = "NOT_PREEMPTABLE";
+	jsonData["dnnConfigurations"]["default"]["sessionAmbr"]["uplink"] = "20Mbps";
+	jsonData["dnnConfigurations"]["default"]["sessionAmbr"]["downlink"] = "22Mbps";
+
+  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"]["arp"]["priorityLevel"] = 1;
+  jsonData["dnnConfigurations"]["carrier.com"]["5gQosProfile"]["arp"]["preemptCap"] = "NOT_PREEMPT";
+  jsonData["dnnConfigurations"]["carrier.com"]["5gQosProfile"]["arp"]["preemptVuln"] = "NOT_PREEMPTABLE";
+  jsonData["dnnConfigurations"]["carrier.com"]["sessionAmbr"]["uplink"] = "10Mbps";
+  jsonData["dnnConfigurations"]["carrier.com"]["sessionAmbr"]["downlink"] = "11Mbps";
 
 /*
 	SessionManagementSubscriptionData subscriptionData;
diff --git a/src/test/udm/udm-api-server.cpp b/src/test/udm/udm-api-server.cpp
index 844e65f1c0fdb3adc5a8ebfae32a4ea8b273fdbd..7700bf4956f689cf17d05db43685b850dad388ac 100644
--- a/src/test/udm/udm-api-server.cpp
+++ b/src/test/udm/udm-api-server.cpp
@@ -117,7 +117,6 @@ int main(int argc, char* argv[]) {
     opts.flags(Pistache::Tcp::Options::ReuseAddr);
     opts.maxPayload(PISTACHE_SERVER_MAX_PAYLOAD);
     httpEndpoint->init(opts);
-
     
     AccessAndMobilitySubscriptionDataRetrievalApiImpl AccessAndMobilitySubscriptionDataRetrievalApiserver(router);
     AccessAndMobilitySubscriptionDataRetrievalApiserver.init();
@@ -160,9 +159,12 @@ int main(int argc, char* argv[]) {
     UEContextInSMSFDataRetrievalApiImpl UEContextInSMSFDataRetrievalApiserver(router);
     UEContextInSMSFDataRetrievalApiserver.init();
 
+    std::cout  << "UDM is listening on address: " << udm_ip_address.c_str() << std::endl;
+
     httpEndpoint->setHandler(router->handler());
     httpEndpoint->serve();
 
+
     httpEndpoint->shutdown();
 
 }