MME2 changes - Propped commits from openmme/paging branch. Added scripts
for code gen

Change-Id: Ie55032217232214ac8544ca76ea34335205329e4
diff --git a/src/mme-app/actionHandlers/attachActionHandlers.cpp b/src/mme-app/actionHandlers/attachActionHandlers.cpp
new file mode 100644
index 0000000..78b8761
--- /dev/null
+++ b/src/mme-app/actionHandlers/attachActionHandlers.cpp
@@ -0,0 +1,980 @@
+/*
+ * Copyright 2019-present Infosys Limited
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/******************************************************************************
+ *
+ * This file has both generated and manual code.
+ *
+ * File template used for code generation:
+ * <TOP-DIR/scripts/SMCodeGen/templates/stateMachineTmpls/actionHandlers.cpp.tt>
+ *
+ ******************************************************************************/
+
+#include <3gpp_24008.h>
+#include <typeinfo>
+#include "actionHandlers/actionHandlers.h"
+#include "controlBlock.h"
+#include "msgType.h"
+#include "contextManager/subsDataGroupManager.h"
+#include "contextManager/dataBlocks.h"
+#include "procedureStats.h"
+#include "log.h"
+#include "secUtils.h"
+#include "state.h"
+#include <string.h>
+#include <sstream>
+#include <smTypes.h>
+#include <cstring>
+#include <event.h>
+#include <ipcTypes.h>
+#include <tipcTypes.h>
+#include <msgBuffer.h>
+#include <interfaces/mmeIpcInterface.h>
+#include <utils/mmeCommonUtils.h>
+#include <utils/mmeContextManagerUtils.h>
+
+using namespace SM;
+using namespace mme;
+using namespace cmn::utils;
+
+extern MmeIpcInterface* mmeIpcIf_g;
+
+ActStatus ActionHandlers::validate_imsi_in_ue_context(ControlBlock& cb)
+{
+    UEContext* ueCtxt_p = static_cast<UEContext*>(cb.getPermDataBlock());
+    if (ueCtxt_p == NULL)
+    {
+         log_msg(LOG_DEBUG, "send_identity_request_to_ue: ue context is NULL \n");
+         return ActStatus::HALT;
+    }
+
+    if (ueCtxt_p->getImsi().isValid())
+    {
+        SM::Event evt(Event_e::IMSI_VALIDATION_SUCCESS, NULL);
+        cb.addEventToProcQ(evt);
+    }
+    else
+    {
+        // TODO: If known GUTI, IMSI_VALIDATION_FAILURE_KNOWN_GUTI to trigger id req to UE
+        // If unknown GUTI, IMSI_VALIDATION_FAILURE_UNKNOWN_GUTI to query old mme
+        // when s10 is supported in MME
+        SM::Event evt(Event_e::IMSI_VALIDATION_FAILURE, NULL);
+        cb.addEventToProcQ(evt);
+    }
+    return ActStatus::PROCEED;
+}
+
+ActStatus ActionHandlers::send_identity_request_to_ue(ControlBlock& cb)
+{
+	log_msg(LOG_DEBUG, "Inside send_identity_request_to_ue \n");
+
+	UEContext* ueCtxt_p = static_cast<UEContext*>(cb.getPermDataBlock());
+	if (ueCtxt_p == NULL)
+	{
+		log_msg(LOG_DEBUG, "send_identity_request_to_ue: ue context is NULL \n");
+		return ActStatus::HALT;
+	}
+
+	struct attachIdReq_info idReqMsg;
+	idReqMsg.msg_type = id_request;
+	idReqMsg.enb_fd = ueCtxt_p->getEnbFd();
+	idReqMsg.s1ap_enb_ue_id = ueCtxt_p->getS1apEnbUeId();
+	idReqMsg.ue_idx = ueCtxt_p->getContextID();
+	idReqMsg.ue_type = ID_IMSI;
+
+	cmn::ipc::IpcAddress destAddr;
+	destAddr.u32 = TipcServiceInstance::s1apAppInstanceNum_c;
+
+	mmeIpcIf_g->dispatchIpcMsg((char *) &idReqMsg, sizeof(idReqMsg), destAddr);
+
+    return ActStatus::PROCEED;
+}
+
+ActStatus ActionHandlers::process_identity_response(ControlBlock& cb)
+{
+	log_msg(LOG_DEBUG, "Inside process_identity_response \n");
+
+	UEContext *ueCtxt_p = static_cast<UEContext*>(cb.getPermDataBlock());
+	if (ueCtxt_p == NULL)
+	{
+		log_msg(LOG_DEBUG, "process_identity_response: ue context is NULL \n");
+		return ActStatus::HALT;
+	}
+
+	MsgBuffer* msgBuf = static_cast<MsgBuffer*>(cb.getMsgData());
+	if (msgBuf == NULL)
+	{
+		log_msg(LOG_DEBUG, "process_identity_response: msgBuf is NULL \n");
+		return ActStatus::HALT;
+	}
+
+	const s1_incoming_msg_data_t* s1_msg_data = static_cast<const s1_incoming_msg_data_t*>(msgBuf->getDataPointer());
+	if (s1_msg_data == NULL)
+	{
+		log_msg(LOG_DEBUG, "process_identity_response: s1MsgData is NULL \n");
+		return ActStatus::HALT;
+	}
+
+	const struct identityResp_Q_msg &id_resp = s1_msg_data->msg_data.identityResp_Q_msg_m;
+	if(SUCCESS != id_resp.status)
+    	{
+		log_msg(LOG_DEBUG, "process_identity_response: ID Response Failure NULL \n");
+		return ActStatus::HALT;
+	}
+
+	uint8_t imsi[BINARY_IMSI_LEN] = {0};
+    	memcpy( imsi, id_resp.IMSI, BINARY_IMSI_LEN );
+
+	// Only upper nibble of first octect in imsi need to be considered
+	// Changing the lower nibble to 0x0f for handling
+	uint8_t first = imsi[0] >> 4;
+	imsi[0] = (uint8_t)(( first << 4 ) | 0x0f );
+
+	DigitRegister15 IMSIInfo;
+	IMSIInfo.convertFromBcdArray(imsi);
+	ueCtxt_p->setImsi(IMSIInfo);
+
+	SubsDataGroupManager::Instance()->addimsikey(ueCtxt_p->getImsi(), ueCtxt_p->getContextID());
+
+    return ActStatus::PROCEED;
+}
+
+
+ActStatus ActionHandlers::send_air_to_hss(SM::ControlBlock& cb)
+{  
+	log_msg(LOG_DEBUG, "Inside send_air_to_hss \n");
+	
+	UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+	if (ue_ctxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "send_air_to_hss: ue context is NULL \n");
+		return ActStatus::HALT;
+	}
+
+	s6a_Q_msg s6a_req;
+	
+	memset(s6a_req.imsi, '\0', sizeof(s6a_req.imsi));
+	ue_ctxt->getImsi().getImsiDigits(s6a_req.imsi);
+
+	memcpy(&(s6a_req.tai), &(ue_ctxt->getTai().tai_m), sizeof(struct TAI));
+
+	s6a_req.ue_idx = ue_ctxt->getContextID();
+	s6a_req.msg_type = auth_info_request;
+
+	cmn::ipc::IpcAddress destAddr;
+	destAddr.u32 = TipcServiceInstance::s6AppInstanceNum_c;
+
+	mmeIpcIf_g->dispatchIpcMsg((char *) &s6a_req, sizeof(s6a_req), destAddr);
+
+	ProcedureStats::num_of_air_sent ++;
+	log_msg(LOG_DEBUG, "Leaving send_air_to_hss \n");
+	
+	return ActStatus::PROCEED;
+
+}
+
+ActStatus ActionHandlers::send_ulr_to_hss(SM::ControlBlock& cb)
+{  
+	log_msg(LOG_DEBUG, "Inside send_ulr_to_hss \n");
+	
+	UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+	if (ue_ctxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "send_ulr_to_hss: ue context is NULL \n");
+		return ActStatus::HALT;
+	}
+
+	s6a_Q_msg s6a_req;
+
+	memset(s6a_req.imsi, '\0', sizeof(s6a_req.imsi));
+	ue_ctxt->getImsi().getImsiDigits(s6a_req.imsi);
+
+	memcpy(&(s6a_req.tai), &(ue_ctxt->getTai().tai_m), sizeof(struct TAI));
+
+	s6a_req.ue_idx = ue_ctxt->getContextID();
+	s6a_req.msg_type = update_loc_request;
+
+	cmn::ipc::IpcAddress destAddr;
+	destAddr.u32 = TipcServiceInstance::s6AppInstanceNum_c;
+
+	mmeIpcIf_g->dispatchIpcMsg((char *) &s6a_req, sizeof(s6a_req), destAddr);
+
+	ProcedureStats::num_of_ulr_sent ++;
+	log_msg(LOG_DEBUG, "Leaving send_ulr_to_hss \n");
+	
+	return ActStatus::PROCEED;
+}
+
+
+ActStatus ActionHandlers::process_aia(SM::ControlBlock& cb)
+{
+	log_msg(LOG_DEBUG, "Inside handle_aia \n");
+
+	UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+	if (ue_ctxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "handle_aia: ue context is NULL \n");
+		return ActStatus::HALT;
+	}
+
+	MsgBuffer* msgBuf = static_cast<MsgBuffer*>(cb.getMsgData());
+
+	if (msgBuf == NULL)
+		return ActStatus::HALT;
+
+	const s6_incoming_msg_data_t* msgData_p = static_cast<const s6_incoming_msg_data_t*>(msgBuf->getDataPointer());
+
+	ue_ctxt->setAiaSecInfo(E_utran_sec_vector(msgData_p->msg_data.aia_Q_msg_m.sec));
+	
+	ProcedureStats::num_of_processed_aia ++;
+	log_msg(LOG_DEBUG, "Leaving handle_aia \n");
+	
+	return ActStatus::PROCEED;
+}
+
+ActStatus ActionHandlers::process_ula(SM::ControlBlock& cb)
+{
+	log_msg(LOG_DEBUG, "Inside handle_ula \n");
+
+	UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+	if (ue_ctxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "handle_ula: ue context is NULL \n");
+		return ActStatus::HALT;
+	}
+
+	SessionContext* sessionCtxt = ue_ctxt->getSessionContext();
+	if( sessionCtxt == NULL )
+    	{
+		log_msg(LOG_ERROR, "Failed to retrieve Session Context for UE IDX %d\n", cb.getCBIndex());
+        	return ActStatus::HALT;
+    	}
+	
+	MsgBuffer* msgBuf = static_cast<MsgBuffer*>(cb.getMsgData());
+
+	if (msgBuf == NULL)
+		return ActStatus::HALT;
+
+	const s6_incoming_msg_data_t* s6_msg_data = static_cast<const s6_incoming_msg_data_t*>(msgBuf->getDataPointer());
+	const struct ula_Q_msg &ula_msg = s6_msg_data->msg_data.ula_Q_msg_m;
+
+	sessionCtxt->setApnConfigProfileCtxId(ula_msg.apn_config_profile_ctx_id);
+	DigitRegister15 ueMSISDN;
+	ueMSISDN.convertFromBcdArray( reinterpret_cast<const uint8_t*>( ula_msg.MSISDN ));
+	ue_ctxt->setMsisdn(ueMSISDN);
+	ue_ctxt->setRauTauTimer(ula_msg.RAU_TAU_timer);
+	ue_ctxt->setSubscriptionStatus(ula_msg.subscription_status);
+	ue_ctxt->setNetAccessMode(ula_msg.net_access_mode);
+	ue_ctxt->setAccessRestrictionData(ula_msg.access_restriction_data);
+
+	struct AMBR ambr;
+	ambr.max_requested_bw_dl = ula_msg.max_requested_bw_dl;
+	ambr.max_requested_bw_ul = ula_msg.max_requested_bw_ul;
+	
+	ue_ctxt->setAmbr(Ambr(ambr));
+	
+	ProcedureStats::num_of_processed_ula ++;
+	log_msg(LOG_DEBUG, "Leaving handle_ula_v \n");
+	
+	return ActStatus::PROCEED;
+}
+
+ActStatus ActionHandlers::auth_req_to_ue(SM::ControlBlock& cb)
+{
+	UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+
+	if (ue_ctxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "auth_req_to_ue: ue context is NULL \n");
+		return ActStatus::HALT;
+	}
+
+	authreq_info authreq;
+	authreq.msg_type = auth_request;
+	authreq.ue_idx = ue_ctxt->getContextID();
+	authreq.enb_fd = ue_ctxt->getEnbFd();
+	authreq.enb_s1ap_ue_id = ue_ctxt->getS1apEnbUeId();
+
+	ue_ctxt->setDwnLnkSeqNo(0);
+
+	E_UTRAN_sec_vector *secVect = const_cast<E_UTRAN_sec_vector*>(ue_ctxt->getAiaSecInfo().AiaSecInfo_mp);
+
+	secinfo& secInfo = const_cast<secinfo&>(ue_ctxt->getUeSecInfo().secinfo_m);
+
+	SecUtils::create_integrity_key(secVect->kasme.val, secInfo.int_key);
+
+	memcpy(&(authreq.rand), &(secVect->rand.val), NAS_RAND_SIZE);
+	memcpy(&(authreq.autn), &(secVect->autn.val), NAS_AUTN_SIZE);
+	
+	cmn::ipc::IpcAddress destAddr;
+	destAddr.u32 = TipcServiceInstance::s1apAppInstanceNum_c;
+
+	mmeIpcIf_g->dispatchIpcMsg((char *) &authreq, sizeof(authreq), destAddr);
+
+	
+	ProcedureStats::num_of_auth_req_to_ue_sent ++;
+	log_msg(LOG_DEBUG, "Leaving auth_req_to_ue_v \n");
+		
+	return ActStatus::PROCEED;
+}
+
+ActStatus ActionHandlers::auth_response_validate(SM::ControlBlock& cb)
+{
+	log_msg(LOG_DEBUG, "Inside auth_response_validate \n");
+	SM::ControlBlock* controlBlk_p = SubsDataGroupManager::Instance()->findControlBlock(cb.getCBIndex());
+
+	UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+	if (ue_ctxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "auth_response_validate: ue context or procedure ctxt is NULL \n");
+		return ActStatus::HALT;
+	}
+	
+	MsgBuffer* msgBuf = static_cast<MsgBuffer*>(cb.getMsgData());
+
+	if (msgBuf == NULL)
+		return ActStatus::HALT;
+
+	const s1_incoming_msg_data_t* s1_msg_data = static_cast<const s1_incoming_msg_data_t*>(msgBuf->getDataPointer());	
+	const struct authresp_Q_msg &auth_resp = s1_msg_data->msg_data.authresp_Q_msg_m;
+	
+	/*Check the state*/
+	if(SUCCESS != auth_resp.status) {
+		log_msg(LOG_ERROR, "eNB authentication failure for UE-%d.\n", ue_ctxt->getContextID());
+		if(auth_resp.auts.len == 0)
+		{
+			log_msg(LOG_ERROR,"No AUTS.Not Synch Failure\n");
+			SM::Event evt(Event_e::AUTH_RESP_FAILURE,NULL);
+        		controlBlk_p->addEventToProcQ(evt);
+		}
+		else
+		{
+			log_msg(LOG_INFO,"AUTS recvd.  Synch failure. send AIR\n");
+			SM::Event evt(Event_e::AUTH_RESP_SYNC_FAILURE,NULL);
+            		controlBlk_p->addEventToProcQ(evt);
+		}
+	}
+	else{
+		log_msg(LOG_INFO,"Auth response validation success. Proceeding to Sec mode Command\n");
+                SM::Event evt(Event_e::AUTH_RESP_SUCCESS,NULL);
+                controlBlk_p->addEventToProcQ(evt);
+
+	}
+	//TODO: XRES comparison
+	#if 0
+	log_msg(LOG_ERROR, "stage 3 processing memcmp - %d, %d, %d", &(ue_ctxt->getaiaSecInfo().AiaSecInfo_mp->xres.val),
+                &(auth_resp->res.val),
+                auth_resp->res.len);
+	if(memcmp(&(ue_ctxt->getaiaSecInfo().AiaSecInfo_mp->xres.val),
+		&(auth_resp->res.val),
+		auth_resp->res.len) != 0) {
+		log_msg(LOG_ERROR, "Invalid auth result received for UE %d",
+			auth_resp->ue_idx);
+		return E_FAIL;//report failure
+	}
+	#endif
+	
+	ProcedureStats::num_of_processed_auth_response ++;
+	log_msg(LOG_DEBUG, "Leaving auth_response_validate \n");
+	
+	return ActStatus::PROCEED;
+}
+
+ActStatus ActionHandlers::send_auth_reject(SM::ControlBlock& cb)
+{
+	log_msg(LOG_DEBUG, "Inside send_auth_reject \n");
+
+	UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+	if (ue_ctxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "send_auth_reject: ue context is NULL \n");
+		return ActStatus::HALT;
+	}
+	return ActStatus::HALT;
+}
+	
+
+ActStatus ActionHandlers::sec_mode_cmd_to_ue(SM::ControlBlock& cb)
+{
+	log_msg(LOG_DEBUG, "Inside sec_mode_cmd_to_ue \n");
+
+	UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+	if (ue_ctxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "sec_mode_cmd_to_ue: ue context is NULL \n");
+		return ActStatus::HALT;
+	}
+	sec_mode_Q_msg sec_mode_msg;
+	sec_mode_msg.msg_type  = sec_mode_command;
+	sec_mode_msg.ue_idx = ue_ctxt->getContextID();
+	sec_mode_msg.enb_fd = ue_ctxt->getEnbFd();
+	sec_mode_msg.enb_s1ap_ue_id = ue_ctxt->getS1apEnbUeId();
+	
+	memcpy(&(sec_mode_msg.ue_network), &(ue_ctxt->getUeNetCapab().ue_net_capab_m),
+		sizeof(struct UE_net_capab));
+
+	memcpy(&(sec_mode_msg.ms_net_capab), &(ue_ctxt->getMsNetCapab().ms_net_capab_m),
+                sizeof(struct MS_net_capab));
+
+	memcpy(&(sec_mode_msg.key), &(ue_ctxt->getAiaSecInfo().AiaSecInfo_mp->kasme),
+			sizeof(struct KASME));
+
+	memcpy(&(sec_mode_msg.int_key), &(ue_ctxt->getUeSecInfo().secinfo_m.int_key),
+			NAS_INT_KEY_SIZE);
+
+	sec_mode_msg.dl_seq_no = ue_ctxt->getDwnLnkSeqNo();
+	ue_ctxt->setDwnLnkSeqNo(sec_mode_msg.dl_seq_no + 1);
+
+	cmn::ipc::IpcAddress destAddr;
+	destAddr.u32 = TipcServiceInstance::s1apAppInstanceNum_c;
+
+	mmeIpcIf_g->dispatchIpcMsg((char *) &sec_mode_msg, sizeof(sec_mode_msg), destAddr);
+	
+	ProcedureStats::num_of_sec_mode_cmd_to_ue_sent ++;
+	log_msg(LOG_DEBUG, "Leaving sec_mode_cmd_to_ue \n");
+	
+	return ActStatus::PROCEED;
+}
+
+
+ActStatus ActionHandlers::process_sec_mode_resp(SM::ControlBlock& cb)
+{
+	log_msg(LOG_DEBUG, "Inside handle_sec_mode_resp \n");
+
+	UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+	if (ue_ctxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "handle_sec_mode_resp: ue context is NULL \n");
+		return ActStatus::HALT;
+	}
+
+	MsgBuffer* msgBuf = static_cast<MsgBuffer*>(cb.getMsgData());
+
+	if (msgBuf == NULL)
+		return ActStatus::HALT;
+
+	const s1_incoming_msg_data_t* s1_msg_data = static_cast<const s1_incoming_msg_data_t*>(msgBuf->getDataPointer());
+	const secmode_resp_Q_msg &secmode_resp = s1_msg_data->msg_data.secmode_resp_Q_msg_m;
+	if(SUCCESS == secmode_resp.status)
+	{
+		log_msg(LOG_INFO, "Sec mode complete rcv. UE - %d.\n",
+				ue_ctxt->getContextID());
+		
+	}	
+	else
+	{
+		log_msg(LOG_INFO, "Sec mode failed. UE %d", ue_ctxt->getContextID());
+	}
+
+	ProcedureStats::num_of_processed_sec_mode_resp ++;
+	log_msg(LOG_DEBUG, "Leaving handle_sec_mode_resp \n");
+	
+	return ActStatus::PROCEED;
+}
+
+ActStatus ActionHandlers::check_esm_info_req_required(SM::ControlBlock& cb)
+{
+	log_msg(LOG_DEBUG, "Inside check_esm_info_req_required \n");
+
+	UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+	if (ue_ctxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "check_esm_info_req_required: ue context is NULL \n");
+		return ActStatus::HALT;
+	}
+	
+	MmeProcedureCtxt* procedure_p = dynamic_cast<MmeProcedureCtxt*>(cb.getTempDataBlock());
+	if (procedure_p == NULL)
+	{
+		log_msg(LOG_DEBUG, "check_esm_info_req_required: procedure context is NULL \n");
+		return ActStatus::HALT;		
+	}
+	SessionContext* sessionCtxt = SubsDataGroupManager::Instance()->getSessionContext();
+	if( sessionCtxt == NULL )
+	{
+	    log_msg(LOG_ERROR, "Failed to allocate Session Context for UE IDX %d\n", cb.getCBIndex());
+
+	    return ActStatus::HALT;
+	}
+	BearerContext* bearerCtxt_p = SubsDataGroupManager::Instance()->getBearerContext();
+	if( bearerCtxt_p == NULL )
+	{
+	    log_msg(LOG_ERROR, "Failed to allocate Bearer context for UE IDx %d\n", cb.getCBIndex());
+
+	    return ActStatus::HALT;
+	}
+
+	bearerCtxt_p->setBearerId(5);
+	sessionCtxt->setPti(procedure_p->getPti());
+	sessionCtxt->setBearerContext( bearerCtxt_p );
+	ue_ctxt->setSessionContext(sessionCtxt);
+	
+	if (procedure_p->getEsmInfoTxRequired() == false)
+	{
+		// hardcoding APN, if ESM info request is not to be sent
+		std::string apnName = "apn1";
+		struct apn_name apn = {0};
+		apn.len = apnName.length() + 1;
+		apn.val[0] = apnName.length();
+		memcpy(&(apn.val[1]), apnName.c_str(), apnName.length());
+
+		sessionCtxt->setAccessPtName(Apn_name(apn));
+        
+		SM::Event evt(Event_e::ESM_INFO_NOT_REQUIRED, NULL);
+		cb.addEventToProcQ(evt);
+	} 
+	else
+	{
+		SM::Event evt(Event_e::ESM_INFO_REQUIRED, NULL);
+		cb.addEventToProcQ(evt);
+	}
+	
+	return  ActStatus::PROCEED;
+}
+
+ActStatus ActionHandlers::send_esm_info_req_to_ue(SM::ControlBlock& cb)
+{
+	UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+
+	if (ue_ctxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "send_esm_info_req_to_ue: ue context is NULL \n");
+		return ActStatus::HALT;
+	}
+
+	SessionContext *sessionCtxt = ue_ctxt->getSessionContext();
+	esm_req_Q_msg esmreq;
+	esmreq.msg_type = esm_info_request;
+	esmreq.ue_idx = ue_ctxt->getContextID();
+	esmreq.enb_fd = ue_ctxt->getEnbFd();
+	esmreq.enb_s1ap_ue_id = ue_ctxt->getS1apEnbUeId();
+	esmreq.pti = sessionCtxt->getPti();
+	esmreq.dl_seq_no = ue_ctxt->getDwnLnkSeqNo();
+	memcpy(&(esmreq.int_key), &((ue_ctxt->getUeSecInfo().secinfo_m).int_key),
+			NAS_INT_KEY_SIZE);
+	ue_ctxt->setDwnLnkSeqNo(esmreq.dl_seq_no+1);
+
+	cmn::ipc::IpcAddress destAddr;
+	destAddr.u32 = TipcServiceInstance::s1apAppInstanceNum_c;
+
+	mmeIpcIf_g->dispatchIpcMsg((char *) &esmreq, sizeof(esmreq), destAddr);
+
+	log_msg(LOG_DEBUG, "Leaving send_esm_info_req_to_ue \n");
+
+	return ActStatus::PROCEED;
+}
+
+ActStatus ActionHandlers::process_esm_info_resp(SM::ControlBlock& cb)
+{
+	UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+	if (ue_ctxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "handle_ula: ue context is NULL \n");
+		return ActStatus::HALT;
+	}
+
+	SessionContext* sessionCtxt = ue_ctxt->getSessionContext();
+	if( sessionCtxt == NULL )
+	{
+	    log_msg(LOG_ERROR, "Failed to allocate Session "
+                            "Context for UE IDX %d\n", cb.getCBIndex());
+	    return ActStatus::HALT;
+	}
+
+	MsgBuffer* msgBuf = static_cast<MsgBuffer*>(cb.getMsgData());
+
+	if (msgBuf == NULL)
+		return ActStatus::HALT;
+
+	const s1_incoming_msg_data_t* s1_msg_data = static_cast<const s1_incoming_msg_data_t*>(msgBuf->getDataPointer());
+	const struct esm_resp_Q_msg &esm_res =s1_msg_data->msg_data.esm_resp_Q_msg_m;
+
+    	sessionCtxt->setAccessPtName(Apn_name(esm_res.apn));
+
+	return ActStatus::PROCEED;
+}
+
+ActStatus ActionHandlers::cs_req_to_sgw(SM::ControlBlock& cb)
+{
+	log_msg(LOG_DEBUG, "Inside cs_req_to_sgw \n");
+
+	UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+	MmeProcedureCtxt *procCtxt = dynamic_cast<MmeProcedureCtxt*>(cb.getTempDataBlock());
+	if (ue_ctxt == NULL  || procCtxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "handle_ula: UE context or Procedure Context is NULL \n");
+
+		return ActStatus::HALT;
+	}
+
+   	SessionContext* sessionCtxt = ue_ctxt->getSessionContext();
+	if( sessionCtxt == NULL )
+	{
+		log_msg(LOG_ERROR, "Failed to allocate Session Context for UE IDX %d\n", cb.getCBIndex());
+
+		return ActStatus::HALT;
+	}
+
+	BearerContext* bearerCtxt_p = sessionCtxt->getBearerContext();
+	if( bearerCtxt_p == NULL )
+	{
+		log_msg(LOG_ERROR, "Failed to allocate Bearer context for UE IDx %d\n", cb.getCBIndex());
+
+		return ActStatus::HALT;
+	}
+
+	struct CS_Q_msg cs_msg;
+	cs_msg.msg_type = create_session_request;
+	cs_msg.ue_idx = ue_ctxt->getContextID();
+	
+	const DigitRegister15& ueImsi = ue_ctxt->getImsi();
+	ueImsi.convertToBcdArray( cs_msg.IMSI );
+	
+	/*uint8_t  plmn_id[3] = {0};
+	memcpy(plmn_id, ue_ctxt->gettai().tai_m.plmn_id.idx, 3);
+	if ((plmn_id[1] & 0xF0) == 0xF0)
+		plmn_id[1] = plmn_id[1] & 0x0F;
+
+	const Apn_name &apnName = sessionCtxt->getaccessPtName();
+	std::string apnStr((const char *)apnName.apnname_m.val, apnName.apnname_m.len);
+
+	stringstream formattedApn;
+	formattedApn << apnStr  <<
+					 "\x6" << "mnc" <<
+					((plmn_id[1] & 0xF0) >> 4) <<
+					(plmn_id[2] & 0x0F) <<
+					((plmn_id[2] & 0xF0) >> 4) <<
+					"\x6" << "mcc" <<
+					(plmn_id[0] & 0x0F) <<
+					((plmn_id[0] & 0xF0) >> 4) <<
+					((plmn_id[1] & 0x0F)) <<
+					"\x4" << "gprs";
+
+	uint32_t formattedApnLen = formattedApn.str().length();
+	cs_msg.apn.len = formattedApnLen + 1;
+	cs_msg.apn.val[0] = apnStr.length();
+	memcpy(&cs_msg.apn.val[1], formattedApn.str().c_str(),
+	formattedApn.str().length()); */
+
+	const Apn_name &apnName = sessionCtxt->getAccessPtName();
+	memcpy(&(cs_msg.apn), &(apnName.apnname_m), sizeof(struct apn_name));
+	memcpy(&(cs_msg.tai), &(ue_ctxt->getTai().tai_m), sizeof(struct TAI));
+	memcpy(&(cs_msg.utran_cgi), &(ue_ctxt->getUtranCgi().cgi_m), sizeof(struct CGI));
+	memcpy(&(cs_msg.pco_options[0]), procCtxt->getPcoOptions(),sizeof(cs_msg.pco_options));
+
+	const AMBR& ambr = ue_ctxt->getAmbr().ambr_m;
+
+	cs_msg.max_requested_bw_dl = ambr.max_requested_bw_dl;
+	cs_msg.max_requested_bw_ul = ambr.max_requested_bw_ul;
+
+	memset(cs_msg.MSISDN, 0, BINARY_IMSI_LEN);
+	
+	const DigitRegister15& ueMSISDN = ue_ctxt->getMsisdn();
+	ueMSISDN.convertToBcdArray(cs_msg.MSISDN);
+
+	cmn::ipc::IpcAddress destAddr;
+	destAddr.u32 = TipcServiceInstance::s11AppInstanceNum_c;
+
+	mmeIpcIf_g->dispatchIpcMsg((char *) &cs_msg, sizeof(cs_msg), destAddr);
+
+	ProcedureStats::num_of_cs_req_to_sgw_sent ++;
+	log_msg(LOG_DEBUG, "Leaving cs_req_to_sgw \n");
+
+    	return ActStatus::PROCEED;
+}
+
+ActStatus ActionHandlers::process_cs_resp(SM::ControlBlock& cb)
+{
+	log_msg(LOG_DEBUG, "Entering handle_cs_resp \n");
+
+	UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+	if (ue_ctxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "handle_cs_resp: ue context is NULL \n");
+		return ActStatus::HALT;
+	}
+
+	SessionContext* sessionCtxt = ue_ctxt->getSessionContext();
+	if (sessionCtxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "handle_cs_resp: session ctxt is NULL \n");
+		return ActStatus::HALT;
+	}
+
+	MsgBuffer* msgBuf = static_cast<MsgBuffer*>(cb.getMsgData());
+
+	if (msgBuf == NULL)
+		return ActStatus::HALT;
+
+	const gtp_incoming_msg_data_t* gtp_msg_data= static_cast<const gtp_incoming_msg_data_t*>(msgBuf->getDataPointer());
+	const struct csr_Q_msg& csr_info = gtp_msg_data->msg_data.csr_Q_msg_m;
+
+	BearerContext* bearerCtxt = sessionCtxt->getBearerContext();
+	if( bearerCtxt == NULL )
+	{
+		log_msg(LOG_ERROR, "Failed to retrive Bearer context for UE IDx %d\n", cb.getCBIndex());
+
+		return ActStatus::HALT;
+	}
+
+	sessionCtxt->setS11SgwCtrlFteid(Fteid(csr_info.s11_sgw_fteid));
+	sessionCtxt->setS5S8PgwCtrlFteid(Fteid(csr_info.s5s8_pgwc_fteid));
+
+	bearerCtxt->setS1uSgwUserFteid(Fteid(csr_info.s1u_sgw_fteid));
+	bearerCtxt->setS5S8PgwUserFteid(Fteid(csr_info.s5s8_pgwu_fteid));
+
+	sessionCtxt->setPdnAddr(Paa(csr_info.pdn_addr));
+		
+	ProcedureStats::num_of_processed_cs_resp ++;
+	log_msg(LOG_DEBUG, "Leaving handle_cs_resp \n");
+	
+	return ActStatus::PROCEED;
+}
+
+ActStatus ActionHandlers::send_init_ctxt_req_to_ue(SM::ControlBlock& cb)
+{
+	log_msg(LOG_DEBUG, "Inside send_init_ctxt_req_to_ue \n");
+
+	UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+	if (ue_ctxt == NULL )
+	{
+		log_msg(LOG_DEBUG, "send_init_ctxt_req_to_ue: ue context is NULL \n");
+		return ActStatus::HALT;
+	}
+
+	MmeProcedureCtxt* procedure_p = dynamic_cast<MmeProcedureCtxt*>(cb.getTempDataBlock());
+	if (procedure_p == NULL)
+	{
+		log_msg(LOG_DEBUG, "send_init_ctxt_req_to_ue: procedure context is NULL \n");
+		return ActStatus::HALT;
+	}
+
+	if (procedure_p->getAttachType() == imsiAttach_c ||
+			procedure_p->getAttachType() == unknownGutiAttach_c)
+	{
+		uint32_t mTmsi = MmeCommonUtils::allocateMtmsi();
+		if (mTmsi == 0)
+		{
+			log_msg(LOG_DEBUG, "send_init_ctxt_req_to_ue: Failed to allocate mTmsi \n");
+			return ActStatus::HALT;
+		}
+
+		ue_ctxt->setMtmsi(mTmsi);
+
+		// TODO: Should this be done here or attach_done method
+		SubsDataGroupManager::Instance()->addmTmsikey(mTmsi, ue_ctxt->getContextID());
+	}
+
+	SessionContext* sessionCtxt = ue_ctxt->getSessionContext();
+	if (sessionCtxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "send_init_ctxt_req_to_ue: session ctxt is NULL \n");
+		return ActStatus::HALT;
+	}
+
+	unsigned int nas_count = 0;
+	E_UTRAN_sec_vector* secVect = const_cast<E_UTRAN_sec_vector*>(ue_ctxt->getAiaSecInfo().AiaSecInfo_mp);
+	secinfo& secInfo = const_cast<secinfo&>(ue_ctxt->getUeSecInfo().secinfo_m);
+
+	SecUtils::create_kenb_key(secVect->kasme.val, secInfo.kenb_key, nas_count);
+	
+	init_ctx_req_Q_msg icr_msg;
+	icr_msg.msg_type = init_ctxt_request;
+	icr_msg.ue_idx = ue_ctxt->getContextID();
+	icr_msg.enb_fd = ue_ctxt->getEnbFd();
+	icr_msg.enb_s1ap_ue_id = ue_ctxt->getS1apEnbUeId();
+
+	icr_msg.exg_max_dl_bitrate = (ue_ctxt->getAmbr().ambr_m).max_requested_bw_dl;
+	icr_msg.exg_max_ul_bitrate = (ue_ctxt->getAmbr().ambr_m).max_requested_bw_ul;
+	BearerContext* bearerCtxt = sessionCtxt->getBearerContext();
+	if( bearerCtxt == NULL )
+	{
+		log_msg(LOG_ERROR, "Failed to retrive Bearer context for UE IDx %d\n", cb.getCBIndex());
+
+		return ActStatus::HALT;
+	}
+
+	icr_msg.bearer_id = bearerCtxt->getBearerId();
+
+	icr_msg.dl_seq_no = ue_ctxt->getDwnLnkSeqNo();
+	memcpy(&(icr_msg.tai), &(ue_ctxt->getTai().tai_m), sizeof(struct TAI));
+	memcpy(&(icr_msg.gtp_teid), &(bearerCtxt->getS1uSgwUserFteid().fteid_m), sizeof(struct fteid));
+	memcpy(&(icr_msg.apn), &(sessionCtxt->getAccessPtName().apnname_m), sizeof(struct apn_name));
+	memcpy(&(icr_msg.pdn_addr), &(sessionCtxt->getPdnAddr().paa_m), sizeof(struct PAA));
+	memcpy(&(icr_msg.int_key), &((ue_ctxt->getUeSecInfo().secinfo_m).int_key),
+			NAS_INT_KEY_SIZE);
+	memcpy(&(icr_msg.sec_key), &((ue_ctxt->getUeSecInfo().secinfo_m).kenb_key),
+			KENB_SIZE);	
+	icr_msg.pti = sessionCtxt->getPti();
+        icr_msg.m_tmsi = ue_ctxt->getMtmsi();
+	ue_ctxt->setDwnLnkSeqNo(icr_msg.dl_seq_no+1);
+
+	cmn::ipc::IpcAddress destAddr;
+	destAddr.u32 = TipcServiceInstance::s1apAppInstanceNum_c;
+
+	mmeIpcIf_g->dispatchIpcMsg((char *) &icr_msg, sizeof(icr_msg), destAddr);
+	
+	ProcedureStats::num_of_init_ctxt_req_to_ue_sent ++;
+	log_msg(LOG_DEBUG, "Leaving send_init_ctxt_req_to_ue_v \n");
+		
+	return ActStatus::PROCEED;
+}
+
+ActStatus ActionHandlers::process_init_ctxt_resp(SM::ControlBlock& cb)
+{
+	log_msg(LOG_DEBUG, "Inside process_init_ctxt_resp \n");
+
+	UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+	MmeProcedureCtxt *procCtxt = dynamic_cast<MmeProcedureCtxt*>(cb.getTempDataBlock());
+
+	if (ue_ctxt == NULL || procCtxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "process_init_ctxt_resp: ue context or procedure ctxt is NULL \n");
+		return ActStatus::HALT;
+	}
+
+	SessionContext* sessionCtxt = ue_ctxt->getSessionContext();
+	if (sessionCtxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "process_init_ctxt_resp: session ctxt is NULL \n");
+		return ActStatus::HALT;
+	}
+	
+	MsgBuffer* msgBuf = static_cast<MsgBuffer*>(cb.getMsgData());
+
+	if (msgBuf == NULL)
+		return ActStatus::HALT;
+
+	const s1_incoming_msg_data_t* s1_msg_data = static_cast<const s1_incoming_msg_data_t*>(msgBuf->getDataPointer());
+	const struct initctx_resp_Q_msg &ics_res =s1_msg_data->msg_data.initctx_resp_Q_msg_m;
+	
+	fteid S1uEnbUserFteid;
+	S1uEnbUserFteid.header.iface_type = 0;
+	S1uEnbUserFteid.header.v4 = 1;
+	S1uEnbUserFteid.header.teid_gre = ics_res.gtp_teid;
+	S1uEnbUserFteid.ip.ipv4 = *(struct in_addr*)&ics_res.transp_layer_addr;
+	
+	BearerContext* bearerCtxt = sessionCtxt->getBearerContext();
+	if (bearerCtxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "process_init_ctxt_resp: bearer ctxt is NULL \n");
+		return ActStatus::HALT;
+	}
+
+	bearerCtxt->setS1uEnbUserFteid(Fteid(S1uEnbUserFteid));
+
+	ProcedureStats::num_of_processed_init_ctxt_resp ++;
+	log_msg(LOG_DEBUG, "Leaving process_init_ctxt_resp \n");
+	
+	return ActStatus::PROCEED;
+}
+
+ActStatus ActionHandlers::send_mb_req_to_sgw(SM::ControlBlock& cb)
+{
+	log_msg(LOG_DEBUG, "Inside send_mb_req_to_sgw \n");
+
+	UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+	if (ue_ctxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "send_mb_req_to_sgw: ue context or procedure ctxt is NULL \n");
+		return ActStatus::HALT;
+	}
+
+	SessionContext* sessionCtxt = ue_ctxt->getSessionContext();
+	if (sessionCtxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "send_mb_req_to_sgw: session ctxt is NULL \n");
+		return ActStatus::HALT;
+	}
+	
+	struct MB_Q_msg mb_msg;
+	mb_msg.msg_type = modify_bearer_request;
+	mb_msg.ue_idx = ue_ctxt->getContextID();
+	
+	memset(mb_msg.indication, 0, S11_MB_INDICATION_FLAG_SIZE); /*TODO : future*/
+	BearerContext* bearerCtxt = sessionCtxt->getBearerContext();
+	if (bearerCtxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "send_mb_req_to_sgw: bearer ctxt is NULL \n");
+		return ActStatus::HALT;
+	}
+
+	mb_msg.bearer_id = bearerCtxt->getBearerId();
+
+	memcpy(&(mb_msg.s11_sgw_c_fteid), &(sessionCtxt->getS11SgwCtrlFteid().fteid_m),
+		sizeof(struct fteid));
+
+	memcpy(&(mb_msg.s1u_enb_fteid), &(bearerCtxt->getS1uEnbUserFteid().fteid_m),
+		sizeof(struct fteid));
+
+
+	cmn::ipc::IpcAddress destAddr;
+	destAddr.u32 = TipcServiceInstance::s11AppInstanceNum_c;
+
+	mmeIpcIf_g->dispatchIpcMsg((char *) &mb_msg, sizeof(mb_msg), destAddr);
+		
+	ProcedureStats::num_of_mb_req_to_sgw_sent ++;
+	log_msg(LOG_DEBUG, "Leaving send_mb_req_to_sgw \n");
+	
+	return ActStatus::PROCEED;
+
+}
+
+ActStatus ActionHandlers::process_attach_cmp_from_ue(SM::ControlBlock& cb)
+{	
+	log_msg(LOG_DEBUG, "Inside handle_attach_cmp_from_ue \n");
+
+	UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+	if (ue_ctxt == NULL)
+	{
+		log_msg(LOG_ERROR, "attach_done: ue context is NULL \n");
+		return ActStatus::HALT;
+	}
+
+	ue_ctxt->setUpLnkSeqNo(ue_ctxt->getUpLnkSeqNo()+1);
+
+	ProcedureStats::num_of_processed_attach_cmp_from_ue ++;
+	log_msg(LOG_DEBUG, "Leaving handle_attach_cmp_from_ue \n");
+	
+	return ActStatus::PROCEED;
+}
+
+ActStatus ActionHandlers::process_mb_resp(SM::ControlBlock& cb)
+{	
+	log_msg(LOG_DEBUG, "Inside handle_mb_resp \n");
+	ProcedureStats::num_of_processed_mb_resp ++;
+	return ActStatus::PROCEED;
+}
+
+ActStatus ActionHandlers::attach_done(SM::ControlBlock& cb)
+{	
+	log_msg(LOG_DEBUG, "Inside attach_done \n");
+	
+	UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+	if (ue_ctxt == NULL)
+	{
+		log_msg(LOG_ERROR, "attach_done: ue context is NULL \n");
+		return ActStatus::HALT;
+	}
+
+	MmContext* mmCtxt = ue_ctxt->getMmContext();
+	if (mmCtxt == NULL)
+	{
+		log_msg(LOG_ERROR, "attach_done: MMcontext is NULL \n");
+		return ActStatus::HALT;
+	}
+
+	mmCtxt->setMmState(EpsAttached);
+	
+	MmeContextManagerUtils::deallocateProcedureCtxt(cb, attach_c);
+
+	ProcedureStats::num_of_attach_done++;
+	ProcedureStats::num_of_subscribers_attached ++;
+
+	log_msg(LOG_DEBUG,"Leaving attach done\n");
+
+	return ActStatus::PROCEED;
+}
diff --git a/src/mme-app/actionHandlers/defaultMmeProcedureActionHandlers.cpp b/src/mme-app/actionHandlers/defaultMmeProcedureActionHandlers.cpp
new file mode 100644
index 0000000..269b7fc
--- /dev/null
+++ b/src/mme-app/actionHandlers/defaultMmeProcedureActionHandlers.cpp
@@ -0,0 +1,382 @@
+/*
+ * Copyright 2019-present Infosys Limited
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/******************************************************************************
+ *
+ * This file has both generated and manual code.
+ *
+ * File template used for code generation:
+ * <TOP-DIR/scripts/SMCodeGen/templates/stateMachineTmpls/actionHandlers.cpp.tt>
+ *
+ ******************************************************************************/
+
+#include <actionHandlers/actionHandlers.h>
+#include <contextManager/dataBlocks.h>
+#include <contextManager/subsDataGroupManager.h>
+#include <controlBlock.h>
+#include <event.h>
+#include <mmeStates/attachStart.h>
+#include <mmeStates/detachStart.h>
+#include <mmeStates/niDetachStart.h>
+#include <mmeStates/pagingStart.h>
+#include <mmeStates/s1ReleaseStart.h>
+#include <mmeStates/serviceRequestStart.h>
+#include "mmeStates/tauStart.h"
+#include <msgBuffer.h>
+#include <msgType.h>
+#include <log.h>
+#include <procedureStats.h>
+#include <s1ap_structs.h>
+#include <state.h>
+#include <string.h>
+#include <sstream>
+#include <smTypes.h>
+#include <typeinfo>
+#include <utils/mmeProcedureTypes.h>
+#include <utils/mmeCommonUtils.h>
+#include <utils/mmeContextManagerUtils.h>
+
+using namespace mme;
+using namespace SM;
+
+/***************************************
+* Action handler : default_attach_req_handler
+***************************************/
+ActStatus ActionHandlers::default_attach_req_handler(ControlBlock& cb)
+{
+	log_msg(LOG_ERROR, "default_attach_req_handler \n");
+
+	UEContext* ueCtxt_p = NULL;
+	MmContext* mmctxt = NULL;
+
+	ueCtxt_p = static_cast <UEContext *>(cb.getPermDataBlock());
+	if (ueCtxt_p != NULL)
+		mmctxt = ueCtxt_p->getMmContext();
+
+	MsgBuffer* msgBuf = static_cast<MsgBuffer*>(cb.getMsgData());
+	if (msgBuf == NULL)
+	{
+		log_msg(LOG_ERROR, "Failed to retrieve message buffer \n");
+		return ActStatus::HALT;
+	}
+
+	const s1_incoming_msg_data_t* msgData_p =
+			static_cast<const s1_incoming_msg_data_t*>(msgBuf->getDataPointer());
+	if (msgData_p == NULL)
+	{
+		log_msg(LOG_ERROR, "Failed to retrieve data buffer \n");
+		return ActStatus::HALT;
+	}
+
+	const struct ue_attach_info &ue_info = (msgData_p->msg_data.ue_attach_info_m);
+
+	AttachType attachType = MmeCommonUtils::getAttachType(ueCtxt_p, ue_info);
+	if (attachType == maxAttachType_c)
+	{
+		log_msg(LOG_ERROR, "Failed to identify attach type \n");
+		return ActStatus::HALT;
+	}
+
+	if (ueCtxt_p == NULL)
+	{
+		ueCtxt_p = SubsDataGroupManager::Instance()->getUEContext();
+		if (ueCtxt_p == NULL)
+		{
+			log_msg(LOG_ERROR, "Failed to allocate UE context \n");
+
+			return ActStatus::HALT;
+		}
+
+		mmctxt = SubsDataGroupManager::Instance()->getMmContext();
+		if( mmctxt == NULL )
+		{
+			log_msg(LOG_ERROR, "Failed to allocate MM Context \n");
+
+			SubsDataGroupManager::Instance()->deleteUEContext( ueCtxt_p );
+			return ActStatus::HALT;
+		}
+
+		ueCtxt_p->setContextID(cb.getCBIndex());
+		ueCtxt_p->setMmContext( mmctxt );
+
+		cb.setPermDataBlock(ueCtxt_p);
+		cb.setFastAccessBlock(ueCtxt_p, 1);
+	}
+
+	MmeProcedureCtxt* prcdCtxt_p = SubsDataGroupManager::Instance()->getMmeProcedureCtxt();
+	if( prcdCtxt_p == NULL )
+	{
+		log_msg(LOG_ERROR, "Failed to allocate Procedure Context \n");
+
+		return ActStatus::HALT;
+	}
+
+	prcdCtxt_p->setCtxtType( ProcedureType::attach_c );
+	prcdCtxt_p->setNextState(AttachStart::Instance());
+
+	cb.setCurrentTempDataBlock(prcdCtxt_p);
+
+	// Copy attach request message data into UE Context
+
+	ueCtxt_p->setS1apEnbUeId(ue_info.s1ap_enb_ue_id);
+	ueCtxt_p->setEnbFd(ue_info.enb_fd);
+	ueCtxt_p->setTai(Tai(ue_info.tai));
+	ueCtxt_p->setUtranCgi(Cgi(ue_info.utran_cgi));
+	ueCtxt_p->setUeNetCapab(Ue_net_capab(ue_info.ue_net_capab));
+	ueCtxt_p->setMsNetCapab(Ms_net_capab(ue_info.ms_net_capab));
+	prcdCtxt_p->setPti(ue_info.pti);
+	prcdCtxt_p->setPcoOptions(ue_info.pco_options);
+	prcdCtxt_p->setEsmInfoTxRequired(ue_info.esm_info_tx_required);
+	prcdCtxt_p->setAttachType(attachType);
+
+	switch(attachType)
+	{
+		case imsiAttach_c:
+		{
+			uint8_t imsi[BINARY_IMSI_LEN] = {0};
+		    	memcpy( imsi, ue_info.IMSI, BINARY_IMSI_LEN );
+
+			// Only upper nibble of first octect in imsi need to be considered
+			// Changing the lower nibble to 0x0f for handling
+			uint8_t first = imsi[0] >> 4;
+			imsi[0] = (uint8_t)(( first << 4 ) | 0x0f );
+
+			DigitRegister15 IMSIInfo;
+			IMSIInfo.convertFromBcdArray(imsi);
+			ueCtxt_p->setImsi(IMSIInfo);
+
+			SubsDataGroupManager::Instance()->addimsikey(ueCtxt_p->getImsi(), ueCtxt_p->getContextID());
+
+			SM::Event evt(Event_e::VALIDATE_IMSI, NULL);
+			cb.addEventToProcQ(evt);
+
+			break;
+		}
+		case knownGutiAttach_c:
+		{
+			// copy seq num?
+
+			SM::Event evt(Event_e::VALIDATE_IMSI, NULL);
+			cb.addEventToProcQ(evt);
+
+			break;
+		}
+		case unknownGutiAttach_c:
+		{
+			SM::Event evt(Event_e::VALIDATE_IMSI, NULL);
+			cb.addEventToProcQ(evt);
+
+			break;
+		}
+		default:
+		{
+			log_msg(LOG_ERROR, "Unhandled attach type %s", attachType);
+		}
+	}
+
+	return ActStatus::PROCEED;
+}
+
+/***************************************
+* Action handler : default_detach_req_handler
+***************************************/
+ActStatus ActionHandlers::default_detach_req_handler(ControlBlock& cb)
+{
+	MmeDetachProcedureCtxt* prcdCtxt_p = SubsDataGroupManager::Instance()->getMmeDetachProcedureCtxt();
+	if( prcdCtxt_p == NULL )
+	{
+		log_msg(LOG_ERROR, "Failed to allocate procedure context for detach cbIndex %d\n", cb.getCBIndex());
+
+		return ActStatus::HALT;
+	}
+
+	prcdCtxt_p->setCtxtType( ProcedureType::detach_c );
+	prcdCtxt_p->setDetachType( DetachType::ueInitDetach_c );
+	prcdCtxt_p->setNextState(DetachStart::Instance());
+	cb.setCurrentTempDataBlock(prcdCtxt_p);
+
+	SM::Event evt(Event_e::DETACH_REQ_FROM_UE, NULL);
+	cb.addEventToProcQ(evt);
+
+	return ActStatus::PROCEED;
+}
+
+/***************************************
+* Action handler : default_ddn_handler
+***************************************/
+ActStatus ActionHandlers::default_ddn_handler(ControlBlock& cb)
+{
+	MmeSvcReqProcedureCtxt* svcReqProc_p = SubsDataGroupManager::Instance()->getMmeSvcReqProcedureCtxt();
+	if (svcReqProc_p == NULL)
+	{
+		log_msg(LOG_ERROR, "Failed to allocate procedure context"
+				" for DDN handling cbIndex %d\n", cb.getCBIndex());
+
+		return ActStatus::HALT;
+	}
+	
+	MsgBuffer* msgBuf = static_cast<MsgBuffer*>(cb.getMsgData());
+
+	if (msgBuf == NULL)
+	{
+	    log_msg(LOG_DEBUG,"process_ddn: msgBuf is NULL \n");
+	    return ActStatus::HALT;
+   	}
+
+   	const gtp_incoming_msg_data_t* gtp_msg_data= static_cast<const gtp_incoming_msg_data_t*>(msgBuf->getDataPointer());
+   	const struct ddn_Q_msg& ddn_info = gtp_msg_data->msg_data.ddn_Q_msg_m;
+
+	svcReqProc_p->setCtxtType(ProcedureType::serviceRequest_c);
+	svcReqProc_p->setNextState(PagingStart::Instance());
+	svcReqProc_p->setPagingTrigger(ddnInit_c);
+	svcReqProc_p->setDdnSeqNo(ddn_info.seq_no);
+	svcReqProc_p->setArp(Arp(ddn_info.arp));
+	svcReqProc_p->setEpsBearerId(ddn_info.eps_bearer_id);
+
+	cb.setCurrentTempDataBlock(svcReqProc_p);
+    
+	SM::Event evt(Event_e::DDN_FROM_SGW, NULL);
+	cb.addEventToProcQ(evt);
+	return ActStatus::PROCEED;
+}
+
+/***************************************
+* Action handler : default_service_req_handler
+***************************************/
+ActStatus ActionHandlers::default_service_req_handler(ControlBlock& cb)
+{
+	MmeSvcReqProcedureCtxt* svcReqProc_p = SubsDataGroupManager::Instance()->getMmeSvcReqProcedureCtxt();
+	if (svcReqProc_p == NULL)
+	{
+		log_msg(LOG_ERROR, "Failed to allocate procedure context"
+				" for service request cbIndex %d\n", cb.getCBIndex());
+
+		return ActStatus::HALT;
+	}
+
+	svcReqProc_p->setCtxtType(ProcedureType::serviceRequest_c);
+	svcReqProc_p->setNextState(ServiceRequestStart::Instance());
+	cb.setCurrentTempDataBlock(svcReqProc_p);
+
+	SM::Event evt(Event_e::SERVICE_REQUEST_FROM_UE, NULL);
+	cb.addEventToProcQ(evt);
+
+    return ActStatus::PROCEED;
+}
+
+/***************************************
+* Action handler : default_cancel_loc_req_handler
+***************************************/
+ActStatus ActionHandlers::default_cancel_loc_req_handler(ControlBlock& cb)
+{
+	UEContext *ueCtxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+	if (ueCtxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "ue context is NULL \n");
+		return ActStatus::HALT;
+	}
+
+	MmContext* mmCtxt = ueCtxt->getMmContext();
+	if (mmCtxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "mm context is NULL \n");
+		return ActStatus::HALT;
+	}
+
+	if (mmCtxt->getMmState() == EpsDetached)
+	{
+		log_msg(LOG_INFO, "Subscriber is already detached. "
+				"Cleaning up the contexts. UE IDx %d\n", cb.getCBIndex());
+		
+		MmeContextManagerUtils::deleteUEContext(cb.getCBIndex());
+
+		return ActStatus::PROCEED;
+	}
+
+	MmeDetachProcedureCtxt* prcdCtxt_p = SubsDataGroupManager::Instance()->getMmeDetachProcedureCtxt();
+	if(prcdCtxt_p == NULL)
+	{
+		log_msg(LOG_ERROR, "Failed to allocate Procedure Ctxt\n");
+		return ActStatus::HALT;
+	}
+	prcdCtxt_p->setCtxtType( ProcedureType::detach_c );
+	prcdCtxt_p->setDetachType(DetachType::hssInitDetach_c);
+	prcdCtxt_p->setNextState(NiDetachStart::Instance());
+	prcdCtxt_p->setCancellationType(SUBSCRIPTION_WITHDRAWAL);
+	cb.setCurrentTempDataBlock(prcdCtxt_p);
+
+	SM::Event evt(Event_e::CLR_FROM_HSS, NULL);
+	cb.addEventToProcQ(evt);
+
+    return ActStatus::PROCEED;
+}
+
+/***************************************
+* Action handler : default_s1_release_req_handler
+***************************************/
+ActStatus ActionHandlers::default_s1_release_req_handler(ControlBlock& cb)
+{
+	MmeProcedureCtxt* prcdCtxt_p = SubsDataGroupManager::Instance()->getMmeProcedureCtxt();
+	if( prcdCtxt_p == NULL )
+	{
+		log_msg(LOG_ERROR, "Failed to allocate procedure Ctxt \n");
+		return ActStatus::HALT;
+	}
+
+	prcdCtxt_p->setCtxtType( ProcedureType::s1Release_c );
+	prcdCtxt_p->setNextState(S1ReleaseStart::Instance());
+	cb.setCurrentTempDataBlock(prcdCtxt_p);
+
+	ProcedureStats::num_of_s1_rel_req_received ++;
+
+	SM::Event evt(Event_e::S1_REL_REQ_FROM_UE, NULL);
+	cb.addEventToProcQ(evt);
+
+	return ActStatus::PROCEED;
+}
+
+/***************************************
+* Action handler : default_tau_req_handler
+***************************************/
+ActStatus ActionHandlers::default_tau_req_handler(ControlBlock& cb)
+{
+	MmeTauProcedureCtxt* tauReqProc_p = SubsDataGroupManager::Instance()->getMmeTauProcedureCtxt();
+	if (tauReqProc_p == NULL)
+	{
+		log_msg(LOG_ERROR, "Failed to allocate procedure context"
+				" for tau request cbIndex %d\n", cb.getCBIndex());
+
+		return ActStatus::HALT;
+	}
+	
+	MsgBuffer* msgBuf = static_cast<MsgBuffer*>(cb.getMsgData());
+	if (msgBuf == NULL)
+	{	
+            log_msg(LOG_DEBUG,"process_tau_req: msgBuf is NULL \n");
+            return ActStatus::HALT;
+	}
+	
+	const s1_incoming_msg_data_t* msgData_p =
+			static_cast<const s1_incoming_msg_data_t*>(msgBuf->getDataPointer());
+	if (msgData_p == NULL)
+	{
+		log_msg(LOG_ERROR, "Failed to retrieve data buffer \n");
+		return ActStatus::HALT;
+	}
+
+	const struct tauReq_Q_msg &tauReq = (msgData_p->msg_data.tauReq_Q_msg_m);	
+	
+	tauReqProc_p->setCtxtType(ProcedureType::tau_c);
+	tauReqProc_p->setNextState(TauStart::Instance());	
+	tauReqProc_p->setS1apEnbUeId(msgData_p->s1ap_enb_ue_id);
+	tauReqProc_p->setEnbFd(tauReq.enb_fd);
+	cb.setCurrentTempDataBlock(tauReqProc_p);	
+
+	SM::Event evt(Event_e::TAU_REQUEST_FROM_UE, NULL);
+	cb.addEventToProcQ(evt);
+	return ActStatus::PROCEED;
+}
+
diff --git a/src/mme-app/actionHandlers/networkInitDetachActionHandlers.cpp b/src/mme-app/actionHandlers/networkInitDetachActionHandlers.cpp
new file mode 100644
index 0000000..2b75249
--- /dev/null
+++ b/src/mme-app/actionHandlers/networkInitDetachActionHandlers.cpp
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2019-present Infosys Limited
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <typeinfo>
+#include "actionHandlers/actionHandlers.h"
+#include "controlBlock.h"
+#include "msgType.h"
+#include "contextManager/subsDataGroupManager.h"
+#include "contextManager/dataBlocks.h"
+#include "procedureStats.h"
+#include "log.h"
+#include "secUtils.h"
+#include "state.h"
+#include <string.h>
+#include <sstream>
+#include <smTypes.h>
+
+#include <ipcTypes.h>
+#include <tipcTypes.h>
+#include <msgBuffer.h>
+#include <interfaces/mmeIpcInterface.h>
+#include <utils/mmeContextManagerUtils.h>
+
+using namespace SM;
+using namespace mme;
+using namespace cmn::utils;
+
+extern MmeIpcInterface* mmeIpcIf_g;
+
+ActStatus ActionHandlers::ni_detach_req_to_ue(SM::ControlBlock& cb)
+{
+	log_msg(LOG_DEBUG, "Inside ni_detach_req_to_ue \n");
+	
+	UEContext *ue_ctxt =  dynamic_cast<UEContext*>(cb.getPermDataBlock());
+	
+	if (ue_ctxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "ni_detach_req_to_ue: ue context is NULL\n");
+		return ActStatus::HALT;
+	}
+	
+	ni_detach_request_Q_msg ni_detach_req;
+	
+	ni_detach_req.msg_type = ni_detach_request;
+	ni_detach_req.enb_fd = ue_ctxt->getEnbFd();
+	ni_detach_req.ue_idx = ue_ctxt->getContextID();
+	ni_detach_req.enb_s1ap_ue_id =  ue_ctxt->getS1apEnbUeId();
+	ni_detach_req.detach_type = 00000010;
+	
+	ue_ctxt->setDwnLnkSeqNo(ue_ctxt->getDwnLnkSeqNo()+1);
+	ni_detach_req.dl_seq_no = ue_ctxt->getDwnLnkSeqNo();
+	
+	memcpy(&(ni_detach_req.int_key), &(ue_ctxt->getUeSecInfo().secinfo_m.int_key), NAS_INT_KEY_SIZE);
+	
+	/* Send message to S1app in S1q*/
+	cmn::ipc::IpcAddress destAddr;
+	destAddr.u32 = TipcServiceInstance::s1apAppInstanceNum_c;
+
+	mmeIpcIf_g->dispatchIpcMsg((char *) &ni_detach_req, sizeof(ni_detach_req), destAddr);
+	
+	log_msg(LOG_DEBUG, "Leaving ni_detach_req_to_ue \n");
+
+	ProcedureStats::num_of_clr_received ++;
+	ProcedureStats::num_of_detach_req_to_ue_sent ++;
+
+	return ActStatus::PROCEED;
+}
+
+ActStatus ActionHandlers::process_detach_accept_from_ue(SM::ControlBlock& cb)
+{
+	log_msg(LOG_DEBUG, "Inside process_detach_accept_from_ue \n");
+		
+	UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+	
+	if (ue_ctxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "process_detach_accept_from_ue: ue context is NULL\n");
+		return ActStatus::HALT;
+	}
+		
+	ue_ctxt->setUpLnkSeqNo(ue_ctxt->getUpLnkSeqNo()+1);
+	
+	log_msg(LOG_DEBUG, "Leaving process_detach_accept_from_ue \n");
+
+	ProcedureStats::num_of_cla_sent ++;
+	ProcedureStats::num_of_detach_accept_from_ue ++;
+
+	return ActStatus::PROCEED;
+}
+
+/***************************************
+* Action handler : send_s1_rel_cmd_to_ue_for_detach
+***************************************/
+ActStatus ActionHandlers::send_s1_rel_cmd_to_ue_for_detach(ControlBlock& cb)
+{
+    log_msg(LOG_DEBUG, "Inside send_s1_rel_cmd_to_ue_for_detach\n");
+
+    UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+    if(ue_ctxt == NULL)
+    {
+            log_msg(LOG_DEBUG, "send_s1_rel_cmd_to_ue_for_detach: ue context is NULL \n");
+            return ActStatus::HALT;
+    }
+
+    struct s1relcmd_info s1relcmd;
+
+    s1relcmd.msg_type = s1_release_command;
+    s1relcmd.ue_idx = ue_ctxt->getContextID();
+    s1relcmd.enb_fd = ue_ctxt->getEnbFd();
+    s1relcmd.enb_s1ap_ue_id = ue_ctxt->getS1apEnbUeId();
+    s1relcmd.cause.present = s1apCause_PR_radioNetwork;
+    s1relcmd.cause.choice.radioNetwork = s1apCauseRadioNetwork_user_inactivity;
+
+    /*Send message to S1AP-APP*/
+    cmn::ipc::IpcAddress destAddr;
+    destAddr.u32 = TipcServiceInstance::s1apAppInstanceNum_c;
+    mmeIpcIf_g->dispatchIpcMsg((char *) &s1relcmd, sizeof(s1relcmd), destAddr);
+
+    log_msg(LOG_DEBUG,"Leaving send_s1_rel_cmd_to_ue \n");
+
+    ProcedureStats::num_of_s1_rel_cmd_sent ++;
+    return ActStatus::PROCEED;
+}
+
+/************************************************************
+* Action handler : process_ue_ctxt_rel_comp_for_detach
+**************************************************************/
+ActStatus ActionHandlers::process_ue_ctxt_rel_comp_for_detach(ControlBlock& cb)
+{
+    log_msg(LOG_DEBUG, "Inside process_ue_ctxt_rel_comp_for_detach \n");
+
+    UEContext *ueCtxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+    MmeDetachProcedureCtxt *procCtxt = dynamic_cast<MmeDetachProcedureCtxt*>(cb.getTempDataBlock());
+    if (ueCtxt == NULL || procCtxt == NULL)
+    {
+    	log_msg(LOG_DEBUG, "UE context or  procedure context is NULL\n");
+    	return ActStatus::HALT;
+    }
+
+    MmContext* mmCtxt = ueCtxt->getMmContext();
+    if (mmCtxt == NULL)
+    {
+    	log_msg(LOG_DEBUG, "MM context is NULL \n");
+    	return ActStatus::HALT;
+    }
+
+    if(procCtxt->getCancellationType() == SUBSCRIPTION_WITHDRAWAL)
+    {
+        MmeContextManagerUtils::deleteUEContext(cb.getCBIndex());
+    }
+    else
+    {
+    	mmCtxt->setMmState( EpsDetached );
+    	MmeContextManagerUtils::deallocateProcedureCtxt(cb, detach_c);
+    }
+
+    ProcedureStats::num_of_subscribers_detached ++;
+    ProcedureStats::num_of_subscribers_attached --;
+
+    log_msg(LOG_DEBUG, "Leaving process_ue_ctxt_rel_comp_for_detach \n");
+
+    return ActStatus::PROCEED;
+
+}
+
diff --git a/src/mme-app/actionHandlers/s1releaseActionHandlers.cpp b/src/mme-app/actionHandlers/s1releaseActionHandlers.cpp
new file mode 100644
index 0000000..de3d16f
--- /dev/null
+++ b/src/mme-app/actionHandlers/s1releaseActionHandlers.cpp
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2019-present Infosys Limited
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/******************************************************************************
+ *
+ * This file has both generated and manual code.
+ *
+ * File template used for code generation:
+ * <TOP-DIR/scripts/SMCodeGen/templates/stateMachineTmpls/actionHandlers.cpp.tt>
+ *
+ ******************************************************************************/
+
+#include <typeinfo>
+#include "actionHandlers/actionHandlers.h"
+#include "controlBlock.h"
+#include "msgType.h"
+#include "contextManager/subsDataGroupManager.h"
+#include "contextManager/dataBlocks.h"
+#include "procedureStats.h"
+#include "log.h"
+#include "secUtils.h"
+#include "state.h"
+#include <string.h>
+#include <sstream>
+#include <smTypes.h>
+
+#include <ipcTypes.h>
+#include <tipcTypes.h>
+#include <msgBuffer.h>
+#include <interfaces/mmeIpcInterface.h>
+#include <utils/mmeContextManagerUtils.h>
+
+using namespace SM;
+using namespace mme;
+using namespace cmn::utils;
+
+extern MmeIpcInterface* mmeIpcIf_g;
+
+ActStatus ActionHandlers:: send_rel_ab_req_to_sgw(SM::ControlBlock& cb)
+{
+	log_msg(LOG_DEBUG, "Inside send_rel_ab_req_to_sgw \n");
+
+	UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+	if (ue_ctxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "send_rel_ab_req_to_sgw: ue ctxt is NULL \n");
+		return ActStatus::HALT;
+	}
+	
+	SessionContext* sessionCtxt = ue_ctxt->getSessionContext();
+	if (sessionCtxt == NULL)
+	{
+		log_msg(LOG_DEBUG, " send_rel_ab_req_to_sgw: session ctxt is NULL \n");
+		return ActStatus::HALT;
+	}
+
+	BearerContext* bearerCtxt = sessionCtxt->getBearerContext();
+	if (bearerCtxt == NULL)
+	{
+		log_msg(LOG_DEBUG, " send_rel_ab_req_to_sgw: bearer ctxt is NULL \n");
+		return ActStatus::HALT;
+	}
+
+	struct RB_Q_msg rb_msg;
+	rb_msg.msg_type = release_bearer_request;
+	rb_msg.ue_idx = ue_ctxt->getContextID();
+	memset(rb_msg.indication, 0 , S11_RB_INDICATION_FLAG_SIZE);
+	rb_msg.bearer_id = bearerCtxt->getBearerId();
+	memcpy(&(rb_msg.s11_sgw_c_fteid), &(sessionCtxt->getS11SgwCtrlFteid()),
+			sizeof(struct fteid));
+	memcpy(&(rb_msg.s1u_enb_fteid), &(bearerCtxt->getS1uEnbUserFteid()),
+			sizeof(struct fteid));
+			
+	cmn::ipc::IpcAddress destAddr;
+	destAddr.u32 = TipcServiceInstance::s11AppInstanceNum_c;
+	mmeIpcIf_g->dispatchIpcMsg((char *) &rb_msg, sizeof(rb_msg), destAddr);
+
+	ProcedureStats::num_of_rel_access_bearer_req_sent ++;
+	
+	log_msg(LOG_DEBUG, "Inside send_rel_ab_req_to_sgw \n");
+
+	return ActStatus::PROCEED;
+}
+
+ActStatus ActionHandlers:: process_rel_ab_resp_from_sgw(SM::ControlBlock& cb)
+{
+	log_msg(LOG_DEBUG, "process_rel_ab_resp_from_sgw \n");
+
+	ProcedureStats::num_of_rel_access_bearer_resp_received ++;
+
+	return ActStatus::PROCEED;
+}
+
+ActStatus ActionHandlers:: send_s1_rel_cmd_to_ue(SM::ControlBlock& cb)
+{
+	log_msg(LOG_DEBUG, "Inside send_s1_rel_cmd_to_ue\n");
+
+	UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+	if(ue_ctxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "send_s1_rel_cmd_to_ue: ue context is NULL \n");
+
+		return ActStatus::HALT;
+	}
+	
+	struct s1relcmd_info s1relcmd;
+	s1relcmd.msg_type = s1_release_command;
+	s1relcmd.ue_idx = ue_ctxt->getContextID();
+	s1relcmd.enb_fd = ue_ctxt->getEnbFd();
+	s1relcmd.enb_s1ap_ue_id = ue_ctxt->getS1apEnbUeId();
+	s1relcmd.cause.present = s1apCause_PR_radioNetwork;
+    	s1relcmd.cause.choice.radioNetwork = s1apCauseRadioNetwork_user_inactivity;
+
+	/*Send message to S1AP-APP*/
+	cmn::ipc::IpcAddress destAddr;
+	destAddr.u32 = TipcServiceInstance::s1apAppInstanceNum_c;
+	mmeIpcIf_g->dispatchIpcMsg((char *) &s1relcmd, sizeof(s1relcmd), destAddr);
+	
+	ProcedureStats::num_of_s1_rel_cmd_sent ++;
+	
+	log_msg(LOG_DEBUG,"Leaving send_s1_rel_cmd_to_ue \n");
+
+	return ActStatus::PROCEED;
+}
+
+ActStatus ActionHandlers:: process_ue_ctxt_rel_comp(SM::ControlBlock& cb)
+{
+	log_msg(LOG_DEBUG, "Inside handle_ctxt_rel_comp \n");
+
+	UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+	if (ue_ctxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "process_ue_ctxt_rel_comp: ue context is NULL\n");
+
+		return ActStatus::HALT;
+	}
+
+	MmeContextManagerUtils::deallocateProcedureCtxt(cb, s1Release_c);
+
+	ProcedureStats::num_of_s1_rel_comp_received++;
+
+    	log_msg(LOG_DEBUG, "Leaving process_ue_ctxt_rel_comp \n");
+
+    	return ActStatus::PROCEED;
+}
+
+	
+	
diff --git a/src/mme-app/actionHandlers/serviceRequestActionHandlers.cpp b/src/mme-app/actionHandlers/serviceRequestActionHandlers.cpp
new file mode 100644
index 0000000..3cbe859
--- /dev/null
+++ b/src/mme-app/actionHandlers/serviceRequestActionHandlers.cpp
@@ -0,0 +1,328 @@
+
+/*
+ * Copyright 2019-present Infosys Limited
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/******************************************************************************
+ *
+ * This file has both generated and manual code.
+ *
+ * File template used for code generation:
+ * <TOP-DIR/scripts/SMCodeGen/templates/stateMachineTmpls/actionHandlers.cpp.tt>
+ *
+ ******************************************************************************/
+
+#include <typeinfo>
+#include "actionHandlers/actionHandlers.h"
+#include "controlBlock.h"
+#include "msgType.h"
+#include "contextManager/subsDataGroupManager.h"
+#include "contextManager/dataBlocks.h"
+#include "procedureStats.h"
+#include "log.h"
+#include "secUtils.h"
+#include "state.h"
+#include <string.h>
+#include <sstream>
+#include <smTypes.h>
+#include "common_proc_info.h"
+#include <ipcTypes.h>
+#include <tipcTypes.h>
+#include <msgBuffer.h>
+#include <interfaces/mmeIpcInterface.h>
+#include <event.h>
+#include <stateMachineEngine.h>
+#include <utils/mmeContextManagerUtils.h>
+
+using namespace mme;
+using namespace SM;
+using namespace cmn::utils;
+
+extern MmeIpcInterface* mmeIpcIf_g;
+
+/***************************************
+* Action handler :send_paging_req_to_ue 
+***************************************/
+ActStatus ActionHandlers::send_paging_req_to_ue(ControlBlock& cb)
+{	
+	log_msg(LOG_INFO,"Inside send_paging_req\n");
+
+	UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+	
+	if (ue_ctxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "send_paging_req: ue context is NULL\n");
+		return ActStatus::HALT;
+	}
+	
+	struct paging_req_Q_msg pag_req;
+	pag_req.msg_type = paging_request;
+	pag_req.ue_idx = ue_ctxt->getContextID();
+	pag_req.enb_s1ap_ue_id = ue_ctxt->getS1apEnbUeId();
+	pag_req.enb_fd = ue_ctxt->getEnbFd();
+	pag_req.cn_domain = CN_DOMAIN_PS;
+
+	const DigitRegister15& ueImsi = ue_ctxt->getImsi();
+	ueImsi.convertToBcdArray( pag_req.IMSI );
+	memcpy(&pag_req.tai, &(ue_ctxt->getTai().tai_m), sizeof(struct TAI));
+
+	cmn::ipc::IpcAddress destAddr;
+	destAddr.u32 = TipcServiceInstance::s1apAppInstanceNum_c;
+	mmeIpcIf_g->dispatchIpcMsg((char *) &pag_req, sizeof(pag_req), destAddr);
+
+	ProcedureStats::num_of_ddn_received++;
+
+	log_msg(LOG_INFO,"Leaving send_paging_req\n");
+
+	return ActStatus::PROCEED;
+}
+
+/***************************************
+* Action handler : process_service_request
+***************************************/
+ActStatus ActionHandlers::process_service_request(ControlBlock& cb)
+{
+    log_msg(LOG_DEBUG, "Inside process_service_request \n");
+	
+	UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+
+	if (ue_ctxt == NULL )
+	{
+		log_msg(LOG_DEBUG, "process_service_request: ue ctxt is NULL \n");
+		return ActStatus::HALT;
+	}
+	
+	log_msg(LOG_DEBUG, "Leaving process_service_request \n");
+
+	ProcedureStats::num_of_service_request_received ++;
+
+	return ActStatus::PROCEED;
+}
+
+/***************************************
+* Action handler : send_ddn_ack_to_sgw
+***************************************/
+ActStatus ActionHandlers::send_ddn_ack_to_sgw(ControlBlock& cb)
+{
+    log_msg(LOG_DEBUG, "Inside send_ddn_ack_to_sgw \n");
+		
+	UEContext *ue_ctxt = static_cast<UEContext*>(cb.getPermDataBlock());
+	MmeSvcReqProcedureCtxt* srPrcdCtxt_p = dynamic_cast<MmeSvcReqProcedureCtxt*>(cb.getTempDataBlock());
+	
+	if (ue_ctxt == NULL || srPrcdCtxt_p == NULL)
+	{
+	    log_msg(LOG_DEBUG, "send_ddn_ack_to_sgw: ue ctxt or MmeSvcReqProcedureCtxt is NULL \n");
+	    return ActStatus::HALT;
+	}
+
+	DDN_ACK_Q_msg ddn_ack;
+	ddn_ack.msg_type = ddn_acknowledgement;
+	ddn_ack.ue_idx= ue_ctxt->getContextID();
+	ddn_ack.seq_no= srPrcdCtxt_p->getDdnSeqNo();
+	ddn_ack.cause = 16;
+	
+	cmn::ipc::IpcAddress destAddr;
+	destAddr.u32 = TipcServiceInstance::s11AppInstanceNum_c;
+
+	mmeIpcIf_g->dispatchIpcMsg((char *) &ddn_ack, sizeof(ddn_ack), destAddr);
+	
+	log_msg(LOG_DEBUG, "Leaving send_ddn_ack_to_sgw \n");
+
+	ProcedureStats::num_of_ddn_ack_sent ++;
+	
+	return ActStatus::PROCEED;
+}
+
+/***************************************
+* Action handler : perform_auth_and_sec_check
+***************************************/
+ActStatus ActionHandlers::perform_auth_and_sec_check(ControlBlock& cb)
+{
+    log_msg(LOG_DEBUG, "Inside auth_and_sec_check \n");
+	SM::ControlBlock* controlBlk_p = SubsDataGroupManager::Instance()->findControlBlock(cb.getCBIndex());	
+	UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+	
+	if (ue_ctxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "auth_and_sec_check: ue context is NULL\n");
+		return ActStatus::HALT;
+	}
+	
+	log_msg(LOG_DEBUG, "Leaving auth_and_sec_check \n");
+	
+
+	SM::Event evt(Event_e::AUTH_AND_SEC_CHECK_COMPLETE, NULL);
+
+	controlBlk_p->addEventToProcQ(evt);
+
+	
+	return ActStatus::PROCEED;
+}
+/***************************************************
+* Action handler : send_init_ctxt_req_to_ue_svc_req
+****************************************************/
+ActStatus ActionHandlers::send_init_ctxt_req_to_ue_svc_req(ControlBlock& cb)
+{
+    log_msg(LOG_DEBUG, "Inside send_init_ctxt_req_to_ue_svc_req \n");
+
+        UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+        if (ue_ctxt == NULL )
+        {
+                log_msg(LOG_DEBUG, "send_init_ctxt_req_to_ue_svc_req : ue context is NULL \n");
+                return ActStatus::HALT;
+        }
+
+        SessionContext* sessionCtxt = ue_ctxt->getSessionContext();
+        if (sessionCtxt == NULL)
+        {
+                log_msg(LOG_DEBUG, "send_init_ctxt_req_to_ue_svc_req : session ctxt is NULL \n");
+                return ActStatus::HALT;
+        }
+
+        unsigned int nas_count = 0;
+        E_UTRAN_sec_vector* secVect = const_cast<E_UTRAN_sec_vector*>(ue_ctxt->getAiaSecInfo().AiaSecInfo_mp);
+        secinfo& secInfo = const_cast<secinfo&>(ue_ctxt->getUeSecInfo().secinfo_m);
+
+        SecUtils::create_kenb_key(secVect->kasme.val, secInfo.kenb_key, nas_count);
+
+        ics_req_paging_Q_msg icr_msg;
+        icr_msg.msg_type = ics_req_paging;
+        icr_msg.ue_idx = ue_ctxt->getContextID();
+        icr_msg.enb_fd = ue_ctxt->getEnbFd();
+        icr_msg.enb_s1ap_ue_id = ue_ctxt->getS1apEnbUeId();
+
+        icr_msg.ueag_max_ul_bitrate = (ue_ctxt->getAmbr().ambr_m).max_requested_bw_dl;
+        icr_msg.ueag_max_dl_bitrate = (ue_ctxt->getAmbr().ambr_m).max_requested_bw_ul;
+        BearerContext* bearerCtxt = sessionCtxt->getBearerContext();
+        icr_msg.bearer_id = bearerCtxt->getBearerId();
+
+        
+       	memcpy(&(icr_msg.gtp_teid), &(bearerCtxt->getS1uSgwUserFteid().fteid_m), sizeof(struct fteid));
+        memcpy(&(icr_msg.sec_key), &((ue_ctxt->getUeSecInfo().secinfo_m).kenb_key),
+                        KENB_SIZE);
+
+        //ue_ctxt->setdwnLnkSeqNo(icr_msg.dl_seq_no+1);
+
+        cmn::ipc::IpcAddress destAddr;
+        destAddr.u32 = TipcServiceInstance::s1apAppInstanceNum_c;
+
+        mmeIpcIf_g->dispatchIpcMsg((char *) &icr_msg, sizeof(icr_msg), destAddr);
+
+        ProcedureStats::num_of_init_ctxt_req_to_ue_sent ++;
+        log_msg(LOG_DEBUG, "Leaving send_init_ctxt_req_to_ue_svc_req_ \n");
+
+    	return ActStatus::PROCEED;
+}
+
+/***************************************
+* Action handler : process_init_ctxt_resp_svc_req
+***************************************/
+ActStatus ActionHandlers::process_init_ctxt_resp_svc_req(ControlBlock& cb)
+{
+    	log_msg(LOG_DEBUG, "Inside process_init_ctxt_resp_svc_req \n");
+
+        UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+        MmeProcedureCtxt *procCtxt = dynamic_cast<MmeProcedureCtxt*>(cb.getTempDataBlock());
+
+        if (ue_ctxt == NULL || procCtxt == NULL)
+        {
+                log_msg(LOG_DEBUG, "process_init_ctxt_resp_svc_req: ue context or procedure ctxt is NULL \n");
+                return ActStatus::HALT;
+        }
+
+        SessionContext* sessionCtxt = ue_ctxt->getSessionContext();
+        if (sessionCtxt == NULL)
+        {
+                log_msg(LOG_DEBUG, "process_init_ctxt_resp_svc_req: session ctxt is NULL \n");
+                return ActStatus::HALT;
+        }
+
+        MsgBuffer* msgBuf = static_cast<MsgBuffer*>(cb.getMsgData());
+
+        if (msgBuf == NULL)
+                return ActStatus::HALT;
+
+        const s1_incoming_msg_data_t* s1_msg_data = static_cast<const s1_incoming_msg_data_t*>(msgBuf->getDataPointer());
+        const struct initctx_resp_Q_msg &ics_res =s1_msg_data->msg_data.initctx_resp_Q_msg_m;
+
+        fteid S1uEnbUserFteid;
+        S1uEnbUserFteid.header.iface_type = 0;
+        S1uEnbUserFteid.header.v4 = 1;
+        S1uEnbUserFteid.header.teid_gre = ics_res.gtp_teid;
+        S1uEnbUserFteid.ip.ipv4 = *(struct in_addr*)&ics_res.transp_layer_addr;
+	
+	    BearerContext* bearerCtxt = sessionCtxt->getBearerContext();
+	    if (bearerCtxt)
+	        bearerCtxt->setS1uEnbUserFteid(Fteid(S1uEnbUserFteid));
+
+        ProcedureStats::num_of_processed_init_ctxt_resp ++;
+        log_msg(LOG_DEBUG, "Leaving process_init_ctxt_resp_svc_req \n");
+
+	return ActStatus::PROCEED;
+}
+
+
+/***************************************
+* Action handler : send_mb_req_to_sgw_svc_req
+***************************************/
+ActStatus ActionHandlers::send_mb_req_to_sgw_svc_req(ControlBlock& cb)
+{
+    	log_msg(LOG_DEBUG, "Inside send_mb_req_to_sgw_svc_req \n");
+
+        UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+        MmeProcedureCtxt *procCtxt = dynamic_cast<MmeProcedureCtxt*>(cb.getTempDataBlock());
+
+        if (ue_ctxt == NULL || procCtxt == NULL)
+        {
+                log_msg(LOG_DEBUG, "send_mb_req_to_sgw_svc_req: ue context or procedure ctxt is NULL \n");
+                return ActStatus::HALT;
+        }
+
+        SessionContext* sessionCtxt = ue_ctxt->getSessionContext();
+        if (sessionCtxt == NULL)
+        {
+                log_msg(LOG_DEBUG, "send_mb_req_to_sgw_svc_req: session ctxt is NULL \n");
+                return ActStatus::HALT;
+        }
+
+        struct MB_Q_msg mb_msg;
+        mb_msg.msg_type = modify_bearer_request;
+        mb_msg.ue_idx = ue_ctxt->getContextID();
+
+        memset(mb_msg.indication, 0, S11_MB_INDICATION_FLAG_SIZE); /*TODO : future*/
+        BearerContext* bearerCtxt = sessionCtxt->getBearerContext();
+        mb_msg.bearer_id = bearerCtxt->getBearerId();
+
+        memcpy(&(mb_msg.s11_sgw_c_fteid), &(sessionCtxt->getS11SgwCtrlFteid().fteid_m),
+                sizeof(struct fteid));
+
+        memcpy(&(mb_msg.s1u_enb_fteid), &(bearerCtxt->getS1uEnbUserFteid().fteid_m),
+                sizeof(struct fteid));
+
+
+        cmn::ipc::IpcAddress destAddr;
+        destAddr.u32 = TipcServiceInstance::s11AppInstanceNum_c;
+
+        mmeIpcIf_g->dispatchIpcMsg((char *) &mb_msg, sizeof(mb_msg), destAddr);
+
+        ProcedureStats::num_of_mb_req_to_sgw_sent ++;
+        log_msg(LOG_DEBUG, "Leaving send_mb_req_to_sgw_svc_req \n");
+
+        return ActStatus::PROCEED;
+}
+
+/***************************************
+* Action handler : process_mb_resp_svc_req
+***************************************/
+ActStatus ActionHandlers::process_mb_resp_svc_req(ControlBlock& cb)
+{
+   	log_msg(LOG_DEBUG, "Inside process_mb_resp_svc_req \n");
+
+	ProcedureStats::num_of_processed_mb_resp ++;
+
+	MmeContextManagerUtils::deallocateProcedureCtxt(cb, serviceRequest_c);
+
+	return ActStatus::PROCEED;
+}
diff --git a/src/mme-app/actionHandlers/tauActionHandlers.cpp b/src/mme-app/actionHandlers/tauActionHandlers.cpp
new file mode 100644
index 0000000..6bf70da
--- /dev/null
+++ b/src/mme-app/actionHandlers/tauActionHandlers.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2019-present Infosys Limited
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/******************************************************************************
+ *
+ * This file has both generated and manual code.
+ *
+ * File template used for code generation:
+ * <TOP-DIR/scripts/SMCodeGen/templates/stateMachineTmpls/actionHandlers.cpp.tt>
+ *
+ ******************************************************************************/
+
+#include <typeinfo>
+#include "actionHandlers/actionHandlers.h"
+#include "controlBlock.h" 
+#include "msgType.h"
+#include "contextManager/dataBlocks.h"
+#include "procedureStats.h"
+#include "log.h"
+#include "secUtils.h"
+#include "state.h"
+#include <string.h>
+#include <sstream>
+#include <smTypes.h>
+#include "common_proc_info.h"
+#include <ipcTypes.h>
+#include <tipcTypes.h>
+#include <msgBuffer.h>
+#include <interfaces/mmeIpcInterface.h>
+#include <event.h>
+#include <stateMachineEngine.h>
+#include <utils/mmeContextManagerUtils.h>
+
+using namespace mme;
+using namespace SM;
+using namespace cmn::utils;
+
+extern MmeIpcInterface* mmeIpcIf_g;
+
+/***************************************
+* Action handler : send_tau_response_to_ue
+***************************************/
+ActStatus ActionHandlers::send_tau_response_to_ue(ControlBlock& cb)
+{	
+	log_msg(LOG_INFO,"Inside send_tau_response_to_ue\n");
+
+	UEContext *ue_ctxt = static_cast<UEContext*>(cb.getPermDataBlock());	
+	if (ue_ctxt == NULL)
+	{
+		log_msg(LOG_ERROR, "send_tau_response_to_ue: ue context is NULL\n",cb.getCBIndex());
+		return ActStatus::HALT;
+	}
+	
+	MmeTauProcedureCtxt* tauPrcdCtxt_p = dynamic_cast<MmeTauProcedureCtxt*>(cb.getTempDataBlock());	
+	if (tauPrcdCtxt_p == NULL)
+	{
+		log_msg(LOG_DEBUG, "send_tau_response_to_ue: MmeTauProcedureCtxt is NULL\n");
+		return ActStatus::HALT;
+	}
+	
+	struct tauResp_Q_msg tau_resp;
+
+	tau_resp.msg_type = tau_response;
+	tau_resp.status = 0;
+	tau_resp.ue_idx = ue_ctxt->getContextID();
+	tau_resp.enb_fd = tauPrcdCtxt_p->getEnbFd();
+	tau_resp.s1ap_enb_ue_id = tauPrcdCtxt_p->getS1apEnbUeId();	
+	tau_resp.dl_seq_no = ue_ctxt->getDwnLnkSeqNo();
+	memcpy(&(tau_resp.int_key), &(ue_ctxt->getUeSecInfo().secinfo_m.int_key),
+			NAS_INT_KEY_SIZE);
+	memcpy(&tau_resp.tai, &(ue_ctxt->getTai().tai_m), sizeof(struct TAI));	
+	tau_resp.m_tmsi = ue_ctxt->getMtmsi();
+	
+	cmn::ipc::IpcAddress destAddr;
+        destAddr.u32 = TipcServiceInstance::s1apAppInstanceNum_c;	
+	mmeIpcIf_g->dispatchIpcMsg((char *) &tau_resp, sizeof(tau_resp), destAddr);
+	
+	MmeContextManagerUtils::deallocateProcedureCtxt(cb, tau_c );
+	ProcedureStats::num_of_tau_response_to_ue_sent++;
+
+	log_msg(LOG_INFO,"Leaving send_tau_response_to_ue\n");
+	return ActStatus::PROCEED;
+}
+
diff --git a/src/mme-app/actionHandlers/ueInitDetachActionHandlers.cpp b/src/mme-app/actionHandlers/ueInitDetachActionHandlers.cpp
new file mode 100644
index 0000000..d37c02e
--- /dev/null
+++ b/src/mme-app/actionHandlers/ueInitDetachActionHandlers.cpp
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2019-present Infosys Limited
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/******************************************************************************
+ *
+ * This file has both generated and manual code.
+ *
+ * File template used for code generation:
+ * <TOP-DIR/scripts/SMCodeGen/templates/stateMachineTmpls/actionHandlers.cpp.tt>
+ *
+ ******************************************************************************/
+
+#include "actionHandlers/actionHandlers.h"
+#include "contextManager/subsDataGroupManager.h"
+#include "contextManager/dataBlocks.h"
+#include "msgType.h"
+#include "controlBlock.h"
+#include "procedureStats.h"
+#include "log.h"
+#include <string.h>
+#include <smTypes.h>
+
+#include <ipcTypes.h>
+#include <tipcTypes.h>
+#include <msgBuffer.h>
+#include <interfaces/mmeIpcInterface.h>
+#include <utils/mmeContextManagerUtils.h>
+
+using namespace SM;
+using namespace mme;
+using namespace cmn::utils;
+
+extern MmeIpcInterface* mmeIpcIf_g;
+
+ActStatus ActionHandlers::del_session_req(SM::ControlBlock& cb)
+{
+	log_msg(LOG_DEBUG, "Inside delete_session_req \n");
+		
+	UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+	
+	if (ue_ctxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "delete_session_req: ue context is NULL\n");
+		return ActStatus::HALT;
+	}
+		
+	ue_ctxt->setUpLnkSeqNo(ue_ctxt->getUpLnkSeqNo()+1);
+	
+	struct DS_Q_msg g_ds_msg;
+	g_ds_msg.msg_type = delete_session_request;
+	
+	memset(g_ds_msg.indication, 0, S11_DS_INDICATION_FLAG_SIZE);
+	g_ds_msg.indication[0] = 8; /* TODO : define macro or enum */
+	
+	SessionContext* sessionCtxt = ue_ctxt->getSessionContext();
+	BearerContext* bearerCtxt = sessionCtxt->getBearerContext();
+	g_ds_msg.bearer_id = bearerCtxt->getBearerId();
+
+	memcpy(&(g_ds_msg.s11_sgw_c_fteid), &(sessionCtxt->getS11SgwCtrlFteid().fteid_m), sizeof(struct fteid));
+		
+	/* Send message to S11app in S11q*/
+	cmn::ipc::IpcAddress destAddr;
+	destAddr.u32 = TipcServiceInstance::s11AppInstanceNum_c;
+
+	mmeIpcIf_g->dispatchIpcMsg((char *) &g_ds_msg, sizeof(g_ds_msg), destAddr);
+	
+	log_msg(LOG_DEBUG, "Leaving delete_session_req \n");
+	ProcedureStats::num_of_del_session_req_sent ++;	
+	return ActStatus::PROCEED;
+
+}
+#if 0	
+ActStatus ActionHandlers::purge_req(SM::ControlBlock& cb)
+{
+	log_msg(LOG_DEBUG, "Inside purge_req \n");
+	UEContext *ue_ctxt =  dynamic_cast<UEContext*>(cb.getPermDataBlock());
+	
+	if (ue_ctxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "purge_req: ue context is NULL\n");
+		return ActStatus::HALT;
+	}
+	
+	s6a_purge_Q_msg g_purge_msg;
+	
+	g_purge_msg.ue_idx = ue_ctxt->getContextId();
+	memcpy(g_purge_msg.IMSI, ue_ctxt->getIMSIInfo(), BINARY_IMSI_LEN);
+		
+	/* Send message to S6app in S6q*/
+	mmeS6If_gp->sendMessage_v((char*)(&g_purge_msg), purge_request);
+	
+	
+	log_msg(LOG_DEBUG, "Leaving purge_req \n");
+	ProcedureStats::num_of_purge_req_sent ++;
+	return ActStatus::PROCEED;
+	
+}
+#endif
+
+ActStatus ActionHandlers::process_del_session_resp(SM::ControlBlock& cb)
+{
+	log_msg(LOG_DEBUG, "Inside handle_delete_session_resp \n");
+	
+	UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
+	if (ue_ctxt == NULL)
+	{
+	    log_msg(LOG_DEBUG, "delete_session_req: ue context is NULL\n");
+	    return ActStatus::HALT;
+	}
+
+	SessionContext* sessionCtxt = ue_ctxt->getSessionContext();
+	if (sessionCtxt != NULL)
+	{
+	    BearerContext* bearerCtxt = sessionCtxt->getBearerContext();
+	    if (bearerCtxt)
+	    {
+	        SubsDataGroupManager::Instance()->deleteBearerContext( bearerCtxt );
+	    }
+	    SubsDataGroupManager::Instance()->deleteSessionContext( sessionCtxt );
+	}
+
+	ue_ctxt->setSessionContext(NULL);
+	
+	log_msg(LOG_DEBUG, "Leaving handle_delete_session_resp \n");
+	ProcedureStats::num_of_processed_del_session_resp ++;
+	return ActStatus::PROCEED;
+	
+}
+
+#if 0
+ActStatus ActionHandlers::process_pur_resp(SM::ControlBlock& cb)
+{
+	log_msg(LOG_DEBUG, "Inside handle_purge_resp \n");
+	
+	UEContext *ue_ctxt =  dynamic_cast<UEContext*>(cb.getPermDataBlock());
+	
+	if (ue_ctxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "handle_purge_resp: ue context is NULL \n");
+		return ActStatus::HALT;
+	}
+	//struct purge_resp_Q_msg *purge_msg = nullptr;
+	
+	/*Nothing is been done. Only takes the UE Index
+	 * increment the stats counter and changes the state*/
+	
+	
+	log_msg(LOG_DEBUG, "Leaving handle_purge_resp for UE-%d.\n", ue_ctxt->getContextId());
+	ProcedureStats::num_of_processed_pur_resp ++;
+	return ActStatus::PROCEED;
+	
+}
+#endif
+ActStatus ActionHandlers::detach_accept_to_ue(SM::ControlBlock& cb)
+{
+	log_msg(LOG_DEBUG, "Inside send_detach_accept \n");
+	
+	UEContext *ue_ctxt =  dynamic_cast<UEContext*>(cb.getPermDataBlock());
+	
+	if (ue_ctxt == NULL)
+	{
+		log_msg(LOG_DEBUG, "send_detach_accept: ue context is NULL\n");
+		return ActStatus::HALT;
+	}
+	
+	detach_accept_Q_msg detach_accpt;
+	detach_accpt.msg_type = detach_accept;
+	detach_accpt.enb_fd = ue_ctxt->getEnbFd();
+	detach_accpt.ue_idx = ue_ctxt->getContextID();
+	detach_accpt.enb_s1ap_ue_id =  ue_ctxt->getS1apEnbUeId();
+	
+	ue_ctxt->setDwnLnkSeqNo(ue_ctxt->getDwnLnkSeqNo()+1);
+	detach_accpt.dl_seq_no = ue_ctxt->getDwnLnkSeqNo();
+	
+	memcpy(&(detach_accpt.int_key), &(ue_ctxt->getUeSecInfo().secinfo_m.int_key), NAS_INT_KEY_SIZE);
+	
+	/* Send message to S11app in S11q*/
+	cmn::ipc::IpcAddress destAddr;
+	destAddr.u32 = TipcServiceInstance::s1apAppInstanceNum_c;
+
+	mmeIpcIf_g->dispatchIpcMsg((char *) &detach_accpt, sizeof(detach_accpt), destAddr);
+	
+	MmeContextManagerUtils::deallocateProcedureCtxt(cb, detach_c );
+
+	MmContext* mmCtxt = ue_ctxt->getMmContext();
+	mmCtxt->setMmState( EpsDetached );
+
+	log_msg(LOG_DEBUG, "Leaving send_detach_accept for UE \n");
+
+	ProcedureStats::num_of_detach_accept_to_ue_sent ++;
+	ProcedureStats::num_of_subscribers_attached --;
+
+	return ActStatus::PROCEED;
+	
+}