/******************************************************************************/
// @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: 2022-03-20 03:51:00 +0100 (Sun, 20 Mar 2022) $
// $Rev: 32851 $
/******************************************************************************/

module NG_NasEmu_CtrlFunctions {
  import from CommonDefs all;
  import from NG_NasEmu_CtrlAspTypes all;
  import from NasEmu_Common4G5G all;
  
  //****************************************************************************
  // Configuration of NAS security
  //----------------------------------------------------------------------------
  
  template (value) NG_NAS_SecurityStartRestart_Type cs_NG_NAS_SecurityInit(B4_Type       p_IntegrityAlgorithm,
                                                                           B128_Key_Type p_K_NASint,
                                                                           B4_Type       p_CipheringAlgorithm,
                                                                           B128_Key_Type p_K_NASenc,
                                                                           template (omit) Null_Type p_NasCountReset := true) :=
  { /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
    Integrity := {
      Algorithm := p_IntegrityAlgorithm,
      K_NAS := p_K_NASint
    },
    Ciphering := {
      Algorithm := p_CipheringAlgorithm,
      K_NAS := p_K_NASenc
    },
    NasCountReset := p_NasCountReset
  };
  
  template (value) NG_NAS_CTRL_REQ cas_NG_NasSecurityStart_REQ(template (value) NG_NAS_SecurityStartRestart_Type p_SecurityStartRestart) :=
  { /* Note: NAS security seems to be cell independent */
    /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
    Common := cs_NasCtrlReqAspCommonPart,
    Request := {
      Security := {
        StartRestart := p_SecurityStartRestart
      }
    }
  };
  
  template (value) NG_NAS_CTRL_REQ cas_NG_NasSecurityRelease_REQ :=
  { /* @status    APPROVED (NR5GC) */
    /* Note: NAS security is cell independent */
    Common := cs_NasCtrlReqAspCommonPart,
    Request := {
      Security := {
        Release := true
      }
    }
  };
  
  template (present) NG_NAS_CTRL_CNF car_NG_NasSecurity_CNF :=
  { /* Note: NAS security seems to be cell independent */
    /* @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS) */
    Common := cr_NasCtrlCnfAspCommonPart,
    Confirm := {
      Security := true
    }
  };
  
  //****************************************************************************
  // Dealing with DL NAS COUNT
  //----------------------------------------------------------------------------
  
  template (value) NG_NAS_CTRL_REQ cas_NG_NasCountGet_REQ :=
  { /* @status    APPROVED (NR5GC, NR5GC_IRAT) */
    Common := cs_NasCtrlReqAspCommonPart,
    Request := {
      NasCount := {
        Get := true
      }
    }
  };
  
  template (present) NG_NAS_CTRL_CNF car_NG_NasCountGet_CNF :=
  { /* @status    APPROVED (NR5GC, NR5GC_IRAT) */
    Common := cr_NasCtrlCnfAspCommonPart,
    Confirm := {
      NasCount := {
        Get := {
          UL := ?,
          DL := ?
        }
      }
    }
  };
  
  template (value) NG_NAS_CTRL_REQ cas_NG_NasCountSet_REQ(template (omit) NasCount_Type p_NASULCount,
                                                          template (omit) NasCount_Type p_NASDLCount) :=
  { /* @status    APPROVED (NR5GC, NR5GC_IRAT) */
    Common := cs_NasCtrlReqAspCommonPart,
    Request := {
      NasCount := {
        Set := {
          UL := p_NASULCount,
          DL := p_NASDLCount
        }
      }
    }
  };
  
  template (present) NG_NAS_CTRL_CNF car_NG_NasCountSet_CNF :=
  { /* @status    APPROVED (NR5GC, NR5GC_IRAT) */
    Common := cr_NasCtrlCnfAspCommonPart,
    Confirm := {
      NasCount := {
        Set := true
      }
    }
  };

  //****************************************************************************
  /*
   * @desc      Common function to configure NAS security
   * @param     p_Port
   * @param     p_NAS_CTRL_REQ
   * @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS)
   */
  function f_SS_NG_NAS_SecurityConfig(NG_NASCTRL_PORT p_Port,
                                      template (value) NG_NAS_CTRL_REQ p_NAS_CTRL_REQ)
  {
    p_Port.send(p_NAS_CTRL_REQ);
    if (valueof(p_NAS_CTRL_REQ.Common.ControlInfo.CnfFlag) == true) {
      p_Port.receive(car_NG_NasSecurity_CNF);
    }
  }
  
  //----------------------------------------------------------------------------
  /*
   * @desc      configure NAS security at the NasEmu
   * @param     p_Port
   * @param     p_NAS_Integrity
   * @param     p_NAS_Ciphering
   * @param     p_NasCountReset     (default value: true)
   * @status    APPROVED (IMS, NR5GC, NR5GC_IRAT, POS)
   */
  function f_SS_NG_NAS_ConfigureSecurity(NG_NASCTRL_PORT p_Port,
                                         NG_NAS_SecurityInfo_Type p_NAS_Integrity,
                                         NG_NAS_SecurityInfo_Type p_NAS_Ciphering,
                                         template (omit) Null_Type p_NasCountReset := true)
  {
    f_SS_NG_NAS_SecurityConfig(p_Port,
                               cas_NG_NasSecurityStart_REQ(cs_NG_NAS_SecurityInit(p_NAS_Integrity.Algorithm,
                                                                                  p_NAS_Integrity.K_NAS,
                                                                                  p_NAS_Ciphering.Algorithm,
                                                                                  p_NAS_Ciphering.K_NAS,
                                                                                  p_NasCountReset)));
  }
  
  //----------------------------------------------------------------------------
  /*
   * @desc      common function to query NAS COUNT from the NAS emulator
   * @param     p_Port
   * @return    NasCountInfo_Type
   * @status    APPROVED (NR5GC, NR5GC_IRAT)
   */
  function f_SS_NG_NAS_CountGet(NG_NASCTRL_PORT p_Port) return NasCountInfo_Type
  {
    var NG_NAS_CTRL_CNF v_NG_NAS_CTRL_CNF;
    
    p_Port.send(cas_NG_NasCountGet_REQ);
    p_Port.receive(car_NG_NasCountGet_CNF) -> value v_NG_NAS_CTRL_CNF;
    return v_NG_NAS_CTRL_CNF.Confirm.NasCount.Get;
  }
  
  //----------------------------------------------------------------------------
  /*
   * @desc      common function to set NAS COUNT at the NAS emulator
   * @param     p_Port
   * @param     p_NASDLCount
   * @param     p_NASULCount        (default value: omit)
   * @status    APPROVED (NR5GC, NR5GC_IRAT)
   */
  function f_SS_NG_NAS_CountSet(NG_NASCTRL_PORT p_Port,
                                template (omit) NasCount_Type p_NASDLCount,
                                template (omit) NasCount_Type p_NASULCount := omit)
  {
    p_Port.send(cas_NG_NasCountSet_REQ(p_NASULCount, p_NASDLCount));
    p_Port.receive(car_NG_NasCountSet_CNF);
  }
  
  /*
   * @desc      function to query DL NAS COUNT from the NAS emulator // @sic R5s110382 sic@
   * @param     p_Port
   * @return    O4_Type
   */
  function f_SS_NG_NAS_CountGetDLNext(NG_NASCTRL_PORT p_Port) return O4_Type
  {
    var NasCountInfo_Type v_NasCountInfo := f_SS_NG_NAS_CountGet(p_Port);
    return f_NasSecurity_IncrementCOUNT(v_NasCountInfo.DL);
  }
  
  /*
   * @desc      function to query UL NAS COUNT from the NAS emulator
   * @param     p_Port
   * @return    O4_Type
   */
  function f_SS_NG_NAS_CountGetULNext(NG_NASCTRL_PORT p_Port) return O4_Type
  {
    var NasCountInfo_Type v_NasCountInfo := f_SS_NG_NAS_CountGet(p_Port);
    return f_NasSecurity_IncrementCOUNT(v_NasCountInfo.UL);
  }
}
