LTE X2AP C++ Sample Code Using OSS ASN.1 Tools


This sample is provided as part of the OSS ASN.1 Tools trial and commercial shipments. The source code and related files are listed below for reference.

The sample demonstrates how to use the OSS ASN.1 Tools to process messages for the 3GPP LTE X2AP standard (TS 36.423 version 19.0.0).

It runs on Linux on x86-64 as an example and illustrates how to decode, inspect, and create LTE X2AP messages using the OSS ASN.1 Tools API.

The sample reads X2AP messages from .per files, decodes and prints them, accesses their components, and creates and encodes successful outcome messages.

A makefile is included for building and running the test program using the OSS ASN.1/C++ library.

To explore more samples (LTE RRC, 5G RRC, S1AP, X2AP, NGAP), visit the main Sample Code page.

Overview

This sample shows how to:

  • Initialize the OSS ASN.1/C++ runtime for the LTE X2AP schema.
  • Read a PER-encoded X2AP message from an input file.
  • Decode and print LTE X2AP messages.
  • Create and encode a successful outcome message.
  • Build and run the sample test program with a makefile on Linux.

Files in This Sample

The files listed below are included in the OSS ASN.1 Tools trial and commercial shipments and are used by this sample program:

File Description
README.TXT Instructions and sample overview.
*.asn ASN.1 source files that describe the 3GPP LTE X2AP protocol (TS 36.423), used with this program example.
X2AP-PDU_HandoverRequest_bin.per Valid PER-encoded X2AP message (HandoverRequest). It should pass testing.
tx2ap.cpp Simple C++ program that shows how to work with LTE X2AP protocol data. It reads input messages from files, decodes and prints them, accesses their components, and creates and encodes successful outcome messages.
makefile Makefile that builds and runs the sample test.
makefile.rtoed Makefile that builds and runs the sample test using RTOED.
gui/ ASN.1 Studio project for viewing/compiling schema and generating sample data.

Build and Run Instructions

(Installation instructions for the OSS ASN.1 Tools are included in all trial and commercial shipments.)

To build and run this sample, install a trial or licensed version of the OSS ASN.1 Tools for C++.

1. Generate C++ source and header files (runtime-only shipments)

If your shipment is runtime-only, generate the .cpp and .h files by running:

make cross

This creates a samples/cross directory with:

  • the required .asn files
  • scripts to run the OSS ASN.1/C++ compiler (asn1cpl.sh or asn1cpl.bat)
2. Build and run the sample
make

This command compiles the sample C++ source, links it with the OSS ASN.1/C++ static library, and executes the test. To use another type of library in the shipment (such as a shared library), set the A makefile variable, for example:

make A=so
3. Clean up generated files
make clean
4. Other Platforms

Note: The C source code in this sample is platform-independent. Linux commands are shown as an example, but equivalent samples and build instructions are available for Windows, macOS, and other platforms. For help with platform-specific instructions, please contact OSS Support.

Code Listing: tx2ap.cpp

The following listing shows the main C++ source file for this sample test program, tx2ap.cpp. It demonstrates how to read PER-encoded LTE X2AP messages from files, decode and print them, and create and encode a successful outcome message using the OSS ASN.1 Tools API.

Show tx2ap.cpp source code
/*****************************************************************************/
/*  Copyright (C) 2025 OSS Nokalva, Inc.  All rights reserved.               */
/*****************************************************************************/
/* THIS FILE IS PROPRIETARY MATERIAL OF OSS NOKALVA, INC.                    */
/* AND MAY BE USED ONLY BY DIRECT LICENSEES OF OSS NOKALVA, INC.             */
/* THIS FILE MAY NOT BE DISTRIBUTED.                                         */
/* THIS COPYRIGHT STATEMENT MAY NOT BE REMOVED.                              */
/* THIS SAMPLE PROGRAM IS PROVIDED AS IS. THE SAMPLE PROGRAM AND ANY RESULTS */
/* OBTAINED FROM IT ARE PROVIDED WITHOUT ANY WARRANTIES OR REPRESENTATIONS,  */
/* EXPRESS, IMPLIED OR STATUTORY.                                            */
/*****************************************************************************/

/*
 * A demonstrative example for handling 3GPP LTE X2AP protocol data in ASN.1/C++
 */
#include <errno.h>
#include "x2ap.h"

/*
 * Auxiliary function to make output prettier.
 */
void printBorder()
{
    printf("-------------------------------------------------------\n");
}

char *filesDir; /* The directory where input files reside. It is set to the
		 * command line parameter if any and to the directory where
		 * the sample is started, otherwise.
		 */


/*
 * A simple class used to report non-ASN.1/C++ errors (such as a failure to
 * create a socket) to the application. You may use any alternative error
 * handling if you wish.
 */

class NonASN1Exception {
private:
    const char *message;	/* can contain C format specifications */
    const char *extra_data;	/* data handled by fmt. specifications (if any) */
    int errcode;
public:
    NonASN1Exception(const char *msg, int code = 0,
	    const char *extd = NULL);
    NonASN1Exception(const NonASN1Exception & that);
    const char *get_message() const;
    const char *get_extra_data() const;
    int get_errcode() const;
};

NonASN1Exception::NonASN1Exception(const char *msg, int code, const char *extd)
{
    message = msg;
    extra_data = extd;
    errcode = code;
}

NonASN1Exception::NonASN1Exception(const NonASN1Exception & that)
{
    message = that.message;
    errcode = that.errcode;
    extra_data = that.extra_data;
}

const char *NonASN1Exception::get_message() const
{
    return message;
}

const char *NonASN1Exception::get_extra_data() const
{
    return extra_data;
}

int NonASN1Exception::get_errcode() const
{
    return errcode;
}

/*
 * FUNCTION     printHexString() prints data (octet string) as a sequence of
 *              hexadecimal digits 'XXXX...'H
 *
 * PARAMETERS
 *    ctl       ASN.1/C++ control object
 *    value     reference to input data (OssString object)
 */
void printHexString(OssControl *ctl, const OssString &value)
{
    ctl->printHex(value.get_buffer(), value.length());
}

/*
 * FUNCTION     printHexBitString() prints data (bit string) as a sequence of
 *              hexadecimal digits 'XXXX...'H
 *
 * PARAMETERS
 *    ctl       ASN.1/C++ control object
 *    value     reference to input data (OssBitString object)
 */
void printHexBitString(OssControl *ctl, const OssBitString &value)
{
    ctl->printHex((const char *)value.get_buffer(), (value.length() + 7) / 8);
}

/*
 * FUNCTION     Helper function to open file in the specified directory.
 *
 * PARAMETERS
 *     directoryName    directory where fileName resides
 *     fileName         file to open
 *
 * RETURNS      pointer to file on success, NULL on failure
 */
FILE * openInputFile(char *directoryName, const char *fileName)
{
    char *path;
    FILE *fv;
    const char kPathSeparator =
#ifdef _WIN32
				'\\';
#else
				'/';
#endif

    if (directoryName) {
	size_t dLength = strlen(directoryName);

	if (NULL == (path = (char *)asn1Malloc(dLength + strlen(fileName) + 2))) {
	    return NULL;
	}

	memcpy(path, directoryName, dLength);
	if (path[dLength - 1] != kPathSeparator)
	    path[dLength++] = kPathSeparator;
	strcpy(path+dLength, fileName);
    } else {
	path = (char *) fileName;
    }

    if (!(fv = fopen(path, "rb"))) {
	printf("Failed to open the '%s' file. Restart the sample program using the file "
		"location as the input parameter.\n", path);
    }

    if (path != fileName)
	asn1Free(path);

    return fv;
}

/*
 * FUNCTION     readEncodingFromFile() reads serialized message from specified
 *              file
 *
 * PARAMETERS
 *    filename  name of file containing serialized message
 *
 * RETURNS      a pointer to a newly allocated EncodedBuffer object containing
 *              the encoding read from the file
 */
static EncodedBuffer *readEncodingFromFile(const char *filename)
{
    long length;
    FILE *in = NULL;
    unsigned char *data = NULL;
    EncodedBuffer *result = new EncodedBuffer();

    try {
	/* Open the file and determine its length */
	in = openInputFile(filesDir, filename);
	if (!in)
	    throw NonASN1Exception(strerror(errno), errno);
	if (fseek(in, 0, SEEK_END))
	    throw NonASN1Exception(strerror(errno), errno);
	length = ftell(in);
	if (length < 0)
	    throw NonASN1Exception(strerror(errno), errno);

	/*
	 * Allocate memory. We need to use asn1Malloc so we can later pass
	 * the ownership of the allocated memory to the EncodedBuffer object.
	 */
	data = (unsigned char *)asn1Malloc(length);
	if (!data)
	    throw NonASN1Exception("No memory", OUT_MEMORY);

	/* Read the file */
	rewind(in);
	if (length != (long)fread(data, 1, (size_t)length, in))
	    throw NonASN1Exception("Error reading the file", 0);
	fclose(in);

	/* Pass the read buffer to the EncodedBuffer */
	result->grab_buffer(length, (char *)data);
	return result;
    } catch (...) {
	if (in)
	    fclose(in);
	if (data)
	    asn1Free(data);
	delete result;
	throw;
    }
}

/* Names of Criticality values */
static const char *Criticalities[] = { "reject", "ignore", "notify" };

/*
 * FUNCTION     printProtocolExtensionsLoc() prints ProtocolExtensionContainer
 *              data.
 *
 * PARAMETERS
 *    ctl       OSS control variable
 *    ie_ext    reference to ProtocolExtensionContainer data to print
 *              (NULL is acceptable, in this case the function does nothing)
 *    indent    indentation
 */
static void printProtocolExtensionsLoc(OssControl *ctl, LocationReportingInformation::iE_Extensions *ie_ext,
	int indent)
{
    int index;
    /*
     * Different messages use iE_Extensions fields, which all are binary compatible
     * if no extensions are defined.
     * We intend to use this function for any protocol extension IE list
     * (except those for which the protocol defines any extensions).
     */
    LocationReportingInformation::iE_Extensions::component *ie;
    x2ap_PDU pdu;

    /* Return if there are no extensions */
    if (!ie_ext)
	return;

    printf("%*s%s includes the following IEs:\n", indent++, "", "iE-Extensions");
    /* Print each IE in the list */
    index = 1;
    for (OssIndex i = ie_ext->first(); i != OSS_NOINDEX; i = ie_ext->next(i)) {
	ie = ie_ext->at(i);

	printf("%*s#%d: id = %2u, criticality = %s\n", indent, "",
		index, ie->get_id(), Criticalities[ie->get_criticality()]);
	if (ie->get_extensionValue().has_decoded()) {
	    /* Extract the open type data */
	    ie->get_extensionValue().get_decoded(pdu);
	    /* Print it in a generic way, using ASN.1 value notation */
	    pdu.print(*ctl);
	} else
	    printf("PDU is not decoded\n");
	index++;
    }
}

/*
 * FUNCTION     printProtocolExtensions() prints ProtocolExtensionContainer
 *              data.
 *
 * PARAMETERS
 *    ctl       OSS control variable
 *    ie_ext    reference to ProtocolExtensionContainer data to print
 *              (NULL is acceptable, in this case the function does nothing)
 *    indent    indentation
 */
static void printProtocolExtensions(OssControl *ctl, ECGI::iE_Extensions *ie_ext,
	int indent)
{
    int index;
    /*
     * Different messages use iE_Extensions fields, which all are binary compatible
     * if no extensions are defined.
     * We intend to use this function for any protocol extension IE list
     * (except those for which the protocol defines any extensions).
     */
    ECGI::iE_Extensions::component *ie;
    x2ap_PDU pdu;

    /* Return if there are no extensions */
    if (!ie_ext)
	return;

    printf("%*s%s includes the following IEs:\n", indent++, "", "iE-Extensions");
    /* Print each IE in the list */
    index = 1;
    for (OssIndex i = ie_ext->first(); i != OSS_NOINDEX; i = ie_ext->next(i)) {
	ie = ie_ext->at(i);

	printf("%*s#%d: id = %2u, criticality = %s\n", indent, "",
		index, ie->get_id(), Criticalities[ie->get_criticality()]);
	if (ie->get_extensionValue().has_decoded()) {
	    /* Extract the open type data */
	    ie->get_extensionValue().get_decoded(pdu);
	    /* Print it in a generic way, using ASN.1 value notation */
	    pdu.print(*ctl);
	} else
	    printf("PDU is not decoded\n");
	index++;
    }
}

/*
 * FUNCTION     printProtocolExtensionsHRList() prints ProtocolExtensionContainer
 *              data.
 *
 * PARAMETERS
 *    ctl       OSS control variable
 *    ie_ext    reference to ProtocolExtensionContainer data to print
 *              (NULL is acceptable, in this case the function does nothing)
 *    indent    indentation
 */
static void printProtocolExtensionsHRList(OssControl *ctl,
	HandoverRestrictionList::iE_Extensions *ie_ext,
	int indent)
{
    int index;
    /*
     * Different messages use iE_Extensions fields, which all are binary compatible
     * if no extensions are defined.
     * We intend to use this function for any protocol extension IE list
     * (except those for which the protocol defines any extensions).
     */
    HandoverRestrictionList::iE_Extensions::component *ie;
    x2ap_PDU pdu;

    /* Return if there are no extensions */
    if (!ie_ext)
	return;

    printf("%*s%s includes the following IEs:\n", indent++, "", "iE-Extensions");
    /* Print each IE in the list */
    index = 1;
    for (OssIndex i = ie_ext->first(); i != OSS_NOINDEX; i = ie_ext->next(i)) {
	ie = ie_ext->at(i);

	printf("%*s#%d: id = %2u, criticality = %s\n", indent, "",
		index, ie->get_id(), Criticalities[ie->get_criticality()]);
	if (ie->get_extensionValue().has_decoded()) {
	    /* Extract the open type data */
	    ie->get_extensionValue().get_decoded(pdu);
	    /* Print it in a generic way, using ASN.1 value notation */
	    pdu.print(*ctl);
	} else
	    printf("PDU is not decoded\n");
	index++;
    }
}


/*
 * FUNCTION     printUE_ContextInformation_ProtocolExtensions()
 *		prints ProtocolExtensionContainer data for UE-ContextInformation
 *		type.
 *
 * PARAMETERS
 *    ctl       OSS control variable
 *    ie_ext    reference to ProtocolExtensionContainer data to print
 *              (NULL is acceptable, in this case the function does nothing)
 *    indent    indentation
 */
static void printUE_ContextInformation_ProtocolExtensions(OssControl *ctl,
	UE_ContextInformation::iE_Extensions *ie_ext, int indent)
{
    int index;
    UE_ContextInformation::iE_Extensions::component *ie;
    x2ap_PDU pdu;

    /* Return if there are no extensions */
    if (!ie_ext)
	return;

    printf("%*s%s includes the following IEs:\n", indent++, "", "iE-Extensions");
    /* Print each IE in the list */
    index = 1;
    for (OssIndex i = ie_ext->first(); i != OSS_NOINDEX; i = ie_ext->next(i)) {
	ie = ie_ext->at(i);

	    printf("%*s#%d: id = %2u, criticality = %s\n", indent, "",
		index, ie->get_id(), Criticalities[ie->get_criticality()]);
        if (ie->get_extensionValue().has_decoded()) {
	    /* Extract the open type data */
	    ie->get_extensionValue().get_decoded(pdu);
	    /*
	     * Print it in a generic way, using ASN.1 value notation. The
	     * only defined extensions (ManagementBasedMDTallowed and MDTPLMNList) are processed
	     * in a generic fashion in this example.
	     */
	    pdu.print(*ctl);

	} else
	    printf("PDU is not decoded\n");
	index++;
    }
}

/*
 * FUNCTION     printTraceActivation_ProtocolExtensions() prints
 *              ProtocolExtensionContainer data for TraceActivation type.
 *
 * PARAMETERS
 *    ctl       OSS control variable
 *    ie_ext    reference to ProtocolExtensionContainer data to print
 *              (NULL is acceptable, in this case the function does nothing)
 *    indent    indentation
 */
static void printTraceActivation_ProtocolExtensions(OssControl *ctl,
	TraceActivation::iE_Extensions *ie_ext, int indent)
{
    int index;
    TraceActivation::iE_Extensions::component *ie;
    x2ap_PDU pdu;

    /* Return if there are no extensions */
    if (!ie_ext)
	return;

    printf("%*s%s includes the following IEs:\n", indent++, "", "iE-Extensions");
    /* Print each IE in the list */
    index = 1;
    for (OssIndex i = ie_ext->first(); i != OSS_NOINDEX; i = ie_ext->next(i)) {
	ie = ie_ext->at(i);

	printf("%*s#%d: id = %2u, criticality = %s\n", indent, "",
		index, ie->get_id(), Criticalities[ie->get_criticality()]);
	if (ie->get_extensionValue().has_decoded()) {
	    /* Extract the open type data */
	    ie->get_extensionValue().get_decoded(pdu);
	    /*
	     * Print it in a generic way, using ASN.1 value notation. The
	     * only defined extension (MDT_Configuration) is processed
	     * in a generic fashion in this example.
	     */
	    pdu.print(*ctl);
	} else
	    printf("PDU is not decoded\n");
	index++;
    }
}


/*
 * FUNCTION     printEutran_ProtocolExtensions() prints
 *              ProtocolExtensionContainer data for LastVisitedEUTRANCellInformation type.
 *
 * PARAMETERS
 *    ctl       OSS control variable
 *    ie_ext    reference to ProtocolExtensionContainer data to print
 *              (NULL is acceptable, in this case the function does nothing)
 *    indent    indentation
 */
static void printEutran_ProtocolExtensions(OssControl *ctl,
	LastVisitedEUTRANCellInformation::iE_Extensions *ie_ext, int indent)
{
    int index;
    LastVisitedEUTRANCellInformation::iE_Extensions::component *ie;
    x2ap_PDU pdu;

    /* Return if there are no extensions */
    if (!ie_ext)
	return;

    printf("%*s%s includes the following IEs:\n", indent++, "", "iE-Extensions");
    /* Print each IE in the list */
    index = 1;
    for (OssIndex i = ie_ext->first(); i != OSS_NOINDEX; i = ie_ext->next(i)) {
	ie = ie_ext->at(i);

	printf("%*s#%d: id = %2u, criticality = %s\n", indent, "",
		index, ie->get_id(), Criticalities[ie->get_criticality()]);
	if (ie->get_extensionValue().has_decoded()) {
	    /* Extract the open type data */
	    ie->get_extensionValue().get_decoded(pdu);
	    /*
	     * Print it in a generic way, using ASN.1 value notation. The
	     * only defined extensions (Time-UE-StayedInCell-EnhancedGranularity and HO-cause) are processed
	     * in a generic fashion in this example.
	     */
	    pdu.print(*ctl);
	} else
	    printf("PDU is not decoded\n");
	index++;
    }
}


/*
 * FUNCTION     printE_RABs_ToBeSetup_List() prints E_RABs_ToBeSetup_List
 *              data. Internal IEs are printed in a generic way, using
 *              ASN.1 value notation.
 *
 * PARAMETERS
 *    ctl       OSS control variable
 *    lst    	reference to E_RABs_ToBeSetup_List data to print
 *    indent    indentation
 */
void printE_RABs_ToBeSetup_List(OssControl *ctl, E_RABs_ToBeSetup_List & lst,
	int indent)
{
    int index;
    OssIndex iter;
    E_RABs_ToBeSetup_List::component *comp;
    E_RABs_ToBeSetup_ItemIEs_Value *ie;
    x2ap_PDU pdu;

    printf("%*s%s includes the following IEs:\n", indent++, "",
	    "e_RABs-ToBeSetup-List");
    index = 1;
    /* Print each IE in the list */
    for (iter = lst.first(); iter != OSS_NOINDEX; iter = lst.next(iter)) {
	comp = lst.at(iter);
	printf("%*s#%d: id = %2u, criticality = %s\n", indent, "", index,
		comp->get_id(), Criticalities[comp->get_criticality()]);
	ie = &comp->get_value();
	if (ie->has_decoded()) {
	    /* Extract the open type data */
	    ie->get_decoded(pdu);
	    /* Print it using ASN.1 value notation */
	    pdu.print(*ctl);
	} else
	    printf("IE is not decoded\n");
	index++;
    }
}

/*
 * FUNCTION     printHistoryInformation() prints UE-HistoryInformation
 *              data.
 *
 * PARAMETERS
 *    ctl       OSS control variable
 *    lst    	reference to E_RABs_ToBeSetup_List data to print
 *    indent    indentation
 */
void printHistoryInformation(OssControl *ctl, UE_HistoryInformation & hi,
	int indent)
{
    int index;
    OssIndex iter;
    LastVisitedCell_Item *comp;
    LastVisitedEUTRANCellInformation *eutran;
    LastVisitedUTRANCellInformation *utran;
    LastVisitedGERANCellInformation *geran;
    ECGI_PDU ecgi_pdu;

    printf("%*s%s includes the following IEs:\n", indent++, "",
	    "HistoryInformation");
    /* Print each IE in the list */
    index = 1;
    /* Print each item in the list */
    for (iter = hi.first(); iter != OSS_NOINDEX; iter = hi.next(iter)) {
	comp = hi.at(iter);
	if ((eutran = comp->get_e_UTRAN_Cell())) {
	    /* E-UTRAN variant is selected */
	    printf("%*s#%d LastVisitedCell-Item: e-UTRAN-Cell:\n",
		    indent, "", index);
	    printf("%*sglobal-Cell-ID:\n", ++indent, "");

	    /* global-Cell-ID is printed using ASN.1 value notation */
	    ecgi_pdu.set_data(eutran->get_global_Cell_ID());
	    ecgi_pdu.print(*ctl);

	    printf("%*sCellType:\n", indent, "");
	    printf("%*sCell-Size: %u\n", ++indent, "",
		    eutran->get_cellType().get_cell_Size());
	    printProtocolExtensions(ctl, eutran->get_cellType().get_iE_Extensions(),
		    indent);
	    printf("%*stime-UE-StayedInCell: %u\n", --indent, "",
		    eutran->get_time_UE_StayedInCell());
	    printEutran_ProtocolExtensions(ctl, eutran->get_iE_Extensions(), indent);
	    indent--;
	} else if ((utran = comp->get_uTRAN_Cell())) {
	    /* UTRAN variant is selected */
	    printf("%*s#%d LastVisitedCell-Item: uTRAN_Cell:\n", indent, "",
		    index);
	    printHexString(ctl, *utran);
	} else if ((geran = comp->get_gERAN_Cell())) {
	    /* GERAN variant is selected */
	    Nulltype *geran_info;

	    printf("%*s#%d LastVisitedCell-Item: gERAN_Cell:\n", indent, "",
		    index);
	    if ((geran_info = geran->get_undefined())) {
		printf("undefined\n");
	    } else {
		printf("Unknown alternative no. %d\n", geran->get_selection());
	    }
	} else {
	    printf("Unknown alternative no. %d\n", comp->get_selection());
	}
	index++;
    }
}

/*
 * FUNCTION     printProtocolIEs() prints ProtocolIE-Container data.
 *
 * PARAMETERS
 *    ctl       OSS control variable
 *    ies       reference to ProtocolIE-Container data to print
 *    indent    indentation
 */
void printProtocolIEs(OssControl *ctl, HandoverRequest::protocolIEs & ies,
	int indent)
{
    int index;		/* IE's ordinal number */
    int index2;		/* Ordinal number of an item in an inner list */
    OssIndex iter, iter2;
    HandoverRequest::protocolIEs::component *ie;

    printf("%*s%s includes the following IEs:\n", indent++, "",
	    "protocolIEs");

    index = 1;
    /* For each IE in the SEQUENCE OF */
    for (iter = ies.first(); iter != OSS_NOINDEX; iter = ies.next(iter)) {
	ie = ies.at(iter);
	printf("\n%*s#%d: id = %2u, criticality = %s\n", indent, "",
		index, ie->get_id(), Criticalities[ie->get_criticality()]);

	indent++;
	index++;
	HandoverRequest_IEs_Value & iedata = ie->get_value();
	if (iedata.has_decoded()) {
	    /* If the IE's data are decoded */
	    switch (ie->get_id()) {
	    case id_Old_eNB_UE_X2AP_ID:
		{
		    /* id-Old-eNB-UE-X2AP-ID */
		    UE_X2AP_ID *ue_id;

		    ue_id = iedata.get_UE_X2AP_ID();
		    printf("%*svalue %s: %u\n", indent, "", "UE-X2AP-ID",
			    *ue_id);
		}
		break;
	    case id_Cause:
		{
		    /* id-Cause */
		    Cause *cause;
		    CauseRadioNetwork *cause_rnw;
		    CauseTransport *cause_trans;
		    CauseProtocol *cause_proto;
		    CauseMisc *cause_misc;

		    cause = iedata.get_Cause();
		    printf("%*svalue %s: ", indent, "", "Cause");
		    if ((cause_rnw = cause->get_radioNetwork())) {
			printf("%s : %d", "radioNetwork", *cause_rnw);
		    } else if ((cause_trans = cause->get_transport())) {
			printf("%s : %d", "transport", *cause_trans);
		    } else if ((cause_proto = cause->get_protocol())) {
			printf("%s : %d", "protocol", *cause_proto);
		    } else if ((cause_misc = cause->get_misc())) {
			printf("%s : %d", "misc", *cause_misc);
		    } else {
			printf("Unknown alternative no. %d", cause->get_selection());
		    }
		    printf("\n");
		}
		break;
	    case id_TargetCell_ID:
		{
		    /* id-TargetCell-ID */
		    ECGI *target;

		    target = iedata.get_ECGI();
		    printf("%*svalue %s:\n", indent, "", "ECGI");
		    indent++;
		    printf("%*s%s: ", indent, "", "pLMN-Identity");
		    printHexString(ctl, target->get_pLMN_Identity());
		    printf("%*s%s: ", indent, "", "eUTRANcellIdentifier");
		    printHexBitString(ctl, target->get_eUTRANcellIdentifier());
		    printProtocolExtensions(ctl, target->get_iE_Extensions(),
			    indent);
		    indent --;
		}
		break;
	    case id_GUMMEI_ID:
		{
		    /* id-GUMMEI-ID */
		    GUMMEI *gummei;

		    gummei = iedata.get_GUMMEI();
		    printf("%*svalue %s:\n", indent, "", "GUMMEI");
		    indent++;
		    printf("%*s%s:\n", indent, "", "gU-Group-ID");
		    indent++;
		    GU_Group_ID & group = gummei->get_gU_Group_ID();
		    /* pLMN-Identity */
		    printf("%*s%s: ", indent, "", "pLMN-Identity");
		    printHexString(ctl, group.get_pLMN_Identity());
		    /* mME-Group-ID */
		    printf("%*s%s: ", indent, "", "mME-Group-ID");
		    printHexString(ctl, group.get_mME_Group_ID());
		    printProtocolExtensions(ctl, group.get_iE_Extensions(),
			    indent);
		    indent--;
		    /* mME-Code */
		    printf("%*s%s: ", indent, "", "mME-Code");
		    printHexString(ctl, gummei->get_mME_Code());
		    printProtocolExtensions(ctl, gummei->get_iE_Extensions(),
			    indent);
		    indent--;
		}
		break;
	    case id_UE_ContextInformation:
		{
		    /* id-UE-ContextInformation */
		    UE_ContextInformation *info;

		    info = iedata.get_UE_ContextInformation();

		    printf("%*svalue %s :\n", indent, "", "UE-ContextInformation");
		    indent++;
		    /* mME-UE-S1AP-ID */
		    printf("%*s%s: %u\n", indent, "", "mME-UE-S1AP-ID",
			    info->get_mME_UE_S1AP_ID());

		    /* uESecurityCapabilities */
		    printf("%*s%s:\n", indent, "", "uESecurityCapabilities");

		    UESecurityCapabilities & seccap =
			    info->get_uESecurityCapabilities();
		    indent++;
		    /* encryptionAlgorithms */
		    printf("%*s%s: ", indent, "", "encryptionAlgorithms");
		    printHexBitString(ctl, seccap.get_encryptionAlgorithms());
		    /* integrityProtectionAlgorithms */
		    printf("%*s%s: ", indent, "", "integrityProtectionAlgorithms");
		    printHexBitString(ctl, seccap.get_integrityProtectionAlgorithms());
		    printProtocolExtensions(ctl, seccap.get_iE_Extensions(),
			    indent);
		    indent--;

		    /* aS_SecurityInformation */
		    printf("%*s%s:\n", indent, "", "aS_SecurityInformation");

		    AS_SecurityInformation & secinf =
			    info->get_aS_SecurityInformation();
		    indent++;
		    /* key_eNB */
		    printf("%*s%s: ", indent, "", "key_eNB");
		    printHexBitString(ctl, secinf.get_key_eNodeB_star());
		    /* nextHopChainingCounter */
		    printf("%*s%s: %u\n", indent, "", "nextHopChainingCounter",
			    secinf.get_nextHopChainingCount());
		    printProtocolExtensions(ctl, secinf.get_iE_Extensions(),
			    indent);
		    indent--;

		    /* uEaggregateMaximumBitRate */
		    printf("%*s%s:\n", indent, "", "uEaggregateMaximumBitRate");

		    UEAggregateMaximumBitRate & rate =
			    info->get_uEaggregateMaximumBitRate();
		    indent++;
		    /* uEaggregateMaximumBitRateDownlink */
		    printf("%*s%s: " ULLONG_FMT "\n", indent, "",
			    "uEaggregateMaximumBitRateDownlink",
			    rate.get_uEaggregateMaximumBitRateDownlink());
		    /* uEaggregateMaximumBitRateUplink */
		    printf("%*s%s: " ULLONG_FMT "\n", indent, "",
			    "uEaggregateMaximumBitRateUplink",
			    rate.get_uEaggregateMaximumBitRateUplink());
		    indent--;

		    /* subscriberProfileIDforRFP is optional */
		    if (info->subscriberProfileIDforRFP_is_present()) {
			printf("%*s%s: %u\n", indent, "",
				"subscriberProfileIDforRFP",
				*info->get_subscriberProfileIDforRFP());
		    }

		    /* e-RABs-ToBeSetup-List */
		    printE_RABs_ToBeSetup_List(ctl,
			    info->get_e_RABs_ToBeSetup_List(), indent);

		    /* rRC-Context */
		    printf("%*s%s: ", indent, "", "rRC-Context");
		    printHexString(ctl, info->get_rRC_Context());

		    /* handoverRestrictionList is optional */
		    HandoverRestrictionList *hrlist =
			    info->get_handoverRestrictionList();

		    if (hrlist) {
			printf("%*s%s:\n", indent, "", "handoverRestrictionList");
			indent++;

			/* servingPLMN */
			printf("%*s%s: ", indent, "", "servingPLMN");
			printHexString(ctl, hrlist->get_servingPLMN());

			/* equivalentPLMNs is optional */
			EPLMNs *eplmns = hrlist->get_equivalentPLMNs();

			if (eplmns) {
			    printf("%*s%s includes the following PLMN-Identity elements:\n",
				    indent++, "", "equivalentPLMNs");
			    /* Print each list element */
			    index2 = 1;
			    for (iter2 = eplmns->first(); iter2 != OSS_NOINDEX;
				    iter2 = eplmns->next(iter2)) {
				printf("%*s#%d: ", indent, "", index2);
				printHexString(ctl, *eplmns->at(iter2));
				index2++;
			    }
			    indent--;
			}

			/* forbiddenTAs is optional */
			ForbiddenTAs *ftas = hrlist->get_forbiddenTAs();

			if (ftas) {
			    printf("%*s%s includes ForbiddenTAs-Item elements:\n",
				    indent++, "", "forbiddenTAs");
			    /* Printing ForbiddenTAs-Item data is omitted */
			    printf("%*s...\n", indent--, "");
			}

			/* forbiddenLAs is optional */
			ForbiddenLAs *flas = hrlist->get_forbiddenLAs();

			if (flas) {
			    printf("%*s%s includes ForbiddenLAs-Item elements:\n",
				    indent++, "", "forbiddenLAs");
			    /* Printing ForbiddenLAs-Item data is omitted */
			    printf("%*s...\n", indent--, "");
			}

			/* forbiddenInterRATs is optional */
			if (hrlist->forbiddenInterRATs_is_present()) {
			    printf("%*s%s: %u\n", indent++, "", "forbiddenInterRATs",
				    *hrlist->get_forbiddenInterRATs());
			}
			printProtocolExtensionsHRList(ctl, hrlist->get_iE_Extensions(),
				indent);
			indent--;
		    }

		    /* locationReportingInformation is optional */
		    LocationReportingInformation *loc =
			    info->get_locationReportingInformation();

		    if (loc) {
			printf("%*s%s:\n", indent, "",
				"locationReportingInformation");
			indent++;

			/* eventType */
			printf("%*s%s: %s\n", indent, "", "eventType",
				(loc->get_eventType() == change_of_serving_cell) ?
				    "change-of-serving-cell" : "unknown");
			/* reportArea */
			printf("%*s%s: %s\n", indent, "", "reportArea",
				(loc->get_reportArea() == ecgi) ?
				    "ecgi" : "unknown");
			printProtocolExtensionsLoc(ctl, loc->get_iE_Extensions(), // roman
				indent);
			indent--;
		    }
		    printUE_ContextInformation_ProtocolExtensions(ctl,
			    info->get_iE_Extensions(), indent);
		    indent--;
		}
		break;
	    case id_UE_HistoryInformation:
		{
		    /* id-UE-HistoryInformation */
		    UE_HistoryInformation *hinfo;

		    hinfo = iedata.get_UE_HistoryInformation();
		    printHistoryInformation(ctl, *hinfo, indent);
		}
		break;
	    case id_TraceActivation:
		{
		    /* id-TraceActivation */
		    TraceActivation *trace;

		    trace = iedata.get_TraceActivation();
		    printf("%*svalue %s :\n", indent, "", "TraceActivation");
		    indent++;
		    /* eUTRANTraceID */
		    printf("%*s%s: ", indent, "", "eUTRANTraceID");
		    printHexString(ctl, trace->get_eUTRANTraceID());
		    /* interfacesToTrace */
		    printf("%*s%s: ", indent, "", "interfacesToTrace");
		    printHexBitString(ctl, trace->get_interfacesToTrace());
		    /* traceDepth */
		    printf("%*s%s: %u\n", indent, "", "traceDepth",
			    trace->get_traceDepth());
		    /* traceCollectionEntityIPAddress */
		    printf("%*s%s: ", indent, "", "traceCollectionEntityIPAddress");
		    printHexBitString(ctl,
			    trace->get_traceCollectionEntityIPAddress());
		    printTraceActivation_ProtocolExtensions(ctl,
			    trace->get_iE_Extensions(), indent);
		    indent--;
		}
		break;
	    case id_CSGMembershipStatus:
		{
		    /* id-CSGMembershipStatus */
		    CSGMembershipStatus  *membstatus;
		    char *MemshipStatus[] = {(char *) "member", (char *) "not-member" };

		    membstatus = iedata.get_CSGMembershipStatus();
	    	    printf("%*svalue %s: %s\n", indent, "", "CSGMembershipStatus",
			    MemshipStatus[*membstatus]);
		}
		break;
	    case id_MobilityInformation:
		{
		    /* id-MobilityInformation */
		    printf("%*svalue %s: ", indent, "", "MobilityInformation");
		    printHexBitString(ctl,
			    *iedata.get_MobilityInformation());
		}
		break;
	    default:
		/* other IEs are printed generically */
		x2ap_PDU ie_pdu;

		iedata.get_decoded(ie_pdu);
		printf("%*s", indent, "");
		ie_pdu.print(*ctl);
	    }
	} else {
	    printf("PDU is not decoded\n");
	}
	indent--;
    }
}

/*
 * FUNCTION     printHandoverRequestMsg() prints an X2AP PDU which contains
 *              a HandoverRequest message.
 *
 * PARAMETERS
 *    ctl       OSS control variable
 *    request   a pointer to the X2AP PDU to print (assuming it contains a
 *              HandoverRequest message)
 */
void printHandoverRequestMsg(OssControl *ctl, X2AP_PDU *request)
{
    InitiatingMessage *initmsg;
    HandoverRequest *hr;

    printf("\nGet message information\n");
    printBorder();

    initmsg = request->get_initiatingMessage();
    if (!initmsg) {
	/* If the message is not an InitiatingMessage */
	printf("Unexpected message id = %d\n", request->get_selection());
	throw NonASN1Exception("Unsupported message type", -1, NULL);
    }

    hr = initmsg->get_value().get_HandoverRequest();
    if (!hr) {
	/* If the message is not a HandoverRequest */
	printf("Unexpected message id = %d\n", initmsg->get_procedureCode());
	throw NonASN1Exception("Unsupported message type", -1, NULL);
    }

    printProtocolIEs(ctl, hr->get_protocolIEs(), 0);
}

/*
 * FUNCTION     createSuccessResponse() creates an X2AP successful outcome
 *              message for a given HandoverRequest request.
 *
 * PARAMETERS
 *    ctl       OSS control object
 *    request   input message (request)
 *    response  pointer to the variable that is to hold the resulting
 *              successful outcome message created by the function
 */
void createSuccessResponse(OssControl *ctl, X2AP_PDU *request,
	X2AP_PDU **response)
{
    InitiatingMessage *initmsg;
    HandoverRequest *hr;
    X2AP_PDU *resp;

    printf("\nCreate response\n");
    printBorder();

    initmsg = request->get_initiatingMessage();
    if (!initmsg) {
	/* If the message is not an InitiatingMessage */
	printf("Unexpected message id = %d\n", request->get_selection());
	throw NonASN1Exception("Unsupported message type", -1, NULL);
    }

    hr = initmsg->get_value().get_HandoverRequest();
    if (!hr) {
	/* If the message is not a HandoverRequired */
	printf("Unexpected message id = %d\n", initmsg->get_procedureCode());
	throw NonASN1Exception("Unsupported message type", -1, NULL);
    }

    /* Create a response message object */
    resp = new X2AP_PDU();

    /* Fill it */
    try {
	SuccessfulOutcome outcome_msg;
	HandoverRequestAcknowledge hra;
	HandoverRequest::protocolIEs &req_ies = hr->get_protocolIEs();
	HandoverRequest::protocolIEs::component *req_ie;
	HandoverRequestAcknowledge::protocolIEs &resp_ies = hra.get_protocolIEs();
	/*
	 * We are filling the response IE list starting from beginning.
	 * However, the OssList class has no function to append a new
	 * component to its tail (it cannot be done efiiciently because
	 * of its single-linked list representation). So, we save an OssList
	 * iterator pointing to the last component of the response IE list.
	 */
	OssIndex resp_tail = OSS_NOINDEX;

	/*
	 * Create successful outcome message from initiating message. Copy
	 * the id-Old-eNB-UE-X2AP-ID IE from input to output.
	 */
	for (OssIndex i = req_ies.first(); i != OSS_NOINDEX;
		i = req_ies.next(i)) {
	    req_ie = req_ies.at(i);
	    if (req_ie->get_id() == id_Old_eNB_UE_X2AP_ID) {
		resp_tail = resp_ies.insert_after(resp_tail,
			*(HandoverRequestAcknowledge::protocolIEs::component *)req_ie);
		/*
		 * The id-Old-eNB-UE-X2AP-ID IE has criticality of reject in
		 * HandoverRequest but criticalty of ignore in HandoverRequestAcknowledge.
		 * So we need to change the criticality.
		 */
		resp_ies.at(resp_tail)->set_criticality(ignore);
	    }
	}

	/* Add New-eNB-UE-X2AP-ID IE to outcome message */
	HandoverRequestAcknowledge::protocolIEs::component resp_ie;
	UE_X2AP_ID new_id;

	resp_ie.set_id(id_New_eNB_UE_X2AP_ID);
	resp_ie.set_criticality(ignore);
	new_id = 456;
	resp_ie.get_value().set_UE_X2AP_ID(new_id);
	resp_tail = resp_ies.insert_after(resp_tail, resp_ie);

	/* Add E-RABs-Admitted-List IE to outcome message */
	E_RABs_Admitted_List list;
	E_RABs_Admitted_List::component list_ie;
	E_RABs_Admitted_Item item;

	item.set_e_RAB_ID(999);

	GTPtunnelEndpoint endpoint;

	endpoint.set_transportLayerAddress(OssBitString(7,
		(unsigned char *)"\x55"));
	endpoint.set_gTP_TEID(OssString(4, "\x01\x02\x03\x04"));
	item.set_uL_GTP_TunnelEndpoint(endpoint);

	endpoint.set_transportLayerAddress(OssBitString(11,
		(unsigned char *)"\x55\x55"));
	endpoint.set_gTP_TEID(OssString(4, "\x05\x06\x07\x08"));
	item.set_dL_GTP_TunnelEndpoint(endpoint);

	list_ie.set_id(id_E_RABs_Admitted_Item);
	list_ie.set_criticality(ignore);
	list_ie.get_value().set_E_RABs_Admitted_Item(item);
	list.prepend(list_ie);

	resp_ie.set_id(id_E_RABs_Admitted_List);
	resp_ie.set_criticality(ignore);
	resp_ie.get_value().set_E_RABs_Admitted_List(list);
	resp_tail = resp_ies.insert_after(resp_tail, resp_ie);

	/* Add TargeteNBtoSource-eNBTransparentContainer IE to outcome message */
	OssString transp_container(1, "\x55");

	resp_ie.set_id(id_TargeteNBtoSource_eNBTransparentContainer);
	resp_ie.set_criticality(ignore);
	resp_ie.get_value().set_TargeteNBtoSource_eNBTransparentContainer(transp_container);
	resp_tail = resp_ies.insert_after(resp_tail, resp_ie);

	/* Construct a response message from the IE list */
	outcome_msg.set_procedureCode(initmsg->get_procedureCode());
	outcome_msg.set_criticality(reject);
	outcome_msg.get_value().set_HandoverRequestAcknowledge(hra);
	resp->set_successfulOutcome(outcome_msg);
	*response = resp;
    } catch (...) {
	/* Cleanup */
	delete resp;
	throw;
    }
}

/*
 * FUNCTION     testX2AP() is used to test X2AP message, the input serialized
 *              pdu is deserialized and printed, then an outcome message
 *              is created, printed and encoded.
 *
 * PARAMETERS
 *    ctl       OSS control object
 *    filename  name of file containing serialized message
 */
static void testX2AP(OssControl *ctl, const char *filename)
{
    EncodedBuffer *encoded_request;
    EncodedBuffer encoded_response;
    X2AP_PDU_PDU pdu;
    X2AP_PDU *request, *response;

    printf("======================================================"
	    "======================\n");
    printf("Read encoding from file: %s\n\n", filename);
    /* Read serialized message from file */
    encoded_request = readEncodingFromFile(filename);
    try {
	printf("Deserialize request\n");
	printBorder();

	/* Decode the input message */
	pdu.decode(*ctl, *encoded_request);

	/* Free memory allocated for encoded message */
	delete encoded_request;
	encoded_request = NULL;

	/* Print the input message in the decoded form */
	printf("\nDeserialized request\n");
	printBorder();
	pdu.print(*ctl);

	/* Access components of the message */
	request = pdu.get_data();
	printHandoverRequestMsg(ctl, request);

	/* Create successful outcome message */
	createSuccessResponse(ctl, request, &response);

	/* Free the decoded input message */
	pdu.free_data(*ctl);

	/* Print the response message */
	pdu.set_data(*response);
	pdu.print(*ctl);

	/* Serialize response */
	printf("\nSerialize response\n");
	pdu.encode(*ctl, encoded_response);
	printBorder();
	printf("\nSerialized response (%lu bytes):\n",
		encoded_response.get_length());
	printBorder();
	encoded_response.print_hex(*ctl);
	printf("\n");

	/* Free memory allocated for outcome message */
	delete response;
    } catch (...) {
	/* Cleanup in case of a possible error */
	delete encoded_request;
	throw;
    }
}

/*
 * Main application routine
 */
int main(int argc, char *argv[])
{
    int retcode;
    filesDir = argc > 1 ? argv[1] : (char *) ".";

    try {
	x2ap_Control ctl;

	/* Set the encoding rules and encoding/decoding flags */
	ctl.setEncodingRules(OSS_PER_ALIGNED);
	ctl.setEncodingFlags(AUTOMATIC_ENCDEC);
	ctl.setDecodingFlags(AUTOMATIC_ENCDEC);
	ctl.setDebugFlags(PRINT_ERROR_MESSAGES | PRINT_DECODING_DETAILS |
		PRINT_ENCODING_DETAILS);

	testX2AP(&ctl, "X2AP-PDU_HandoverRequest_bin.per");
	retcode = 0;
    } catch (ASN1RuntimeException &exc) {
        retcode = exc.get_code();
	printf("An error occurred: code = %d.\n", retcode);
    } catch (NonASN1Exception &exc) {
	printf("NonASN1Exception: ");
	retcode = exc.get_errcode();
	printf(exc.get_message(), exc.get_extra_data(), retcode);
        printf("\n");
        if (!retcode)
	    retcode = -1;
    } catch (...) {
	printf("An unexpected exception occurred.\n");
	retcode =  -1;
    }
    if (!retcode)
	printf("Testing successful.\n");

    return retcode;
}

Expected Output (Excerpt)

This is the expected output when running the sample:

Encoding response message...
Encoding successful.

ASN.1 Schema Excerpt (x2ap.asn)

Show excerpt from x2ap.asn
-- Excerpt from x2ap.asn 3GPP TS 36.423 V19.0.0 (2025-09) 

-- Elementary Procedure definitions
--
-- **************************************************************

X2AP-PDU-Descriptions {
itu-t (0) identified-organization (4) etsi (0) mobileDomain (0) 
eps-Access (21) modules (3) x2ap (2) version1 (1) x2ap-PDU-Descriptions (0) }

DEFINITIONS AUTOMATIC TAGS ::= 

BEGIN

-- **************************************************************
--
-- IE parameter types from other modules.
--
-- **************************************************************

IMPORTS
	Criticality,
	ProcedureCode

FROM X2AP-CommonDataTypes

	CellActivationRequest,
	CellActivationResponse,
	CellActivationFailure,
	ENBConfigurationUpdate,
	ENBConfigurationUpdateAcknowledge,
	ENBConfigurationUpdateFailure,
	ErrorIndication,
	HandoverCancel,
	HandoverReport,
	HandoverPreparationFailure,
	HandoverRequest,
	HandoverRequestAcknowledge,
	LoadInformation,
	PrivateMessage,
	ResetRequest,
	ResetResponse,
	ResourceStatusFailure,
	ResourceStatusRequest,
	ResourceStatusResponse,
	ResourceStatusUpdate, 
	RLFIndication,
	SNStatusTransfer,
	UEContextRelease,
	X2SetupFailure,
	X2SetupRequest,
	X2SetupResponse,
	MobilityChangeRequest,
	MobilityChangeAcknowledge,
	MobilityChangeFailure,
	X2Release,
	X2APMessageTransfer,
	SeNBAdditionRequest,
	SeNBAdditionRequestAcknowledge,
	SeNBAdditionRequestReject,
	SeNBReconfigurationComplete,
	SeNBModificationRequest,
	SeNBModificationRequestAcknowledge,
	SeNBModificationRequestReject,
	SeNBModificationRequired,
	SeNBModificationConfirm,
	SeNBModificationRefuse,
	SeNBReleaseRequest,
	SeNBReleaseRequired,
	SeNBReleaseConfirm,
	SeNBCounterCheckRequest,
	X2RemovalFailure,
	X2RemovalRequest,
	X2RemovalResponse,
	RetrieveUEContextRequest,
	RetrieveUEContextResponse,
	RetrieveUEContextFailure,
	SgNBAdditionRequest,
	SgNBAdditionRequestAcknowledge,
	SgNBAdditionRequestReject,
	SgNBReconfigurationComplete,
	SgNBModificationRequest,
	SgNBModificationRequestAcknowledge,
	SgNBModificationRequestReject,
	SgNBModificationRequired,
	SgNBModificationConfirm,
	SgNBModificationRefuse,
	SgNBReleaseRequest,
	SgNBReleaseRequestAcknowledge,
	SgNBReleaseRequestReject,
	SgNBReleaseRequired,
	SgNBReleaseConfirm,
	SgNBCounterCheckRequest,
	SgNBChangeRequired,
	SgNBChangeConfirm,
	SgNBChangeRefuse,
	RRCTransfer,
	ENDCX2SetupRequest,
	ENDCX2SetupResponse,
	ENDCX2SetupFailure,
	ENDCConfigurationUpdate,
	ENDCConfigurationUpdateAcknowledge,
	ENDCConfigurationUpdateFailure,
	SecondaryRATDataUsageReport,
	ENDCCellActivationRequest,
	ENDCCellActivationResponse,
	ENDCCellActivationFailure,
	ENDCPartialResetRequired,
	ENDCPartialResetConfirm,
	EUTRANRCellResourceCoordinationRequest,
	EUTRANRCellResourceCoordinationResponse,
	SgNBActivityNotification,
	ENDCX2RemovalRequest,
	ENDCX2RemovalResponse,
	ENDCX2RemovalFailure,
	DataForwardingAddressIndication,
	GNBStatusIndication,
	ENDCConfigurationTransfer,
	DeactivateTrace,
	TraceStart,
	HandoverSuccess,
	EarlyStatusTransfer,
	ConditionalHandoverCancel,
	ENDCResourceStatusRequest,
	ENDCResourceStatusResponse,
	ENDCResourceStatusFailure,
	ENDCResourceStatusUpdate,
	CellTrafficTrace,
	F1CTrafficTransfer,
	UERadioCapabilityIDMappingRequest,
	UERadioCapabilityIDMappingResponse,
	AccessAndMobilityIndication,
	CPC-cancel,
	RachIndication,
	SCGFailureInformationReport,
	SCGFailureTransfer





FROM X2AP-PDU-Contents

	id-cellActivation,
	id-eNBConfigurationUpdate,
	id-errorIndication,
	id-handoverCancel, 
	id-handoverReport,
	id-handoverPreparation,
	
	id-loadIndication,
	id-privateMessage,
	id-reset,
	
	id-resourceStatusReporting,
	id-resourceStatusReportingInitiation, 
	id-rLFIndication,
	id-snStatusTransfer,
	id-uEContextRelease,
	id-x2Setup,
	id-mobilitySettingsChange,
	id-x2Release,
	id-x2APMessageTransfer,
	id-seNBAdditionPreparation,
	id-seNBReconfigurationCompletion,
	id-meNBinitiatedSeNBModificationPreparation,
	id-seNBinitiatedSeNBModification,
	id-meNBinitiatedSeNBRelease,
	id-seNBinitiatedSeNBRelease,
	id-seNBCounterCheck,
	id-x2Removal,
	id-retrieveUEContext,
	id-sgNBAdditionPreparation,
	id-sgNBReconfigurationCompletion,
	id-meNBinitiatedSgNBModificationPreparation,
	id-sgNBinitiatedSgNBModification,
	id-meNBinitiatedSgNBRelease,
	id-sgNBinitiatedSgNBRelease,
	id-sgNBChange,
	id-sgNBCounterCheck,
	id-rRCTransfer,
	id-endcX2Setup,
	id-endcConfigurationUpdate,
	id-secondaryRATDataUsageReport,
	id-endcCellActivation,
	id-endcPartialReset,
	id-eUTRANRCellResourceCoordination,
	id-SgNBActivityNotification,
	id-endcX2Removal,
	id-dataForwardingAddressIndication,
	id-gNBStatusIndication,
	id-endcConfigurationTransfer,
	id-deactivateTrace,
	id-traceStart,
	id-handoverSuccess,
	id-earlyStatusTransfer,
	id-conditionalHandoverCancel,
	id-endcresourceStatusReporting,
	id-endcresourceStatusReportingInitiation,
	id-cellTrafficTrace,
	id-f1CTrafficTransfer,
	id-UERadioCapabilityIDMapping,
	id-accessAndMobilityIndication,
	id-CPC-cancel,
	id-rachIndication,
	id-scgFailureInformationReport,
	id-scgFailureTransfer




FROM X2AP-Constants;

-- **************************************************************
--
-- Interface Elementary Procedure Class
--
-- **************************************************************

X2AP-ELEMENTARY-PROCEDURE ::= CLASS {
	&InitiatingMessage				,
	&SuccessfulOutcome				OPTIONAL,
	&UnsuccessfulOutcome				OPTIONAL,
	&procedureCode			ProcedureCode 	UNIQUE,
	&criticality			Criticality 	DEFAULT ignore
}
WITH SYNTAX {
	INITIATING MESSAGE		&InitiatingMessage
	[SUCCESSFUL OUTCOME		&SuccessfulOutcome]
	[UNSUCCESSFUL OUTCOME		&UnsuccessfulOutcome]
	PROCEDURE CODE			&procedureCode
	[CRITICALITY			&criticality]
}

Using ASN.1 Studio (Optional)

The gui/ subdirectory contains an ASN.1 Studio project for this sample. With ASN.1 Studio you can:

  • Open the LTE X2AP ASN.1 modules.
  • Generate code from the ASN.1 schema.
  • Create and edit sample encoded LTE X2AP messages.
  • Export projects to gmake makefiles.

Related Samples

Disclaimer

This sample is provided solely for illustration purposes, for example to demonstrate usage of the OSS ASN.1 Tools API with 3GPP LTE X2AP messages. It does not represent a complete application. To build and run this sample, you must use a trial or licensed version of the appropriate OSS ASN.1 Tools. The copyright and license statements included in each source file remain fully applicable.

Need Help?

If you have questions about using this sample, contact OSS Nokalva Support.

See Also