/******************************************************************************/
// @copyright   Copyright Notification
//   No part may be reproduced except as authorized by written permission.
//   The copyright and the foregoing restriction extend to reproduction in all media.
//   (c) 2023, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TSDSI, TTA, TTC).
//   All rights reserved.
// @version: IWD_23wk37
// $Date: 2023-09-14 09:54:06 +0200 (Thu, 14 Sep 2023) $
// $Rev: 37128 $
/******************************************************************************/

module NG_NAS_Common {

  import from CommonDefs all;
  import from NAS_CommonTypeDefs all;
  import from NG_NAS_TypeDefs all;
  import from NAS_AuxiliaryDefsAndFunctions all;
  import from NAS_CommonTemplates all;
  import from Parameters all;
  import from CommonIP all;
  import from LoopbackIP_PacketFilterTest all;

  type record GMM_MobilityInfo_Type {                                /* structured type to be stored & passed in/out of GMM Msgs
                                                                      @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
    NG_MobileIdentity           Guti,
    NG_GMM_Cap                  GMMCap              optional,
    NG_UE_SecurityCapability    UECap               optional,
    UE_NetworkCap               S1NwkCap            optional,
    PDU_SessionStatus           SessionStatus       optional,
    EPS_BearerContextStatus     EPSBearerStatus     optional,        // @sic R5-206426 sic@
    UERadioCapId                UERadioCapId        optional         // @sic R5-206419 sic@
  } with {
    variant "FIELDORDER(msb)";
  };

  type record GSM_MobilityInfo_Type {                                /* structured type to be stored & passed in/out of GSM Msgs
                                                                      @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
    O1_Type                         SessionId,  // @sic R5s200564 sic@
    ProcedureTransactionIdentifier  PTI,
    PDU_PDN_DNN_Type                PDUType,    // @sic R5-206296 sic@
    B3_Type                         SessionType optional,
    DNN                             DNN         optional,
    AlwaysOnPDUSessionInd           AlwaysOn    optional,
    ExtdProtocolConfigOptions       PCO         optional,
    integer                         EPS_Bearer  optional,   // @sic R5s201094 sic@
    PDN_Index_Type                  PdnIndex    optional,   // @sic R5s201094 sic@
    S_NSSAI_Type                    NSSAI       optional    // @sic R5s210148 sic@
  } with {
    variant "FIELDORDER(msb)";
  };

  type record of GSM_MobilityInfo_Type PDUSessionInfoList_Type;         /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */

  type enumerated DeleteNSSAI_Type {Delete_Default_Configured, Delete_Configured, Delete_Allowed}; /* @status    APPROVED (NR5GC) */

  const ExtdProtocolDiscriminator tsc_EPD_GMM := '01111110'B; // from 24.007       /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  const ExtdProtocolDiscriminator tsc_EPD_GSM := '00101110'B; // from 24.007       /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */

  // NAS message types acc. 24.501 cl.9.7
  const MessageType tsc_MT_NG_RegistrationRequest         := '01000001'B;       /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  const MessageType tsc_MT_NG_RegistrationAccept          := '01000010'B;       /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  const MessageType tsc_MT_NG_RegistrationComplete        := '01000011'B;       /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  const MessageType tsc_MT_NG_RegistrationReject          := '01000100'B;       /* @status    APPROVED (NR5GC, NR5GC_IRAT) */
  const MessageType tsc_MT_NG_DeregistrationRequest_MO    := '01000101'B;       /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  const MessageType tsc_MT_NG_DeregistrationAccept_MO     := '01000110'B;       /* @status    APPROVED (NR5GC) */
  const MessageType tsc_MT_NG_DeregistrationRequest_MT    := '01000111'B;       /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  const MessageType tsc_MT_NG_DeregistrationAccept_MT     := '01001000'B;       /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  const MessageType tsc_MT_NG_ServiceRequest              := '01001100'B;       /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  const MessageType tsc_MT_NG_ServiceReject               := '01001101'B;       /* @status    APPROVED (NR5GC) */
  const MessageType tsc_MT_NG_ServiceAccept               := '01001110'B;       /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  const MessageType tsc_MT_NG_CP_Service_Request          := '01001111'B;
  const MessageType tsc_MT_NG_NetworkSliceSpecificAuthenticationCommand := '01010000'B;       /* @status    APPROVED (NR5GC) */
  const MessageType tsc_MT_NG_NetworkSliceSpecificAuthenticationComplete:= '01010001'B;       /* @status    APPROVED (NR5GC) */
  const MessageType tsc_MT_NG_NetworkSliceSpecificAuthenticationResult  := '01010010'B;       /* @status    APPROVED (NR5GC) */
  const MessageType tsc_MT_NG_ConfigurationUpdateCommand  := '01010100'B;       /* @status    APPROVED (NR5GC) */
  const MessageType tsc_MT_NG_ConfigurationUpdateComplete := '01010101'B;       /* @status    APPROVED (NR5GC) */
  const MessageType tsc_MT_NG_AuthenticationRequest       := '01010110'B;       /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  const MessageType tsc_MT_NG_AuthenticationResponse      := '01010111'B;       /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  const MessageType tsc_MT_NG_AuthenticationReject        := '01011000'B;       /* @status    APPROVED (NR5GC) */
  const MessageType tsc_MT_NG_AuthenticationFailure       := '01011001'B;       /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  const MessageType tsc_MT_NG_AuthenticationResult        := '01011010'B;       /* @status    APPROVED (NR5GC) */
  const MessageType tsc_MT_NG_IdentityRequest             := '01011011'B;       /* @status    APPROVED (NR5GC) */
  const MessageType tsc_MT_NG_IdentityResponse            := '01011100'B;       /* @status    APPROVED (NR5GC) */
  const MessageType tsc_MT_NG_SecurityModeCommand         := '01011101'B;       /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  const MessageType tsc_MT_NG_SecurityModeComplete        := '01011110'B;       /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  const MessageType tsc_MT_NG_SecurityModeReject          := '01011111'B;       /* @status    APPROVED (NR5GC) */
  const MessageType tsc_MT_NG_GMM_Status                  := '01100100'B;       /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  const MessageType tsc_MT_NG_Notification                := '01100101'B;
  const MessageType tsc_MT_NG_NotificationResponse        := '01100110'B;
  const MessageType tsc_MT_NG_UL_NASTransport             := '01100111'B;       /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  const MessageType tsc_MT_NG_DL_NASTransport             := '01101000'B;       /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */

  const MessageType tsc_MT_NG_PDUSessionEstablishmentRequest  := '11000001'B;   /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  const MessageType tsc_MT_NG_PDUSessionEstablishmentAccept   := '11000010'B;   /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  const MessageType tsc_MT_NG_PDUSessionEstablishmentReject   := '11000011'B;   /* @status    APPROVED (NR5GC) */
  const MessageType tsc_MT_NG_PDUSessionAuthenticationCommand := '11000101'B;     /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  const MessageType tsc_MT_NG_PDUSessionAuthenticationComplete:= '11000110'B;     /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  const MessageType tsc_MT_NG_PDUSessionAuthenticationResult  := '11000111'B;     /* @status    APPROVED (NR5GC) */
  const MessageType tsc_MT_NG_PDUSessionModificationRequest   := '11001001'B;     /* @status    APPROVED (NR5GC, NR5GC_IRAT) */
  const MessageType tsc_MT_NG_PDUSessionModificationReject    := '11001010'B;
  const MessageType tsc_MT_NG_PDUSessionModificationCommand   := '11001011'B;     /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT) */
  const MessageType tsc_MT_NG_PDUSessionModificationComplete  := '11001100'B;     /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT) */
  const MessageType tsc_MT_NG_PDUSessionModificationCommandReject := '11001101'B; /* @status    APPROVED (NR5GC) */
  const MessageType tsc_MT_NG_PDUSessionReleaseRequest        := '11010001'B;     /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  const MessageType tsc_MT_NG_PDUSessionReleaseReject         := '11010010'B;
  const MessageType tsc_MT_NG_PDUSessionReleaseCommand        := '11010011'B;     /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  const MessageType tsc_MT_NG_PDUSessionReleaseComplete       := '11010100'B;     /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  const MessageType tsc_MT_NG_GSM_Status                      := '11010110'B;     /* @status    APPROVED (NR5GC) */

  const MessageType tsc_MsgType_NSSAI_DeleteReq         := '10100110'B; /* @sic R5-201207 sic@
                                                                           @status    APPROVED (NR5GC) */
  const MessageType tsc_MsgType_NSSAI_DeleteResp        := '10100111'B; /* @sic R5s200339 sic@
                                                                           @status    APPROVED (NR5GC) */
  const MessageType tsc_MsgType_SetUAIReq         := '10101000'B;   /* @status    APPROVED (NR5GC) */
  const MessageType tsc_MsgType_SetUAIResp        := '10101001'B;   /* @status    APPROVED (NR5GC) */

  const B8_Type tsc_DeleteNSSAI_DefaultConfiguredNSSAI := '00000000'B; /* @status    APPROVED (NR5GC) */
  const B8_Type tsc_DeleteNSSAI_ConfiguredNSSAI := '00000001'B; /* @sic R5s200339 sic@
                                                                   @status    APPROVED (NR5GC) */
  const B8_Type tsc_DeleteNSSAI_AllowedNSSAI := '00000010'B; /* @sic R5s200339 sic@
                                                                @status    APPROVED (NR5GC) */

  type enumerated TypeOfRegistration_Type {Initial_NoSecurity, Initial_Secure, Mobility, Periodic, Emergency, SNPN_Onboarding};                             /* @sic R5-233987 sic@ @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  type enumerated RegistrationAccessType {Access_3GPP, Non3GPP, Both_3GPP_Non3GPP};                                                        /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  type enumerated NG_ALL_STATE_Type {STATE_OFF_0A, STATE_OFF_0B, STATE_IDLE_1A, STATE_INACTIVE_2A, STATE_CONNECTED_3A, STATE_CONNECTED_3A_T3540,     /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
                                 STATE_DEREGISTERED, STATE_EMERGENCY_RELEASE_CONNECTED, STATE_EMERGENCY_RELEASE_IDLE};  // Used for Postamble @sic R5-214620 sic@
  type NG_ALL_STATE_Type NG_STATE_Type (STATE_OFF_0A, STATE_OFF_0B, STATE_IDLE_1A, STATE_INACTIVE_2A, STATE_CONNECTED_3A, STATE_CONNECTED_3A_T3540); // Used for Preamble   /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */

  const B3_Type tsc_NG_RegistrationInitial := '001'B;           /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  const B3_Type tsc_NG_RegistrationMobility := '010'B;          /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  const B3_Type tsc_NG_RegistrationPeriodic := '011'B;          /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  const B3_Type tsc_NG_RegistrationEmergency := '100'B;         /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  const B3_Type tsc_NG_RegistrationSNPN := '101'B;              /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  const B3_Type tsc_NG_RegResult_3GPP := '001'B;                /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  const B3_Type tsc_NG_RegResult_Non3GPP := '010'B;             /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  const B3_Type tsc_NG_RegResult_Both := '011'B;                /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */

  const B4_Type tsc_PayloadContainerSMSMsg := '0010'B;          /* @status    APPROVED (NR5GC) */
  const B4_Type tsc_PayloadContainerLPPMsg := '0011'B;          /* @status    APPROVED (POS) */
  const B4_Type tsc_PayloadContainerSORMsg := '0100'B;          /* @status    APPROVED (NR5GC) */
  const B4_Type tsc_PayloadContainerUEPolicyMsg := '0101'B;
  const B4_Type tsc_PayloadContainerCIoTUserData := '1000'B;    /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */

  const O1_Type tsc_QoSFlowParameter_5QI        := '01'O;       /* @status    APPROVED (ENDC, IMS, NR5GC, NR5GC_IRAT, POS) */
  const O1_Type tsc_QoSFlowParameter_GFBR_UL    := '02'O;       /* @status    APPROVED (ENDC, IMS, NR5GC, NR5GC_IRAT, POS) */
  const O1_Type tsc_QoSFlowParameter_GFBR_DL    := '03'O;       /* @status    APPROVED (ENDC, IMS, NR5GC, NR5GC_IRAT, POS) */
  const O1_Type tsc_QoSFlowParameter_MFBR_UL    := '04'O;       /* @status    APPROVED (ENDC, IMS, NR5GC, NR5GC_IRAT, POS) */
  const O1_Type tsc_QoSFlowParameter_MFBR_DL    := '05'O;       /* @status    APPROVED (ENDC, IMS, NR5GC, NR5GC_IRAT, POS) */
  const O1_Type tsc_QoSFlowParameter_AvWindow   := '06'O;
  const O1_Type tsc_QoSFlowParameter_EPSBearerId := '07'O;  /* @status    APPROVED (ENDC, IMS, NR5GC, NR5GC_IRAT, POS) */

  type enumerated NG_NAS_NumOfPLMN_Type {NG_AllCellsOnSamePLMN, NG_CellsOnDifferentPLMN};       /* @status    APPROVED (NR5GC, NR5GC_IRAT) */

  const B32_Type tsc_NG_TMSI1 := oct2bit('C2345678'O);          /* Maps to EUTRA M-TMSI
                                                                   @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */

  const NAS_IdType tsc_IdType_NG_Noidentity   := '000'B;        /* @status    APPROVED (NR5GC) */
  const NAS_IdType tsc_IdType_NG_SUCI   := '001'B;              /* @status    APPROVED (NR5GC) */
  const NAS_IdType tsc_IdType_NG_GUTI   := '010'B;              /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  const NAS_IdType tsc_IdType_NG_IMEI   := '011'B;              /* @status    APPROVED (NR5GC) */
  const NAS_IdType tsc_IdType_NG_STMSI   := '100'B;             /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
  const NAS_IdType tsc_IdType_NG_IMEISV   := '101'B;            /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */

  const NAS_CauseValue_Type tsc_NR5GCCause_ServNetNotAuthorized             := '01001001'B;    /* @status    APPROVED (NR5GC) */
  const NAS_CauseValue_Type tsc_NR5GCCause_InvalidPDUSessionIdentity        := '00101011'B;    /* @status    APPROVED (NR5GC) */
  const NAS_CauseValue_Type tsc_NR5GCCause_NoSuitableCellsInTA              := '00001111'B;    /* @status    APPROVED (NR5GC) */
  const NAS_CauseValue_Type tsc_NR5GCCause_Congestion                       := '00010110'B; /* @status    APPROVED (NR5GC) */

  type record NG_NAS_GutiParameters_Type {                      /* to be stored in component
                                                                   @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
    B8_Type         AMF_RegionId,
    B10_Type        AMF_SetId,
    B6_Type         AMF_Pointer,
    B32_Type        NG_TMSI
  };

  template (value) NG_PacketFilter_Type2 cs_PacketFilter_RemoteAddress (B4_Type p_Id, octetstring p_Component) :=
  { /* @status    APPROVED (ENDC, IMS, NR5GC, NR5GC_IRAT, POS) */
     spare          := tsc_Spare2,
     direction      := '11'B,       // bi-directional
     packetFilterId := p_Id,
     len            := int2oct(lengthof(p_Component), 1),
     contents       := p_Component
  };

  template (value) QoS_Rule cs_QoS_RuleRemoteAccess (O1_Type p_Id,
                                         B1_Type p_DQR,
                                         O1_Type p_Precedence,
                                         B6_Type p_FlowId,
                                         octetstring p_Component,
                                         O2_Type p_Length,
                                         B4_Type p_FilterId) :=
   { /* @status    APPROVED (ENDC, IMS, NR5GC, NR5GC_IRAT, POS) */
    identifier          := p_Id,
    iel                 := p_Length,
    u := {
      creat := {
        ruleOperationCode   := '001'B,
        dqrBit              := p_DQR,
        numOfPacketFilters  := '0001'B,
        packetFilterList    := { cs_PacketFilter_RemoteAddress (p_FilterId, p_Component) },
        precedence          := p_Precedence,
        spare               := tsc_Spare1,
        segregation         := tsc_Spare1,
        flowIdentifier      := p_FlowId
      }
    }
  };

  template (value) NG_NAS_GutiParameters_Type cs_NG_NAS_GutiParameters(B8_Type p_AMF_RegionId,
                                                                       B32_Type p_NG_TMSI) :=
  { // to be stored in component
    /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
    AMF_RegionId    := p_AMF_RegionId,
    AMF_SetId       := int2bit(1, 10),
    AMF_Pointer     := int2bit(1,6),
    NG_TMSI         := p_NG_TMSI
  };

  template (value) NG_MobileIdentity cs_NG_MobileIdentity_Guti(template (omit) IEI8_Type p_IEI,
                                                               octetstring p_Guti) :=
  { /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
    iei         := p_IEI,
    iel         := int2oct(lengthof(p_Guti) + 1, 2),    // 11 octets in case of GUTI
    idDigit1    := '1111'B,                             // in case of the GUTI
    oddEvenInd  := '0'B,                                // in case of the GUTI
    typeOfId := tsc_IdType_NG_GUTI,
    otherDigits := p_Guti
  };

  template (value) NG_MobileIdentity cs_NG_MobileIdentity_STMSI(template (omit) IEI8_Type p_IEI,
                                                        octetstring p_Guti) :=
  { /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
    iei         := p_IEI,
    iel         := int2oct(lengthof(p_Guti) + 1, 2),    // 11 octets in case of GUTI
    idDigit1    := '1111'B,                             // in case of the GUTI
    oddEvenInd  := '0'B,                                // in case of the GUTI
    typeOfId := tsc_IdType_NG_STMSI,
    otherDigits := p_Guti
  };

  template (value) NG_MobileIdentity cs_NG_MobileIdentitySUCI(template (value) B4_Type p_SUPIFormat,
                                                              template (value) octetstring p_OtherDigits) :=
  { /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
      iei         := omit,
      iel         := int2oct(1+lengthof(p_OtherDigits), 2),              // @sic R5s190719 sic@
      idDigit1    := p_SUPIFormat,                      // 4 bits
      oddEvenInd  := '0'B,                              // 1 bit
      typeOfId    := tsc_IdType_NG_SUCI,                // 3 bits
      otherDigits := p_OtherDigits
  };

  template (present) NG_MobileIdentity cr_NG_MobileIdentity_TypeOfId(template (present) B4_Type p_FirstDigit,
                                                                     template (present) B1_Type p_OddEvenInd,
                                                                     template (present) octetstring p_OtherDigits,
                                                                     template (present) NAS_IdType p_TypeOfId := tsc_IdType_NG_IMEISV
                                                                     ) :=
  { /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
    iei         := omit,
    iel         := ?,                                 // @sic R5s190719 sic@
    idDigit1    := p_FirstDigit,                      // 4 bits
    oddEvenInd  := p_OddEvenInd,                      // 1 bit
    typeOfId    := p_TypeOfId,                        // 3 bits
    otherDigits := p_OtherDigits
  };

  template (present) NG_MobileIdentity cr_NG_MobileIdentitySUCI(template (present) B4_Type p_SUPIFormat,
                                                                template (present) octetstring p_OtherDigits) :=
  { /* @status    APPROVED (NR5GC) */
    iei         := omit,
    iel         := ?,                                 // @sic R5s190719 sic@
    idDigit1    := p_SUPIFormat,                      // 4 bits
    oddEvenInd  := '0'B,                              // 1 bit
    typeOfId    := tsc_IdType_NG_SUCI,                // 3 bits
    otherDigits := p_OtherDigits
  };

  template (present) NG_MobileIdentity cr_NG_MobileIdentityNoIdentity :=
  { /* @status    APPROVED (NR5GC) */
    iei         := omit,
    iel         := '0001'O,
    idDigit1    := tsc_Spare4,                        // 4 bits
    oddEvenInd  := tsc_Spare1,                        // 1 bit
    typeOfId    := tsc_IdType_NG_Noidentity,                // 3 bits
    otherDigits := omit
  };

  //------------------------------------------------------------------------------------------
  /*
   * @desc      convert from  PLMN and GutiParameters_Type to NAS NG_MobileIdentity
   * @param     p_NasPLMN
   * @param     p_GutiParams
   * @param     p_IEI               (default value: '77'O)
   * @return    template (value) NG_MobileIdentity
   * @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS)
   */
  function f_NG_GutiParameters2MobileIdentity(NAS_PlmnId p_NasPLMN,
                                              NG_NAS_GutiParameters_Type p_GutiParams,
                                              template (omit) IEI8_Type p_IEI := '77'O) return template (value) NG_MobileIdentity
  {
    var bitstring v_AMFId := p_GutiParams.AMF_RegionId & p_GutiParams.AMF_SetId & p_GutiParams.AMF_Pointer;
    var octetstring v_GutiString := p_NasPLMN & bit2oct(v_AMFId) & bit2oct(p_GutiParams.NG_TMSI);
    return cs_NG_MobileIdentity_Guti(p_IEI, v_GutiString);
  }

  //------------------------------------------------------------------------------------------
  /*
   * @desc      convert from GutiParameters_Type to NAS NG_MobileIdentity
   * @param     p_IEI
   * @param     p_GutiParams
   * @return    template (value) NG_MobileIdentity
   * @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS)
   */
  function f_NG_S_TMSI2MobileIdentity(template (omit) IEI8_Type p_IEI,
                                      NG_NAS_GutiParameters_Type p_GutiParams) return template (value) NG_MobileIdentity
  {
    var bitstring v_AMFId := p_GutiParams.AMF_SetId & p_GutiParams.AMF_Pointer;
    var octetstring v_STMSIString := bit2oct(v_AMFId) & bit2oct(p_GutiParams.NG_TMSI);
    return cs_NG_MobileIdentity_STMSI(p_IEI, v_STMSIString);
  }

  //----------------------------------------------------------------------------
  /*
   * @desc      Convert from IMEISV of type hexstring to NAS NG_MobileIdentity
   * @param     p_IMEISV
   * @return    template (present) NG_MobileIdentity
   * @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS)
   */
  function f_NG_Imeisv2MobileIdentity(hexstring p_IMEISV) return template (present) NG_MobileIdentity
  {
    var integer v_ImeiLength := lengthof(p_IMEISV);
    var integer v_Odd := (v_ImeiLength rem 2);
    var octetstring v_Other  := f_ImsiImei2Octetstring (p_IMEISV);
    var B4_Type v_FirstDigit := hex2bit(p_IMEISV[0]);
    var B1_Type v_OddEvenInd := int2bit(v_Odd, 1);

    return cr_NG_MobileIdentity_TypeOfId(v_FirstDigit, v_OddEvenInd, v_Other);
  }

  //----------------------------------------------------------------------------
  /*
   * @desc      To convert the RejectedS_NSSAI into a charstring for the AT command
   * @param     p_S_NSSAI
   * @return    charstring
   * @status    APPROVED (NR5GC)
   */
  function f_ConvertRejectedS_NSSAI_ForATCommand(template (value) RejectedS_NSSAI p_S_NSSAI) return charstring
  {
    var RejectedS_NSSAI v_S_NSSAI := valueof(p_S_NSSAI);
    var charstring v_S_NSSAIstring := "";

    v_S_NSSAIstring := oct2str(v_S_NSSAI.sst);
    if (ispresent(v_S_NSSAI.sd)) {
      v_S_NSSAIstring := v_S_NSSAIstring & "." & oct2str(v_S_NSSAI.sd);
    }
    v_S_NSSAIstring := v_S_NSSAIstring & "#" & int2str(bit2int(v_S_NSSAI.causeValue)); // @sic R5s201142 sic@
    return v_S_NSSAIstring;
  }

  /*
   * @desc      To convert the NSSAI (list of S_NSSAI_Type) into a charstring for the AT command
   * @param     p_NSSAI
   * @return    charstring
   * @status    APPROVED (NR5GC)
   */
  function f_Convert_ListOfRejectedNSSAI_ForATCommand(template (value) RejectedNSSAI p_NSSAI) return charstring
  {
    var integer i;
    var integer v_Length := lengthof(p_NSSAI.rejectS_NSSAI);
    var charstring v_ListOfNSSAI := "";
    var charstring v_S_NSSAI := "";

    for (i := 0; i < v_Length; i := i+1) {
      v_S_NSSAI := f_ConvertRejectedS_NSSAI_ForATCommand(p_NSSAI.rejectS_NSSAI[i]);
      v_ListOfNSSAI := v_ListOfNSSAI & v_S_NSSAI;
      if (i < (v_Length-1)) { // add a colon to all but the last one
        v_ListOfNSSAI := v_ListOfNSSAI & ":";
      }
    }
    return v_ListOfNSSAI;
  }

  /*
   * @desc      To convert the NSSAI (list of ExtdRejectedNSSAI) into a charstring for the MMI command
   * @param     p_NSSAI
   * @return    charstring
   */
  function f_Convert_ListOfExtdRejectedNSSAI_ForMMICommand(template (value) ExtdRejectedNSSAI p_NSSAI) return charstring
  {
    var integer i;
    var integer v_Length := lengthof(p_NSSAI.partialXtd);
    var charstring v_ListOfNSSAI := "";
    var charstring v_S_NSSAI := "";

    for (i := 0; i < v_Length; i := i+1) {
      v_S_NSSAI := f_ConvertPartialXtdRejectedS_NSSAI_ForMMICommand(p_NSSAI.partialXtd[i]);
      v_ListOfNSSAI := v_ListOfNSSAI & v_S_NSSAI;
      if (i < (v_Length-1)) { // add a colon to all but the last one
        v_ListOfNSSAI := v_ListOfNSSAI & ":";
      }
    }
    return v_ListOfNSSAI;
  }

  /*
   * @desc      To convert the PartialXtdRejectedNSSAI into a charstring for the AT command
   * @param     p_Partial_NSSAI
   * @return    charstring
   */
  function f_ConvertPartialXtdRejectedS_NSSAI_ForMMICommand(template (value) PartialXtdRejectedNSSAI p_Partial_NSSAI) return charstring
  {
    var PartialXtdRejectedNSSAI v_Partial_NSSAI := valueof(p_Partial_NSSAI);
    var XtdRejectedS_NSSAI_List v_Xtd_List;
    var XtdRejectedS_NSSAI v_XtdRejectedS_NSSAI;
    var integer v_NumOfElements;
    var integer i;
    var charstring v_S_NSSAIstring := "";

    if (ischosen (v_Partial_NSSAI.type0)) {
      v_NumOfElements := bit2int(v_Partial_NSSAI.type0.numOfElements);
      v_Xtd_List := v_Partial_NSSAI.type0.rejectS_NSSAI;
    } else {  // must be type 1
      // ignore extra field: back off timer
      v_NumOfElements := bit2int(v_Partial_NSSAI.type1.numOfElements);
      v_Xtd_List := v_Partial_NSSAI.type1.rejectS_NSSAI;
    }

    for (i := 0; i < v_NumOfElements; i := i+1) {
      v_XtdRejectedS_NSSAI := v_Xtd_List[i];
      v_S_NSSAIstring := v_S_NSSAIstring & f_ConvertXtdRejectedS_NSSAI_ForMMICommand(v_XtdRejectedS_NSSAI);
      if (i < (v_NumOfElements-1)) { // add a colon to all but the last one
        v_S_NSSAIstring := v_S_NSSAIstring & ":";
      }
    }
    return v_S_NSSAIstring;
  }

  /*
   * @desc      To convert the XtdRejectedS_NSSAI into a charstring for the AT command
   * @param     p_Xtd_NSSAI
   * @return    charstring
   */
  function f_ConvertXtdRejectedS_NSSAI_ForMMICommand(XtdRejectedS_NSSAI p_Xtd_NSSAI) return charstring
  {
    var charstring v_S_NSSAIstring := "";

    v_S_NSSAIstring := f_ConvertS_NSSAI_VForMMICommand(p_Xtd_NSSAI.snssai);
    v_S_NSSAIstring := v_S_NSSAIstring & "#" & int2str(bit2int(p_Xtd_NSSAI.causeValue));
    return v_S_NSSAIstring;
  }

  /*
   * @desc      To convert the S_NSSAI_V into a charstring for the AT command
   * @param     p_S_NSSAI
   * @return    charstring
   */
  function f_ConvertS_NSSAI_VForMMICommand(S_NSSAI_V p_S_NSSAI) return charstring
  {
    var charstring v_S_NSSAIstring := "";

    v_S_NSSAIstring := oct2str(p_S_NSSAI.sst);
    if (ispresent(p_S_NSSAI.sd)) {
      v_S_NSSAIstring := v_S_NSSAIstring & "." & oct2str(p_S_NSSAI.sd);
    }
    if (ispresent(p_S_NSSAI.mappedSST)) {
      v_S_NSSAIstring := v_S_NSSAIstring & "." & oct2str(p_S_NSSAI.mappedSST);
    }
    if (ispresent(p_S_NSSAI.mappedSD)) {
      v_S_NSSAIstring := v_S_NSSAIstring & "." & oct2str(p_S_NSSAI.mappedSD);
    }
    return v_S_NSSAIstring;
  }

  /*
   * @desc      To convert the S_NSSAI into a charstring for the AT command
   * @param     p_S_NSSAI
   * @return    charstring
   * @status    APPROVED (IMS, NR5GC)
   */
  function f_ConvertS_NSSAI_ForATCommand(template (value) S_NSSAI_LV p_S_NSSAI) return charstring
  {
    var S_NSSAI_LV v_S_NSSAI := valueof(p_S_NSSAI);
    var charstring v_S_NSSAIstring := "";

    v_S_NSSAIstring := oct2str(v_S_NSSAI.vPart.sst); // @sic R5s221179 Baseline Moving sic@
    if (ispresent(v_S_NSSAI.vPart.sd)) {
      v_S_NSSAIstring := v_S_NSSAIstring & "." & oct2str(v_S_NSSAI.vPart.sd); // @sic R5s221179 Baseline Moving sic@
    }
    if (ispresent(v_S_NSSAI.vPart.mappedSST)) {
      v_S_NSSAIstring := v_S_NSSAIstring & ";" & oct2str(v_S_NSSAI.vPart.mappedSST);  // @sic R5s221179 Baseline Moving sic@
    }
    if (ispresent(v_S_NSSAI.vPart.mappedSD)) {
      v_S_NSSAIstring := v_S_NSSAIstring & "." & oct2str(v_S_NSSAI.vPart.mappedSD);  // @sic R5s221179 Baseline Moving sic@
    }
    return v_S_NSSAIstring;
  }

  /*
   * @desc      To convert the NSSAI (list of S_NSSAI_Type) into a charstring for the AT command
   * @param     p_NSSAI
   * @return    charstring
   * @status    APPROVED (NR5GC)
   */
  function f_Convert_ListOfNSSAI_ForATCommand(template (value) NSSAI p_NSSAI) return charstring
  {
    var integer i;
    var integer v_Length := lengthof(p_NSSAI.lvPart.s_nssai);   // @sic R5s221179 Baseline Moving sic@
    var charstring v_ListOfNSSAI := "";
    var charstring v_S_NSSAI := "";

    for (i := 0; i < v_Length; i := i+1) {
      v_S_NSSAI := f_ConvertS_NSSAI_ForATCommand(p_NSSAI.lvPart.s_nssai[i]);  // @sic R5s221179 Baseline Moving sic@
      v_ListOfNSSAI := v_ListOfNSSAI & v_S_NSSAI;                       // @sic R5s200339 sic@
      if (i < (v_Length-1)) { // add a colon to all but the last one
        v_ListOfNSSAI := v_ListOfNSSAI & ":";
      }
    }
    return v_ListOfNSSAI;
  }

  /*
   * @desc      To build QoS Rule for Remote Access
   * @param     p_RuleNum
   * @return    template (value) QoS_Rule
   * @status    APPROVED (ENDC, IMS, NR5GC, NR5GC_IRAT, POS)
   */
  function f_BuildQoSRuleRemoteAccess (charstring p_RuleNum) return template (value) QoS_Rule
  {
    var O1_Type v_Id;
    var B1_Type v_DQR;
    var O1_Type v_Precedence;
    var B6_Type v_FlowId;
    var octetstring v_Component;
    var O2_Type v_Length;
    var B4_Type v_FilterId;

    select (p_RuleNum) {
      case ("3") {
        v_Id := int2oct(str2int(p_RuleNum),1);
        v_DQR := '0'B;
        v_Precedence := int2oct(str2int(p_RuleNum),1);
        v_FlowId := '000001'B;
        v_FilterId := '0010'B;
        v_Component := fl_BuildRemoteAddressPacketFilter("2");
      }
      case ("4") {
        v_Id := int2oct(str2int(p_RuleNum),1);
        v_DQR := '1'B;
        v_Precedence := int2oct(str2int(p_RuleNum),1);
        v_FlowId := '000010'B;
        v_FilterId := '0011'B;
        v_Component := fl_BuildRemoteAddressPacketFilter("3");
      }
      case ("4a") {
        v_Id := '0F'O;
        v_DQR := '0'B;
        v_Precedence := '0F'O;
        v_FlowId := '000100'B;
        v_FilterId := '1111'B;
        v_Component := fl_BuildRemoteAddressPacketFilter("3a");
      }
      case ("5") {
        v_Id := int2oct(str2int(p_RuleNum),1);
        v_DQR := '0'B;
        v_Precedence := int2oct(str2int(p_RuleNum),1);
        v_FlowId := '000101'B;
        v_FilterId := '0100'B;
        v_Component := fl_BuildRemoteAddressPacketFilter("4");
      }
      case ("6") {
        v_Id := int2oct(str2int(p_RuleNum),1);
        v_DQR := '0'B;
        v_Precedence := int2oct(str2int(p_RuleNum),1);
        v_FlowId := '000110'B;
        v_FilterId := '0101'B;
        v_Component := fl_BuildRemoteAddressPacketFilter("5");
      }
    }
    v_Length := int2oct(lengthof(v_Component) + 5, 2);   // @sic R5s190944 sic@
    return cs_QoS_RuleRemoteAccess(v_Id, v_DQR, v_Precedence, v_FlowId, v_Component, v_Length, v_FilterId);
  }

  /*
   * @desc      Build a Remote Address Packet Filter according to 38.508-1 cl. 4.8.2
   * @param     p_FilterNum
   * @return    octetstring
   * @status    APPROVED (ENDC, IMS, NR5GC, NR5GC_IRAT, POS)
   */
  function fl_BuildRemoteAddressPacketFilter (charstring p_FilterNum) return octetstring
  {
    if (pc_IPv6) {
      return fl_BuildRemoteAddressPrefixLengthIPv6 (p_FilterNum);
    } else { // Must be IPv4 only
      return fl_BuildRemoteAddressPacketFilterIPv4 (p_FilterNum);
    }
  }

  /*
   * @desc      Build a Remote Address Packet Filter for IPv4 according to 38.508-1 cl. 4.8.2
   * @param     p_FilterNum
   * @return    octetstring
   * @status    APPROVED (ENDC, IMS, NR5GC, NR5GC_IRAT, POS)
   */
  function fl_BuildRemoteAddressPacketFilterIPv4 (charstring p_FilterNum) return octetstring
  {
    var template (value) PacketFilterComponent v_Component;
    var bitstring v_EncodedComponent;

    v_Component := cs_PktFilterCompIPv4RemoteAddress(fl_GetIPv4Address(p_FilterNum), tsc_IPv4Mask);
    v_EncodedComponent := encvalue(v_Component);
    return bit2oct(v_EncodedComponent);
  }

  /*
   * @desc      Build a Remote Address Packet Filter for IPv6 according to 38.508-1 cl. 4.8.2
   * @param     p_FilterNum
   * @return    octetstring
   * @status    APPROVED (ENDC, IMS, NR5GC, NR5GC_IRAT, POS)
   */
  function fl_BuildRemoteAddressPrefixLengthIPv6 (charstring p_FilterNum) return octetstring
  {
    var O1_Type v_PrefixLength := '64'O;
    var octetstring v_PacketFilter;

    v_PacketFilter := '21'O; // id = IPv6 remote address / Prefix length
    v_PacketFilter := v_PacketFilter & f_Convert_IPv6Addr2OctString(fl_GetIPv6Address(p_FilterNum));
    v_PacketFilter := v_PacketFilter & v_PrefixLength;
    return v_PacketFilter;
  }

  /*
   * @desc      Build an IPv4 address according to 38.508-1 cl. 4.8.2
   * @param     p_FilterNum
   * @return    charstring
   * @status    APPROVED (ENDC, IMS, NR5GC, NR5GC_IRAT, POS)
   */
  function fl_GetIPv4Address (charstring p_FilterNum) return charstring
  {
    var charstring v_IPv4_Address := "10.10.10.";
    select (p_FilterNum) {
      case ("2") {
        v_IPv4_Address := v_IPv4_Address & "2";
      }
      case ("3") {
        v_IPv4_Address := v_IPv4_Address & "3";
      }
      case ("3a") {
        v_IPv4_Address := v_IPv4_Address & "30";
      }
      case ("4") {
        v_IPv4_Address := v_IPv4_Address & "4";
      }
      case ("5") {
        v_IPv4_Address := v_IPv4_Address & "5";
      }
      case else {
        // out of supported range
        FatalError(__FILE__, __LINE__, "unsupported packet filter");
      }
    }
    return v_IPv4_Address;
  }

  /*
   * @desc      Build an IPv4 address according to 38.508-1 cl. 4.8.2
   * @param     p_FilterNum
   * @return    charstring
   * @status    APPROVED (ENDC, IMS, NR5GC, NR5GC_IRAT, POS)
   */
  function fl_GetIPv6Address (charstring p_FilterNum) return charstring
  {
    var charstring v_IPv6_Address;
    select (p_FilterNum) {
      case ("2") {
        v_IPv6_Address := "C0C0:C0C0:C0C0:C002:C0C0:C0C0:C0C0:C0C0";
      }
      case ("3") {
        v_IPv6_Address := "C0C0:C0C0:C0C0:C003:C0C0:C0C0:C0C0:C0C0";
      }
      case ("3a") {
        v_IPv6_Address := "C0C0:C0C0:C0C0:C030:C0C0:C0C0:C0C0:C0C0";
      }
      case ("4") {
        v_IPv6_Address := "C0C0:C0C0:C0C0:C004:C0C0:C0C0:C0C0:C0C0";
      }
      case ("5") {
        v_IPv6_Address := "C0C0:C0C0:C0C0:C005:C0C0:C0C0:C0C0:C0C0";
      }
      case else {
       // out of supported range
       FatalError(__FILE__, __LINE__, "unsupported packet filter");
     }
   }
    return v_IPv6_Address;
  }

  //----------------------------------------------------------------------------
  /*
   * @desc      Create a datagram that will fit the packet filter indicated in the parameter
   * @param     p_FilterNum
   * @return    octetstring
   * @status    APPROVED (NR5GC)
   */
  function f_SdapTests_CreateDatagram(charstring p_FilterNum) return octetstring
  {
    var charstring v_IPv4_DestAddr := fl_GetIPv4Address(p_FilterNum);
    var charstring v_IPv6_DestAddr := fl_GetIPv6Address(p_FilterNum);
    var charstring v_IPv4_SourceAddr := "192.168.0.1";
    var charstring v_IPv6_SourceAddr := "fe80::1:1";
    var UInt20_Type v_IPv6_FlowLabel := 10;
    var UInt16_Type v_SourcePort := 60001;
    var UInt16_Type v_DestPort := 60350;
    var O1_Type v_TOS_TC := 'A9'O;
    var UInt8_Type v_Protocol := tsc_IP_Protocol_UDP;
    var O4_Type v_IPSecSPI := '0F80F000'O;
    var boolean v_IpTypeIsIPv4 := false;

    if (pc_IPv6) {} //variable initialised to false
    else if (pc_IPv4) {
      v_IpTypeIsIPv4 := true;
    }
    else {
      FatalError(__FILE__, __LINE__, "Neither IPv4 nor IPv6 supported");
    }

    return f_PacketFilterTest_CreateDatagram(v_IpTypeIsIPv4,
                                             v_Protocol,
                                             v_IPv4_SourceAddr,
                                             v_IPv4_DestAddr,
                                             v_IPv6_SourceAddr,
                                             v_IPv6_DestAddr,
                                             v_IPv6_FlowLabel,
                                             v_SourcePort,
                                             v_DestPort,
                                             v_IPSecSPI,
                                             v_TOS_TC);
  }

} with { encode "RAW"/*"NAS Types"*/}
