/******************************************************************************/
// @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.
//   Trademark 2010, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC).
//   All rights reserved.
// @version: IWD_10wk37
// $Date: 2010-09-13 18:44:47 +0200 (Mon, 13 Sep 2010) $
// $Rev: 3862 $
/******************************************************************************/

module EUTRA_NASCommonFunctions {

  import from EUTRA_RRC_ASN1_Definitions language "ASN.1:1997" all;
  import from CommonDefs all;
  import from EUTRA_CommonDefs all;
  import from NAS_CommonTypeDefs all;
  import from EPS_NAS_TypeDefs all;
  import from EPS_NAS_Constants all;
  import from EPS_NAS_MsgContainers all;
  import from EUTRA_NASCommonTemplates all;
  import from EPS_NAS_Templates all;
  import from EUTRA_AspCommon_Templates all;
  import from EUTRA_RRC_Templates all;
  import from EUTRA_SRB_Templates all;
  import from EUTRA_Component all;
  import from EUTRA_ConfigurationSteps all;
  import from EUTRA_CommonProcedures all;
  import from UpperTesterFunctions all;
  import from EUTRA_CellInfo all;
  import from EUTRA_RRCSteps all;
  import from EUTRA_NASSteps all;
  import from EUTRA_Paging all;
  import from EUTRA_SecurityFunctions all;
  import from EUTRA_Timing all;
  import from EUTRA_DRB_Templates all;

  function f_EUTRA_CheckNoRrcConnEst(float p_Delay_sec,
                                     CellId_Type p_CellId)
    runs on EUTRA_PTC
    return boolean
  { /* @desc Check that no RRC connection establishment request gets
     *       received on the cell p_CellId within the given time period of
     *       p_Delay_sec.
     * @return True if no RRC connection est. request message was received in the
     *         given time frame, false otherwise.
     * @param p_Delay_sec Time to wait for the attempt to establish an RRC
     *        connection.
     * @param p_CellId ID of the cell on which the RRC connection establishment
     *        gets checked. */
    timer t_Wait;
    t_Wait.start(p_Delay_sec);
    alt {
      // receive RRC Connection Request on SRB0 (CCCH):
      [] SRB.receive(car_SRB0_RrcPdu_IND(p_CellId,
                                         cr_RRCConnectionRequest(?)))
        {
          t_Wait.stop;
          return false;
        }
      [] t_Wait.timeout {
        // no action required
      }
    }
    return true;
  }

  function f_EUTRA_WaitForNasUlMessage(float p_Delay_sec,
                                       CellId_Type p_CellId,
                                       template (present) NAS_MSG_Indication_Type p_NasRcvTemplate)
    runs on EUTRA_PTC
    return boolean
  { /* @desc Check that the NAS UL message specified by p_NasRcvTemplate
     *       gets received on the cell p_CellId within the given time period
     *       of p_Delay_sec.
     *       Returns true if the message was received in the
     *       given time frame, false if the message was not received.
     * @param p_Delay_sec Time to wait for the expected message.
     * @param p_CellId ID of the cell on which the expected message shall arrive.
     * @param p_NasRcvTemplate Template for the expected NAS UL message. */

    timer t_Wait;
    t_Wait.start(p_Delay_sec);
    alt {
      [] SRB.receive(car_SRB1_NasPdu_IND(p_CellId,
                                         p_NasRcvTemplate))
        {
          t_Wait.stop;
          return true;
        }
      [] t_Wait.timeout {
        // no action required
      }
    }
    return false;
  }

/*  Currently only referenced in WorkingDrafts files
function f_GetTmsiStatus()
    return template (omit) TMSI_Status
  {
    if( pc_CSfallback ) {
      return cr_TMSI_Status(tsc_NoValidTmsi);
    }
    return omit;
  }
*/

  /*
   * @desc      Generic test step to reject a registration attempt by the UE.
   *            This is based on the Preamble function and should be run as an alternative.
   *            This results in the UE being switched off, and  with no valid GUTI
   * @param     p_CellId
   * @param     p_RejectCause
   * @status    APPROVED
   */
  function f_EUTRA_Preamble_Reject(CellId_Type p_CellId,
                                   NAS_CauseValue_Type p_RejectCause) runs on EUTRA_PTC
  {
    // First switch cell back on
    f_EUTRA_SetCellPower ( p_CellId, tsc_ServingCellRS_EPRE, cs_TimingInfo_Now );

    f_EUTRA_AttachReject (p_CellId, p_RejectCause);

    // And then just need to switch UE off
    f_UT_SwitchOffUE (UT, false);
  }

  /*
   * @desc      Generic test step to reject a registration attempt by the UE.
   *            This expects the UE to be switched off before calling this function, and leaves the UE switched on at the end
   * @param     p_CellId
   * @param     p_RejectCause
   * @status    APPROVED
   */
  function f_EUTRA_AttachReject (CellId_Type p_CellId,
                                 NAS_CauseValue_Type p_RejectCause) runs on EUTRA_PTC
  {
    var RRC_TransactionIdentifier v_RRC_TI := tsc_RRC_TI_Def;
    var NAS_AttDetValue_Type v_AttachType;
    var PdnTypeValue v_PDNValue;
    var NAS_MSG_Indication_Type v_NAS_Ind;
    var EUTRA_SecurityParams_Type v_AuthParams := f_EUTRA_Security_Get();
    var template AdditionalUpdateType v_AdditionalUpdateType := f_GetAdditionalUpdateType ();  //used to follow TTCN3 v411 standard

    // Switch on UE
    f_UT_SwitchOnUE (UT, false);

    v_AttachType := f_GetEAttachType();

    v_PDNValue := f_GetPdnType();

    // RRC Connection Establishment, with Attach Request and PDN Connectivity
    v_NAS_Ind := f_EUTRA_RRC_ConnEst_DefWithNas(p_CellId,
                                                v_RRC_TI,
                                                cr_EstablishmentCause_Any,
                                                cr_NAS_IndicationWithPiggybacking((tsc_SHT_NoSecurityProtection,
                                                                                   tsc_SHT_IntegrityProtected),
                                                                                  cr_508_ATTACH_REQUEST(v_AttachType, v_AdditionalUpdateType), // @sic R5-103681 sic@
                                                                                  cr_508_PDN_CONNECTIVITY_REQUEST(tsc_PdnRequest_InitialAttach,
                                                                                                                  v_PDNValue)));

    // Set UE network capabilities as sent by the UE to be used later in the test case(see TS 24.301 clause 5.4.3.3)
    v_AuthParams.NAS_SecurityCap := f_EUTRA_FillNAS_SecurityCapability(v_NAS_Ind.Pdu.Msg.aTTACH_REQUEST);  // @sic R5s100135 sic@
    f_EUTRA_Security_Set(v_AuthParams);

    // Now send Attach Reject, to get UE to delete GUTI
    SRB.send  ( cas_SRB1_NasPdu_REQ ( p_CellId,
                                      cs_TimingInfo_Now,
                                      cs_NAS_Request ( tsc_SHT_NoSecurityProtection,
                                                       cs_508_AttachReject ( cs_EMM_Cause_v(p_RejectCause),
                                                                             omit))));

    f_EUTRA_RRC_ConnectionRelease(p_CellId, v_RRC_TI, other);
  }

  /*
   * @desc      Send RRCConnectionReconfiguration with piggy-backed MODIFY EPS BEARER CONTEXT REQUEST
   * @param     p_CellId
   * @param     p_RRC_TI
   * @param     p_Id
   * @param     p_ProcTi
   * @param     p_QoS
   * @param     p_Tft
   * @status    APPROVED
   */
  function f_EUTRA_TxModifyEpsBearerCtxtReq(CellId_Type p_CellId,
                                            RRC_TransactionIdentifier p_RRC_TI,
                                            EPS_BearerIdentity p_Id,
                                            ProcedureTransactionIdentifier p_ProcTi, // octet
                                            template (value) EPS_QualityOfService p_QoS,
                                            template (omit) TrafficFlowTemplate p_Tft)
    runs on EUTRA_PTC
  {
    // send RRCConnectionReconfiguration with piggy-backed MODIFY EPS BEARER CONTEXT REQUEST
    var template (value) NAS_DL_Message_Type v_ModifyEPSBearerCxtReq := cs_508_ModifyEPSBearerCxtReq(p_Id,
                                                                                                     p_ProcTi,
                                                                                                     p_QoS,
                                                                                                     p_Tft); // @sic R5-103625 sic@
    
    SRB.send(cas_SRB1_RrcNasPdu_REQ(p_CellId,
                                 cs_TimingInfo_Now,
                                 cs_RRCConnectionReconfiguration_RadioResConfig(p_RRC_TI, cs_RadioResourceConfig_DRB_RECONFIG),
                                 cs_NAS_Request(tsc_SHT_IntegrityProtected_Ciphered,
                                                v_ModifyEPSBearerCxtReq)));   // @sic R5-103626 sic@
    
  };

  /*
   * @desc      Test procedure Paging (for NAS testing) in TS 6.4.2.4 for PS domain
   *            For CS domain, the the check procedure is still  FFS.
   * @param     p_CellId
   * @param     p_Cn_Domain
   * @status    APPROVED
   */
  function f_EPS_508Check_NAS_Paging ( CellId_Type p_CellId,
                                       CN_Domain_Type p_Cn_Domain ) runs on EUTRA_PTC
  { /* This procedure aims at checking whether the UE is in RRC_IDLE on
     * a certain cell of a test case or not.  */
    var GutiParameters_Type v_GutiParams := f_EUTRA_CellInfo_GetGuti(p_CellId);
    var NAS_MSG_Indication_Type v_NasInd;

    // Step 1. Paging. SS pages the UE using S-TMSI for PS or CS domain
    f_EUTRA_UE_Page(p_CellId,
                    cs_DomainNasPaging_OneRecord(cs_PagingUE_Identity_S_TMSI(v_GutiParams.MME_Code,
                                                                             v_GutiParams.M_TMSI),
                                                 p_Cn_Domain));
    if (p_Cn_Domain ==  ps){
      // Step 2. Verify that the UE sends Service Request
      v_NasInd := f_EUTRA_RRC_ConnEst_DefWithNas(p_CellId,
                                                 tsc_RRC_TI_Def,
                                                 cr_EstablishmentCause_mt_Access,
                                                 cr_NAS_Indication(tsc_SHT_IntegrityProtected,
                                                                   cr_508_SERVICE_REQUEST(f_EUTRA_SecurityKSIasme_Get())));

    } else {
      // Step 2 CS domain. Verify that the UE sends Extended Service Request
      v_NasInd := f_EUTRA_RRC_ConnEst_DefWithNas(p_CellId,
                                                 tsc_RRC_TI_Def,
                                                 cr_EstablishmentCause_mt_Access,
                                                 cr_NAS_Indication(tsc_SHT_IntegrityProtected,
                                                                   cr_508_EXT_SERVICE_REQUEST(f_EUTRA_SecurityKSIasme_Get(),
                                                                                              tsc_EST_CsFallback_MO,
                                                                                              bit2oct(v_GutiParams.M_TMSI))));
    }

    // Bring UE to a stable state (back to idle)
    SRB.send ( cas_SRB1_NasPdu_REQ ( p_CellId,
                                     cs_TimingInfo_Now,
                                     cs_NAS_Request ( tsc_SHT_NoSecurityProtection,
                                                      cs_508_SERVICE_REJECT ( tsc_Cause_Congestion ) ) ) );
    f_EUTRA_RRC_ConnectionRelease(p_CellId, tsc_RRC_TI_Def, other);
    f_EUTRA_PreliminaryPass(__FILE__, __LINE__, "508Check NASPaging");
  }


  /*
   * @desc      Test procedure for no response to paging (for NAS testing)
   *            See TS 36.508 clause 6.4.2.5.
   * @param     p_CellId
   * @param     p_PagingRecordList
   * @param     p_NoReactionTimer
   * @status    APPROVED
   */
  function f_EUTRA_508Check_NASNoResponse(CellId_Type p_CellId,
                                          template (value) PagingRecordList  p_PagingRecordList,
                                          float p_NoReactionTimer) runs on EUTRA_PTC
  {
    f_EUTRA_UE_Page_NoReaction ( p_CellId, p_PagingRecordList, p_NoReactionTimer );
  }

  /*
   * @desc      Test procedure to check that a dedicated EPS bearer context is active (for NAS testing)
   *            See TS 36.508 clause 6.4.2.6.
   * @param     p_CellId
   * @param     p_DedicatedEpsBearerId
   * @param     p_QoS
   * @param     p_Tft
   * @status    APPROVED
   */
  function f_EUTRA_508Check_DedicatedEPSIsActive( CellId_Type p_CellId,
                                                  EPS_BearerIdentity p_DedicatedEpsBearerId,
                                                  template (value) EPS_QualityOfService p_QoS,
                                                  template (value) TrafficFlowTemplate p_Tft)
    runs on EUTRA_PTC
  {
    var ProcedureTransactionIdentifier v_EpsProcedureTransactionId := '00'O;
    
    // The SS transmits an MODIFY EPS BEARER CONTEXT REQUEST
    
    /* Note: This message is included in a RRCConnectionReconfiguration message to
     * setup the new radio bearer associated with the dedicated EPS bearer context
     * activated by the NAS message
     */
    f_EUTRA_TxModifyEpsBearerCtxtReq(p_CellId,
                                     tsc_RRC_TI_Def,
                                     p_DedicatedEpsBearerId,
                                     v_EpsProcedureTransactionId,
                                     p_QoS,
                                     p_Tft);
    
    //Receive RRCConnectionReconfigurationComplete
    SRB.receive(car_SRB1_RrcPdu_IND(p_CellId, cr_508_RRCConnectionReconfigurationComplete(tsc_RRC_TI_Def))); // @sic R5s100295 sic@

    // The UE transmits an MODIFY EPS BEARER CONTEXT ACCEPT message as specified
    SRB.receive(car_SRB2_NasPdu_IND(p_CellId,
                                    cr_NAS_Indication(tsc_SHT_IntegrityProtected_Ciphered,
                                                      cr_508_ModifyEPSBearerCxtAccept(p_DedicatedEpsBearerId))));
    f_EUTRA_PreliminaryPass(__FILE__, __LINE__, "508Check DedicatedEPSIsActive");
  }
  
  //----------------------------------------------------------------------------
  /*
   * @desc      Check whether UE tries to attach in any cell given by p_CellId
   * @param     p_CellId        ... template describing on or more cells
   * @param     p_WaitTimer         (by reference)
   * @param     p_FailMsg       ... message to be used in case of FAIL
   * @status    APPROVED
   */
  function fl_EUTRA_CheckNoAttach_Common(template (present) CellId_Type p_CellId,
                                         inout timer p_WaitTimer,
                                         charstring p_FailMsg) runs on EUTRA_PTC
  {
    p_WaitTimer.start;
    alt {
       []  SRB.receive(car_SRB0_RrcPdu_IND(p_CellId, cr_RRCConnectionRequest(?)))
         {
           p_WaitTimer.stop;
           f_EUTRA_SetVerdictFailOrInconc (__FILE__, __LINE__, p_FailMsg);
         }
       []  p_WaitTimer.timeout
         {
         }
    }
  }

  /*
   * @desc      Check whether UE tries to attach to given cell
   * @param     p_CellId
   * @param     p_Wait          ... time to wait before UE may attach again
   * @param     p_StepNo            (default value: "")
   * @status    APPROVED
   */
  function f_EUTRA_CheckNoAttachOn1Cell(CellId_Type p_CellId,
                                        float p_Wait,
                                        charstring p_StepNo := "") runs on EUTRA_PTC
  {
    timer t_Wait := f_EUTRA_SetTimerToleranceMin (p_CellId, p_Wait);
    fl_EUTRA_CheckNoAttach_Common(p_CellId, t_Wait, p_StepNo);
  }
   
  /*
   * @desc      Wrapper function to check whether the UE tries to attach to the given cells
   * @param     p_CellIdA
   * @param     p_CellIdB
   * @param     p_Wait
   * @param     p_StepNo            (default value: "")
   * @status    APPROVED
   */
  function f_EUTRA_CheckNoAttachOn2Cells(CellId_Type p_CellIdA,
                                         CellId_Type p_CellIdB,
                                         float p_Wait,
                                         charstring p_StepNo := "") runs on EUTRA_PTC
  {
    var template (present) CellId_Type v_CellId := (p_CellIdA, p_CellIdB);
    timer t_Wait := f_EUTRA_SetTimerToleranceMin (p_CellIdA, p_Wait);
    fl_EUTRA_CheckNoAttach_Common(v_CellId, t_Wait, p_StepNo);
  }

  function f_EUTRA_CheckNoAttachOn4Cells(CellId_Type p_CellIdA,
                                             CellId_Type p_CellIdB,
                                             CellId_Type p_CellIdC,
                                             CellId_Type p_CellIdD,
                                             float p_Wait,
                                             charstring p_StepNo := "") runs on EUTRA_PTC
  {
    var template (present) CellId_Type v_CellId := (p_CellIdA, p_CellIdB, p_CellIdC, p_CellIdD);
    timer t_Wait := f_EUTRA_SetTimerToleranceMin (p_CellIdA, p_Wait);
    fl_EUTRA_CheckNoAttach_Common(v_CellId, t_Wait, p_StepNo);
  }

  /*
   * @desc      UE Registration acc. to 36.508 cl. 4.5.2
   * @param     p_CellId
   * @param     p_VerdictComment
   * @param     p_ForcedAttach      (default value: NORMAL)
   * @status    (APPROVED)
   */
  function f_EUTRA_AttachProcedure ( CellId_Type p_CellId,
                                     charstring p_VerdictComment,
                                     EUTRA_ATTACH_Type p_ForcedAttach := NORMAL ) runs on EUTRA_PTC
  {
    var RRC_TransactionIdentifier v_RRC_TI := tsc_RRC_TI_Def;
    var NAS_AttDetValue_Type v_AttachType := f_GetEAttachType();
    var B3_Type v_PDNType := f_GetPdnType();
    var template AdditionalUpdateType v_AdditionalUpdateType := f_GetAdditionalUpdateType ();
    var NAS_MSG_Indication_Type v_NAS_Ind;
    
    // Receive RRC Connection Setup Complete with
    v_NAS_Ind := f_EUTRA_RRC_ConnEst_DefWithNas(p_CellId,
                                                v_RRC_TI,
                                                cr_EstablishmentCause_Any,
                                                cr_NAS_IndicationWithPiggybacking(tsc_SHT_IntegrityProtected,
                                                                                  cr_508_ATTACH_REQUEST(v_AttachType, v_AdditionalUpdateType),
                                                                                  cr_508_PDN_CONNECTIVITY_REQUEST(tsc_PdnRequest_InitialAttach, v_PDNType)));
    if (p_VerdictComment != "No Verdict") {
      f_EUTRA_PreliminaryPass(__FILE__, __LINE__, p_VerdictComment);
    }
    
    f_EUTRA_IdleUpdated_Step5_17 (p_CellId, STATE2_IDLEUPDATE, p_ForcedAttach, v_NAS_Ind);
    
  } // f_EUTRA_AttachProcedure
  
}
