| /* |
| * 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; |
| } |
| |