module RANAP_Templates {

import from General_Types all;

import from RANAP_IEs all;
import from RANAP_CommonDataTypes all;
import from RANAP_Constants all;
import from RANAP_Containers all;
import from RANAP_PDU_Contents all;
import from RANAP_PDU_Descriptions all;

template (value) Cause ts_RanapCause_om_intervention := { misc := 113 };

/*****************************************************************************************************
 * Reset
 *****************************************************************************************************/

template (value) RANAP_PDU
ts_RANAP_Reset(template (value) Cause cause, template (value) CN_DomainIndicator dom,
			  template (omit) Reset.protocolExtensions exts := omit) := {
	initiatingMessage := {
		procedureCode := id_Reset,
		criticality := reject,
		value_ := {
			Reset := {
				protocolIEs := {
					{
						id := id_Cause,
						criticality := ignore,
						value_ := {
							cause := cause
						}
					}, {
						id := id_CN_DomainIndicator,
						criticality := reject,
						value_ := {
							cN_DomainIndicator := dom
						}
					}
				},
				protocolExtensions := exts
			}
		}
	}
}
template RANAP_PDU
tr_RANAP_Reset(template Cause cause := ?, template CN_DomainIndicator dom := ?,
			  template Reset.protocolExtensions exts := *) := {
	initiatingMessage := {
		procedureCode := id_Reset,
		criticality := reject,
		value_ := {
			Reset := {
				protocolIEs := {
					{
						id := id_Cause,
						criticality := ignore,
						value_ := {
							cause := cause
						}
					}, {
						id := id_CN_DomainIndicator,
						criticality := reject,
						value_ := {
							cN_DomainIndicator := dom
						}
					}, *
				},
				protocolExtensions := exts
			}
		}
	}
}

template (value) RANAP_PDU
ts_RANAP_ResetAck(template (value) CN_DomainIndicator dom,
		  template (omit) ResetAcknowledge.protocolExtensions exts := omit) := {
	successfulOutcome := {
		procedureCode := id_Reset,
		criticality := reject,
		value_ := {
			ResetAcknowledge := {
				protocolIEs := {
					{
						id := id_CN_DomainIndicator,
						criticality := reject,
						value_ := {
							cN_DomainIndicator := dom
						}
					}
				},
				protocolExtensions := exts
			}
		}
	}
}
template RANAP_PDU
tr_RANAP_ResetAck(template CN_DomainIndicator dom := ?,
		  template ResetAcknowledge.protocolExtensions exts := *) := {
	successfulOutcome := {
		procedureCode := id_Reset,
		criticality := reject,
		value_ := {
			ResetAcknowledge := {
				protocolIEs := {
					{
						id := id_CN_DomainIndicator,
						criticality := reject,
						value_ := {
							cN_DomainIndicator := dom
						}
					}, *
				},
				protocolExtensions := exts
			}
		}
	}
}

/*****************************************************************************************************
 * Security Mode Control
 *****************************************************************************************************/

template (value) RANAP_PDU
ts_RANAP_SecurityModeCmd(template (value) PermittedIntegrityProtectionAlgorithms uia_algs,
			 template (value) IntegrityProtectionKey uia_key,
			 template (value) KeyStatus key_sts,
		  	 template (omit) SecurityModeCommand.protocolExtensions exts := omit) := {
	initiatingMessage := {
		procedureCode := id_SecurityModeControl,
		criticality := reject,
		value_ := {
			securityModeCommand := {
				protocolIEs := {
					{
						id := id_IntegrityProtectionInformation,
						criticality := reject,
						value_ := {
							integrityProtectionInformation := {
								permittedAlgorithms := uia_algs,
								key := uia_key,
								iE_Extensions := omit
							}
						}
					}, {
						id := id_KeyStatus,
						criticality := reject,
						value_ := {
							keyStatus := key_sts
						}
					}
				},
				protocolExtensions := exts
			}
		}
	}
}
template RANAP_PDU
tr_RANAP_SecurityModeCmd(template PermittedIntegrityProtectionAlgorithms uia_algs,
			 template IntegrityProtectionKey uia_key,
			 template KeyStatus key_sts,
		  	 template SecurityModeCommand.protocolExtensions exts := *) := {
	initiatingMessage := {
		procedureCode := id_SecurityModeControl,
		criticality := reject,
		value_ := {
			securityModeCommand := {
				protocolIEs := {
					{
						id := id_IntegrityProtectionInformation,
						criticality := reject,
						value_ := {
							integrityProtectionInformation := {
								permittedAlgorithms := uia_algs,
								key := uia_key,
								iE_Extensions := *
							}
						}
					}, {
						id := id_KeyStatus,
						criticality := reject,
						value_ := {
							keyStatus := key_sts
						}
					}
				},
				protocolExtensions := exts
			}
		}
	}
}

template (value) RANAP_PDU
ts_RANAP_SecurityModeCmdEnc(template (value) PermittedIntegrityProtectionAlgorithms uia_algs,
			    template (value) IntegrityProtectionKey uia_key,
			    template (value) KeyStatus key_sts,
			    template (value) PermittedEncryptionAlgorithms uea_algs,
			    template (value) EncryptionKey uea_key,
		  	    template (omit) SecurityModeCommand.protocolExtensions exts := omit) := {
	initiatingMessage := {
		procedureCode := id_SecurityModeControl,
		criticality := reject,
		value_ := {
			securityModeCommand := {
				protocolIEs := {
					{
						id := id_IntegrityProtectionInformation,
						criticality := reject,
						value_ := {
							integrityProtectionInformation := {
								permittedAlgorithms := uia_algs,
								key := uia_key,
								iE_Extensions := omit
							}
						}
					}, {
						id := id_EncryptionInformation,
						criticality := ignore,
						value_ := {
							encryptionInformation := {
								permittedAlgorithms := uea_algs,
								key := uea_key,
								iE_Extensions := omit
							}
						}
					}, {
						id := id_KeyStatus,
						criticality := reject,
						value_ := {
							keyStatus := key_sts
						}
					}
				},
				protocolExtensions := exts
			}
		}
	}
}
template RANAP_PDU
tr_RANAP_SecurityModeCmdEnc(template PermittedIntegrityProtectionAlgorithms uia_algs,
			    template IntegrityProtectionKey uia_key,
			    template KeyStatus key_sts,
			    template PermittedEncryptionAlgorithms uea_algs,
			    template EncryptionKey uea_key,
		  	    template SecurityModeCommand.protocolExtensions exts := *) := {
	initiatingMessage := {
		procedureCode := id_SecurityModeControl,
		criticality := reject,
		value_ := {
			securityModeCommand := {
				protocolIEs := {
					{
						id := id_IntegrityProtectionInformation,
						criticality := reject,
						value_ := {
							integrityProtectionInformation := {
								permittedAlgorithms := uia_algs,
								key := uia_key,
								iE_Extensions := *
							}
						}
					}, {
						id := id_EncryptionInformation,
						criticality := ignore,
						value_ := {
							encryptionInformation := {
								permittedAlgorithms := uea_algs,
								key := uea_key,
								iE_Extensions := *
							}
						}
					}, {
						id := id_KeyStatus,
						criticality := reject,
						value_ := {
							keyStatus := key_sts
						}
					}
				},
				protocolExtensions := exts
			}
		}
	}
}

template (value) RANAP_PDU
ts_RANAP_SecurityModeComplete(template (value) IntegrityProtectionAlgorithm uia_alg,
			      template (omit) SecurityModeComplete.protocolExtensions exts := omit) := {
	successfulOutcome := {
		procedureCode := id_SecurityModeControl,
		criticality := reject,
		value_ := {
			securityModeComplete := {
				protocolIEs := {
					{
						id := id_ChosenIntegrityProtectionAlgorithm,
						criticality := reject,
						value_ := {
							chosenIntegrityProtectionAlgorithm := uia_alg
						}
					}
				},
				protocolExtensions := exts
			}
		}
	}
}
template RANAP_PDU
tr_RANAP_SecurityModeComplete(template IntegrityProtectionAlgorithm uia_alg,
			      template SecurityModeComplete.protocolExtensions exts := *) := {
	successfulOutcome := {
		procedureCode := id_SecurityModeControl,
		criticality := reject,
		value_ := {
			securityModeComplete := {
				protocolIEs := {
					{
						id := id_ChosenIntegrityProtectionAlgorithm,
						criticality := reject,
						value_ := {
							chosenIntegrityProtectionAlgorithm := uia_alg
						}
					}
				},
				protocolExtensions := exts
			}
		}
	}
}

template (value) RANAP_PDU
ts_RANAP_SecurityModeCompleteEnc(template (value) IntegrityProtectionAlgorithm uia_alg,
				 template (value) EncryptionAlgorithm uea_alg,
				 template (omit) SecurityModeComplete.protocolExtensions exts := omit) := {
	successfulOutcome := {
		procedureCode := id_SecurityModeControl,
		criticality := reject,
		value_ := {
			securityModeComplete := {
				protocolIEs := {
					{
						id := id_ChosenIntegrityProtectionAlgorithm,
						criticality := reject,
						value_ := {
							chosenIntegrityProtectionAlgorithm := uia_alg
						}
					}, {
						id := id_ChosenEncryptionAlgorithm,
						criticality := ignore,
						value_ := {
							chosenEncryptionAlgorithm := uea_alg
						}
					}
				},
				protocolExtensions := exts
			}
		}
	}
}
template RANAP_PDU
tr_RANAP_SecurityModeCompleteEnc(template IntegrityProtectionAlgorithm uia_alg,
				 template EncryptionAlgorithm uea_alg,
				 template SecurityModeComplete.protocolExtensions exts := *) := {
	successfulOutcome := {
		procedureCode := id_SecurityModeControl,
		criticality := reject,
		value_ := {
			securityModeComplete := {
				protocolIEs := {
					{
						id := id_ChosenIntegrityProtectionAlgorithm,
						criticality := reject,
						value_ := {
							chosenIntegrityProtectionAlgorithm := uia_alg
						}
					}, {
						id := id_ChosenEncryptionAlgorithm,
						criticality := ignore,
						value_ := {
							chosenEncryptionAlgorithm := uea_alg
						}
					}
				},
				protocolExtensions := exts
			}
		}
	}
}

template (value) RANAP_PDU
ts_RANAP_SecurityModeReject(template (value) Cause cause,
			    template (omit) SecurityModeReject.protocolExtensions exts := omit) := {
	unsuccessfulOutcome := {
		procedureCode := id_SecurityModeControl,
		criticality := reject,
		value_ := {
			securityModeReject := {
				protocolIEs := {
					{
						id := id_Cause,
						criticality := ignore,
						value_ := {
							cause := cause
						}
					}
				},
				protocolExtensions := exts
			}
		}
	}
}
template RANAP_PDU
tr_RANAP_SecurityModeReject(template Cause cause,
			    template SecurityModeReject.protocolExtensions exts := *) := {
	unsuccessfulOutcome := {
		procedureCode := id_SecurityModeControl,
		criticality := reject,
		value_ := {
			securityModeReject := {
				protocolIEs := {
					{
						id := id_Cause,
						criticality := ignore,
						value_ := {
							cause := cause
						}
					}
				},
				protocolExtensions := exts
			}
		}
	}
}



/*****************************************************************************************************
 * Iu Release Request
 *****************************************************************************************************/

template (value) RANAP_PDU
ts_RANAP_IuReleaseRequest(template (value) Cause cause,
			  template (omit) Iu_ReleaseRequest.protocolExtensions exts := omit) := {
	initiatingMessage := {
		procedureCode := id_Iu_ReleaseRequest,
		criticality := ignore,
		value_ := {
			iu_ReleaseRequest := {
				protocolIEs := {
					{
						id := id_Cause,
						criticality := reject,
						value_ := {
							cause := cause
						}
					}
				},
				protocolExtensions := exts
			}
		}
	}
}
template RANAP_PDU
tr_RANAP_IuReleaseRequest(template Cause cause,
			  template Iu_ReleaseRequest.protocolExtensions exts := *) := {
	initiatingMessage := {
		procedureCode := id_Iu_ReleaseRequest,
		criticality := ignore,
		value_ := {
			iu_ReleaseRequest := {
				protocolIEs := {
					{
						id := id_Cause,
						criticality := reject,
						value_ := {
							cause := cause
						}
					}
				},
				protocolExtensions := exts
			}
		}
	}
}

/*****************************************************************************************************
 * RAB Release
 *****************************************************************************************************/

template (value) RANAP_PDU
ts_RANAP_RabReleaseRequest(template (value) RAB_ID rab_id, template (value) Cause cause,
			   template (omit) RAB_ReleaseRequest.protocolExtensions exts := omit) := {
	initiatingMessage := {
		procedureCode := id_RAB_ReleaseRequest,
		criticality := ignore,
		value_ := {
			rAB_ReleaseRequest := {
				protocolIEs := {
					{
						id := id_RAB_ReleaseList,
						criticality := ignore,
						value_ := {
							rAB_ReleaseList := {{
								{
									id := id_RAB_ReleaseItem,
									criticality := ignore,
									value_ := {
										rAB_ReleaseItem := {
											rAB_ID := rab_id,
											cause := cause,
											iE_Extensions := omit
										}
									}
								}
							}}
						}
					}
				},
				protocolExtensions := exts
			}
		}
	}
}
template RANAP_PDU
tr_RANAP_RabReleaseRequest(template RAB_ID rab_id, template Cause cause,
			   template RAB_ReleaseRequest.protocolExtensions exts := *) := {
	initiatingMessage := {
		procedureCode := id_RAB_ReleaseRequest,
		criticality := ignore,
		value_ := {
			rAB_ReleaseRequest := {
				protocolIEs := {
					{
						id := id_RAB_ReleaseList,
						criticality := ignore,
						value_ := {
							rAB_ReleaseList := {{
								{
									id := id_RAB_ReleaseItem,
									criticality := ignore,
									value_ := {
										rAB_ReleaseItem := {
											rAB_ID := rab_id,
											cause := cause,
											iE_Extensions := *
										}
									}
								}
							}}
						}
					}
				},
				protocolExtensions := exts
			}
		}
	}
}


/*****************************************************************************************************
 * Iu Release
 *****************************************************************************************************/

template (value) RANAP_PDU
ts_RANAP_IuReleaseCommand(template (value) Cause cause,
			  template (omit) Iu_ReleaseCommand.protocolExtensions exts := omit) := {
	initiatingMessage := {
		procedureCode := id_Iu_Release,
		criticality := reject,
		value_ := {
			iu_ReleaseCommand := {
				protocolIEs := {
					{
						id := id_Cause,
						criticality := ignore,
						value_ := {
							cause := cause
						}
					}
				},
				protocolExtensions := exts
			}
		}
	}
}
template RANAP_PDU
tr_RANAP_IuReleaseCommand(template Cause cause,
			  template Iu_ReleaseCommand.protocolExtensions exts := *) := {
	initiatingMessage := {
		procedureCode := id_Iu_Release,
		criticality := reject,
		value_ := {
			iu_ReleaseCommand := {
				protocolIEs := {
					{
						id := id_Cause,
						criticality := ignore,
						value_ := {
							cause := cause
						}
					}
				},
				protocolExtensions := exts
			}
		}
	}
}

template (value) RANAP_PDU
ts_RANAP_IuReleaseComplete(template (omit) Iu_ReleaseComplete.protocolIEs ies := {},
			   template (omit) Iu_ReleaseComplete.protocolExtensions exts := omit) := {
	successfulOutcome := {
		procedureCode := id_Iu_Release,
		criticality := reject,
		value_ := {
			iu_ReleaseComplete := {
				protocolIEs := ies,
				protocolExtensions := exts
			}
		}
	}
}
template RANAP_PDU
tr_RANAP_IuReleaseComplete(template Iu_ReleaseComplete.protocolIEs ies := *,
			   template Iu_ReleaseComplete.protocolExtensions exts := *) := {
	successfulOutcome := {
		procedureCode := id_Iu_Release,
		criticality := reject,
		value_ := {
			iu_ReleaseComplete:= {
				protocolIEs := ies,
				protocolExtensions := exts
			}
		}
	}
}

/*****************************************************************************************************
 * Paging
 *****************************************************************************************************/

template (value) RANAP_PDU
ts_RANAP_Paging(template (value) CN_DomainIndicator dom, template (value) IMSI imsi,
		template (omit) TemporaryUE_ID temp_id := omit,
		template (omit) Paging.protocolExtensions exts := omit) := {
	initiatingMessage := {
		procedureCode := id_Paging,
		criticality := ignore,
		value_ := {
			paging := {
				protocolIEs := {
					{
						id := id_CN_DomainIndicator,
						criticality := ignore,
						value_ := {
							cN_DomainIndicator := dom
						}
					}, {
						id := id_PermanentNAS_UE_ID,
						criticality := ignore,
						value_ := {
							permanentNAS_UE_ID := {
								iMSI := imsi
							}
						}
					}
				},
				protocolExtensions := exts
			}
		}
	}
}
template RANAP_PDU
tr_RANAP_Paging(template CN_DomainIndicator dom, template IMSI imsi,
		template Paging.protocolExtensions exts := *) := {
	initiatingMessage := {
		procedureCode := id_Paging,
		criticality := ignore,
		value_ := {
			paging := {
				protocolIEs := {
					{
						id := id_CN_DomainIndicator,
						criticality := ignore,
						value_ := {
							cN_DomainIndicator := dom
						}
					}, {
						id := id_PermanentNAS_UE_ID,
						criticality := ignore,
						value_ := {
							permanentNAS_UE_ID := {
								iMSI := imsi
							}
						}
					}, *
				},
				protocolExtensions := exts
			}
		}
	}
}



/*****************************************************************************************************
 * Common ID
 *****************************************************************************************************/

template (value) RANAP_PDU
ts_RANAP_CommonId(template (value) IMSI imsi,
		template (omit) CommonID.protocolExtensions exts := omit) := {
	initiatingMessage := {
		procedureCode := id_CommonID,
		criticality := ignore,
		value_ := {
			commonID := {
				protocolIEs := {
					{
						id := id_PermanentNAS_UE_ID,
						criticality := ignore,
						value_ := {
							permanentNAS_UE_ID := {
								iMSI := imsi
							}
						}
					}
				},
				protocolExtensions := exts
			}
		}
	}
}
template RANAP_PDU
tr_RANAP_CommonId(template IMSI imsi,
		  template CommonID.protocolExtensions exts := *) := {
	initiatingMessage := {
		procedureCode := id_CommonID,
		criticality := ignore,
		value_ := {
			commonID := {
				protocolIEs := {
					{
						id := id_PermanentNAS_UE_ID,
						criticality := ignore,
						value_ := {
							permanentNAS_UE_ID := {
								iMSI := imsi
							}
						}
					}
				},
				protocolExtensions := exts
			}
		}
	}
}

/*****************************************************************************************************
 * Initial UE Message
 *****************************************************************************************************/

template (value) RANAP_PDU
ts_RANAP_initialUE_CS(template (value) LAI lai, template (value) SAI sai,
		      template (value) NAS_PDU nas,
		      template (value) IuSignallingConnectionIdentifier sigc_id,
		      template (value) GlobalRNC_ID grnc_id,
		      template (omit) InitialUE_Message.protocolExtensions exts := omit) := {
	initiatingMessage := {
		procedureCode := id_InitialUE_Message,
		criticality := ignore,
		value_ := {
			initialUE_Message := {
				protocolIEs := {
					{
						id := id_CN_DomainIndicator,
						criticality := ignore,
						value_ := {
							cN_DomainIndicator := cs_domain
						}
					}, {
						id := id_LAI,
						criticality := ignore,
						value_ := {
							lAI := lai
						}
					}, {
						id := id_SAI,
						criticality := ignore,
						value_ := {
							sAI := sai
						}
					}, {
						id := id_NAS_PDU,
						criticality := ignore,
						value_ := {
							nAS_PDU := nas
						}
					}, {
						id := id_IuSigConId,
						criticality := ignore,
						value_ := {
							iuSignallingConnectionIdentifier := sigc_id
						}
					}, {
						id := id_GlobalRNC_ID,
						criticality := ignore,
						value_ := {
							globalRNC_ID := grnc_id
						}
					}
				},
				protocolExtensions := exts
			}
		}
	}
}
template RANAP_PDU
tr_RANAP_initialUE_CS(template LAI lai, template SAI sai,
		      template NAS_PDU nas,
		      template IuSignallingConnectionIdentifier sigc_id,
		      template GlobalRNC_ID grnc_id,
		      template InitialUE_Message.protocolExtensions exts := *) := {
	initiatingMessage := {
		procedureCode := id_InitialUE_Message,
		criticality := ignore,
		value_ := {
			initialUE_Message := {
				protocolIEs := {
					{
						id := id_CN_DomainIndicator,
						criticality := ignore,
						value_ := {
							cN_DomainIndicator := cs_domain
						}
					}, {
						id := id_LAI,
						criticality := ignore,
						value_ := {
							lAI := lai
						}
					}, {
						id := id_SAI,
						criticality := ignore,
						value_ := {
							sAI := sai
						}
					}, {
						id := id_NAS_PDU,
						criticality := ignore,
						value_ := {
							nAS_PDU := nas
						}
					}, {
						id := id_IuSigConId,
						criticality := ignore,
						value_ := {
							iuSignallingConnectionIdentifier := sigc_id
						}
					}, {
						id := id_GlobalRNC_ID,
						criticality := ignore,
						value_ := {
							globalRNC_ID := grnc_id
						}
					}
				},
				protocolExtensions := exts
			}
		}
	}
}

template (value) RANAP_PDU
ts_RANAP_initialUE_PS(template (value) LAI lai, template (value) RAC rac, template (value) SAI sai,
		      template (value) NAS_PDU nas,
		      template (value) IuSignallingConnectionIdentifier sigc_id,
		      template (value) GlobalRNC_ID grnc_id,
		      template (omit) InitialUE_Message.protocolExtensions exts := omit) := {
	initiatingMessage := {
		procedureCode := id_InitialUE_Message,
		criticality := ignore,
		value_ := {
			initialUE_Message := {
				protocolIEs := {
					{
						id := id_CN_DomainIndicator,
						criticality := ignore,
						value_ := {
							cN_DomainIndicator := ps_domain
						}
					}, {
						id := id_LAI,
						criticality := ignore,
						value_ := {
							lAI := lai
						}
					}, {
						id := id_RAC,
						criticality := ignore,
						value_ := {
							rAC := rac
						}
					}, {
						id := id_SAI,
						criticality := ignore,
						value_ := {
							sAI := sai
						}
					}, {
						id := id_NAS_PDU,
						criticality := ignore,
						value_ := {
							nAS_PDU := nas
						}
					}, {
						id := id_IuSigConId,
						criticality := ignore,
						value_ := {
							iuSignallingConnectionIdentifier := sigc_id
						}
					}, {
						id := id_GlobalRNC_ID,
						criticality := ignore,
						value_ := {
							globalRNC_ID := grnc_id
						}
					}
				},
				protocolExtensions := exts
			}
		}
	}
}
template RANAP_PDU
tr_RANAP_initialUE_PS(template LAI lai, template RAC rac, template SAI sai,
		      template NAS_PDU nas,
		      template IuSignallingConnectionIdentifier sigc_id,
		      template GlobalRNC_ID grnc_id,
		      template InitialUE_Message.protocolExtensions exts := *) := {
	initiatingMessage := {
		procedureCode := id_InitialUE_Message,
		criticality := ignore,
		value_ := {
			initialUE_Message := {
				protocolIEs := {
					{
						id := id_CN_DomainIndicator,
						criticality := ignore,
						value_ := {
							cN_DomainIndicator := ps_domain
						}
					}, {
						id := id_LAI,
						criticality := ignore,
						value_ := {
							lAI := lai
						}
					}, {
						id := id_RAC,
						criticality := ignore,
						value_ := {
							rAC := rac
						}
					}, {
						id := id_SAI,
						criticality := ignore,
						value_ := {
							sAI := sai
						}
					}, {
						id := id_NAS_PDU,
						criticality := ignore,
						value_ := {
							nAS_PDU := nas
						}
					}, {
						id := id_IuSigConId,
						criticality := ignore,
						value_ := {
							iuSignallingConnectionIdentifier := sigc_id
						}
					}, {
						id := id_GlobalRNC_ID,
						criticality := ignore,
						value_ := {
							globalRNC_ID := grnc_id
						}
					}
				},
				protocolExtensions := exts
			}
		}
	}
}

/*****************************************************************************************************
 * Direct Transfer
 *****************************************************************************************************/

private function f_gen_ts_dt_ies(template (value) NAS_PDU nas,
				 template (omit) SAPI sapi,
				 template (value) DirectTransfer.protocolIEs opt_ies)
return DirectTransfer.protocolIEs {
	var DirectTransfer.protocolIEs ies := {
		/* NAS PDU is mandatory */
		{
			id := id_NAS_PDU,
			criticality := ignore,
			value_ := {
				nAS_PDU := valueof(nas)
			}
		}
	};

	/* Optional IEs, e.g. LAI, RAC, SAI */
	ies := ies & valueof(opt_ies);

	/* Optional SAPI is the last IE */
	if (isvalue(sapi)) {
		ies := ies & {{
			id := id_SAPI,
			criticality := ignore,
			value_ := {
				sAPI := valueof(sapi)
			}
		}};
	}

	return ies;
}

private function f_gen_tr_dt_ies(template NAS_PDU nas,
				 template SAPI sapi,
				 template DirectTransfer.protocolIEs opt_ies)
return template DirectTransfer.protocolIEs {
	var template DirectTransfer.protocolIEs ies := {
		/* NAS PDU is mandatory */
		{
			id := id_NAS_PDU,
			criticality := ignore,
			value_ := {
				nAS_PDU := nas
			}
		}
	};

	/* Optional IEs start from index 1 */
	var integer idx := 1;

	/* Optional IEs, e.g. LAI, RAC, SAI */
	if (istemplatekind(opt_ies, "*")) {
		ies[idx] := *;
		idx := idx + 1;
	} else if (not istemplatekind(opt_ies, "omit")) {
		for (var integer i := 0; i < lengthof(opt_ies); i := i + 1) {
			ies[idx] := opt_ies[idx];
			idx := idx + 1;
		}
	}

	/* Optional SAPI is the last IE */
	if (istemplatekind(sapi, "*")) {
		ies[idx] := *;
	} else if (not istemplatekind(sapi, "omit")) {
		ies[idx] := {
			id := id_SAPI,
			criticality := ignore,
			value_ := {
				sAPI := sapi
			}
		};
	}

	return ies;
}

template (value) RANAP_PDU
ts_RANAP_DirectTransfer(template (value) NAS_PDU nas,
			template (omit) SAPI sapi := omit,
			template (value) DirectTransfer.protocolIEs ies := {},
			template (omit) DirectTransfer.protocolExtensions exts := omit) := {
	initiatingMessage := {
		procedureCode := id_DirectTransfer,
		criticality := ignore,
		value_ := {
			directTransfer := {
				protocolIEs := f_gen_ts_dt_ies(nas, sapi, ies),
				protocolExtensions := exts
			}
		}
	}
}
template RANAP_PDU
tr_RANAP_DirectTransfer(template NAS_PDU nas,
			template SAPI sapi := *,
			template DirectTransfer.protocolIEs ies := *,
			template DirectTransfer.protocolExtensions exts := *) := {
	initiatingMessage := {
		procedureCode := id_DirectTransfer,
		criticality := ignore,
		value_ := {
			directTransfer := {
				protocolIEs := f_gen_tr_dt_ies(nas, sapi, ies),
				protocolExtensions := exts
			}
		}
	}
}


/*****************************************************************************************************
 * RAB Assignment Request
 *****************************************************************************************************/

template (value) RAB_Parameters ts_RabParams := {
	trafficClass := conversational,
	rAB_AsymmetryIndicator := symmetric_bidirectional,
	maxBitrate := { 12200 },
	guaranteedBitRate := { 12200 },
	deliveryOrder := delivery_order_requested,
	maxSDU_Size := 244,
	sDU_Parameters := {
		{
			sDU_ErrorRatio := { mantissa := 1, exponent := 5, iE_Extensions := omit },
			residualBitErrorRatio := { mantissa := 1, exponent := 6, iE_Extensions := omit },
			deliveryOfErroneousSDU := yes,
			sDU_FormatInformationParameters := {
				{
					subflowSDU_Size := 81,
					rAB_SubflowCombinationBitRate := omit,
					iE_Extensions := omit
				}, {
					subflowSDU_Size := 39,
					rAB_SubflowCombinationBitRate := omit,
					iE_Extensions := omit
				}
			},
			iE_Extensions := omit
		}, {
			sDU_ErrorRatio := omit,
			residualBitErrorRatio := { mantissa := 1, exponent := 3, iE_Extensions := omit },
			deliveryOfErroneousSDU := no_error_detection_consideration,
			sDU_FormatInformationParameters := {
				{
					subflowSDU_Size := 103,
					rAB_SubflowCombinationBitRate := omit,
					iE_Extensions := omit
				}, {
					subflowSDU_Size := 0,
					rAB_SubflowCombinationBitRate := omit,
					iE_Extensions := omit
				}
			},
			iE_Extensions := omit
		}, {
			sDU_ErrorRatio := omit,
			residualBitErrorRatio := { mantissa := 5, exponent := 3, iE_Extensions := omit },
			deliveryOfErroneousSDU := no_error_detection_consideration,
			sDU_FormatInformationParameters := {
				{
					subflowSDU_Size := 60,
					rAB_SubflowCombinationBitRate := omit,
					iE_Extensions := omit
				}, {
					subflowSDU_Size := 0,
					rAB_SubflowCombinationBitRate := omit,
					iE_Extensions := omit
				}
			},
			iE_Extensions := omit
		}
	},
	transferDelay := 80,
	trafficHandlingPriority := omit,
	allocationOrRetentionPriority := {
		priorityLevel := 15,
		pre_emptionCapability := shall_not_trigger_pre_emption,
		pre_emptionVulnerability := pre_emptable,
		queuingAllowed := queueing_not_allowed,
		iE_Extensions := omit
	},
	sourceStatisticsDescriptor := omit,
	relocationRequirement := omit,
	iE_Extensions := omit
}

template (value) UserPlaneInformation ts_UserPlaneInfo := {
	userPlaneMode := support_mode_for_predefined_SDU_sizes,
	uP_ModeVersions := '0000000000000010'B,
	iE_Extensions := omit
}

template (value) TransportLayerInformation ts_TLI(template (value) TransportLayerAddress tla,
						  template (value) BindingID binding_id) := {
	transportLayerAddress := tla,
	iuTransportAssociation := {
		bindingID := binding_id
	},
	iE_Extensions := omit
}
template TransportLayerInformation tr_TLI(template TransportLayerAddress tla,
					  template BindingID binding_id) := {
	transportLayerAddress := tla,
	iuTransportAssociation := {
		bindingID := binding_id
	},
	iE_Extensions := *
}

template (value) RAB_SetupOrModifyList ts_RAB_SML(template (value) RAB_ID rab_id,
						  template (value) TransportLayerAddress tla,
						  template (value) BindingID binding_id) := { {
	{
		id := id_RAB_SetupOrModifyItem,
		firstCriticality := reject,
		firstValue := {
			rAB_SetupOrModifyItemFirst := {
				rAB_ID := rab_id,
				nAS_SynchronisationIndicator := omit,
				rAB_Parameters := ts_RabParams,
				userPlaneInformation := ts_UserPlaneInfo,
				transportLayerInformation := ts_TLI(tla, binding_id),
				service_Handover := omit,
				iE_Extensions := omit
			}
		},
		secondCriticality := ignore,
		secondValue := {
			rAB_SetupOrModifyItemSecond := {
				pDP_TypeInformation := omit,
				dataVolumeReportingIndication := omit,
				dl_GTP_PDU_SequenceNumber := omit,
				ul_GTP_PDU_SequenceNumber := omit,
				dl_N_PDU_SequenceNumber := omit,
				ul_N_PDU_SequenceNumber := omit,
				iE_Extensions := omit
			}
		}
	}
} }
template RAB_SetupOrModifyList tr_RAB_SML(template RAB_ID rab_id,
					  template TransportLayerAddress tla,
					  template BindingID binding_id) := { {
	{
		id := id_RAB_SetupOrModifyItem,
		firstCriticality := reject,
		firstValue := {
			rAB_SetupOrModifyItemFirst := {
				rAB_ID := rab_id,
				nAS_SynchronisationIndicator := *,
				rAB_Parameters := ts_RabParams,
				userPlaneInformation := ts_UserPlaneInfo,
				transportLayerInformation := tr_TLI(tla, binding_id),
				service_Handover := *,
				iE_Extensions := *
			}
		},
		secondCriticality := ignore,
		secondValue := {
			rAB_SetupOrModifyItemSecond := {
				pDP_TypeInformation := omit,
				dataVolumeReportingIndication := omit,
				dl_GTP_PDU_SequenceNumber := omit,
				ul_GTP_PDU_SequenceNumber := omit,
				dl_N_PDU_SequenceNumber := omit,
				ul_N_PDU_SequenceNumber := omit,
				iE_Extensions := omit
			}
		}
	}
} }


template (value) RANAP_PDU
ts_RANAP_RabAssReq(template (value) RAB_SetupOrModifyList rab_sml,
		   template (omit) RAB_AssignmentRequest.protocolExtensions exts := omit) := {
	initiatingMessage := {
		procedureCode := id_RAB_Assignment,
		criticality := reject,
		value_ := {
			rAB_AssignmentRequest := {
				protocolIEs := {
					{
						id := id_RAB_SetupOrModifyList,
						criticality := reject,
						value_ := {
							rAB_SetupOrModifyList := rab_sml
						}
					}
				},
				protocolExtensions := exts
			}
		}
	}
}
template RANAP_PDU
tr_RANAP_RabAssReq(template RAB_SetupOrModifyList rab_sml,
		   template RAB_AssignmentRequest.protocolExtensions exts := *) := {
	initiatingMessage := {
		procedureCode := id_RAB_Assignment,
		criticality := reject,
		value_ := {
			rAB_AssignmentRequest := {
				protocolIEs := {
					{
						id := id_RAB_SetupOrModifyList,
						criticality := ignore,
						value_ := {
							rAB_SetupOrModifyList := rab_sml
						}
					}
				},
				protocolExtensions := exts
			}
		}
	}
}


template (value) RANAP_PDU
ts_RANAP_RabAssResp(template (value) RAB_SetupOrModifiedList rab_sml,
		    template (omit) RAB_AssignmentResponse.protocolExtensions exts := omit) := {
	outcome := {
		procedureCode := id_RAB_Assignment,
		criticality := reject,
		value_ := {
			rAB_AssignmentResponse := {
				protocolIEs := {
					{
						id := id_RAB_SetupOrModifiedList,
						criticality := ignore,
						value_ := {
							rAB_SetupOrModifiedList := rab_sml
						}
					}
					/* RAB-ReleasedList */
					/* RAB-QueuedList */
					/* RAB-FailedList */
					/* RAB-ReleaseFailedList */
				},
				protocolExtensions := exts
			}
		}
	}
}
template RANAP_PDU
tr_RANAP_RabAssResp(template RAB_SetupOrModifiedList rab_sml,
		    template RAB_AssignmentResponse.protocolExtensions exts := *) := {
	outcome := {
		procedureCode := id_RAB_Assignment,
		criticality := reject,
		value_ := {
			rAB_AssignmentResponse := {
				protocolIEs := {
					{
						id := id_RAB_SetupOrModifiedList,
						criticality := ignore,
						value_ := {
							rAB_SetupOrModifiedList := rab_sml
						}
					}, *
					/* RAB-ReleasedList */
					/* RAB-QueuedList */
					/* RAB-FailedList */
					/* RAB-ReleaseFailedList */
				},
				protocolExtensions := exts
			}
		}
	}
}


/*****************************************************************************************************
 *
 *****************************************************************************************************/

/* extract the L3 (NAS) from a given RANAP message */
function f_ranap_extract_l3(RANAP_PDU ranap) return template (omit) octetstring
{
	var integer i;

	if (match(ranap, tr_RANAP_initialUE_CS(?, ?, ?, ?, ?)) or
	    match(ranap, tr_RANAP_initialUE_PS(?, ?, ?, ?, ?, ?)) ) {
		var InitialUE_Message.protocolIEs ies := ranap.initiatingMessage.value_.initialUE_Message.protocolIEs;
		for (i := 0; i < lengthof(ies); i := i+1) {
			if (ies[i].id == id_NAS_PDU) {
				return ies[i].value_.nAS_PDU;
			}
		}
	} else if (match(ranap, tr_RANAP_DirectTransfer(?))) {
		var DirectTransfer.protocolIEs ies := ranap.initiatingMessage.value_.directTransfer.protocolIEs;
		for (i := 0; i < lengthof(ies); i := i+1) {
			if (ies[i].id == id_NAS_PDU) {
				return ies[i].value_.nAS_PDU;
			}
		}
	} else {
		/* relocationInformation not supported yet*/
	}
	return omit;
}

function f_ranap_extract_sapi(RANAP_PDU ranap) return template (omit) SAPI
{
	var integer i;

	/* InitialUE message has no SAPI */
	if (match(ranap, tr_RANAP_DirectTransfer(?, omit))) {
		var DirectTransfer.protocolIEs ies := ranap.initiatingMessage.value_.directTransfer.protocolIEs;
		for (i := 0; i < lengthof(ies); i := i+1) {
			if (ies[i].id == id_SAPI) {
				return ies[i].value_.sAPI;
			}
		}
	}
	return omit;
}


}
