LTE X2AP Java 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, and creates and encodes successful outcome messages.

A Unix shell script (run.sh) is included for running the test program using the OSS ASN.1/Java runtime.

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 X2AP project.
  • Read a PER-encoded X2AP message from an input file.
  • Decode and print LTE X2AP messages.
  • Create and encode a successful outcome message.
  • Run the sample test program using the provided run.sh script.

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.java Simple Java program that shows how to work with LTE X2AP protocol data. It reads input messages from files, decodes and prints them, and creates and encodes successful outcome messages.
x2ap.cmd ASN.1 compiler command file used to ASN.1-compile the LTE X2AP specifications.
run.sh Unix shell script that runs the sample test.
sample.out Expected output from this test.
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 Java.

1. Verify environment variables

Before running the test, ensure the following are set appropriately:

  • OSS_ASN1_JAVA
  • CLASSPATH
  • PATH
2. Run the sample
./run.sh
3. Clean up generated files
./run.sh cleanup
4. Other Platforms

Note: The Java 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.java

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

Show Tx2ap.java 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.                                            */
/*****************************************************************************/

/*
 * Demonstrates work with data for X2AP protocol of LTE
 */

import java.io.*;

import com.oss.asn1.*;
import com.oss.util.*;

import x2ap.*;
import x2ap.oss_x2ap_x2ap_commondatatypes.*;
import x2ap.oss_x2ap_x2ap_constants.*;
import x2ap.oss_x2ap_x2ap_containers.*;
import x2ap.oss_x2ap_x2ap_ies.*;
import x2ap.oss_x2ap_x2ap_pdu_contents.*;
import x2ap.oss_x2ap_x2ap_pdu_descriptions.*;

public class Tx2ap {
    static Coder coder;
    static String border = "-------------------------------------------------------";
    /* Names of Criticality values */
    static String[] Criticalities = { "reject", "ignore", "notify" };

    /*
     * Deserializes and prints input messages, creates and prints successful
     * outcome messages
     */
    public static void main(String[] args)
	throws java.io.FileNotFoundException, Exception
    {
	// Initialize the project
	try {
	    X2ap.initialize();
	} catch (Exception e) {
	    System.out.println("Initialization exception: " + e);
	    System.exit(1);
	}

	coder = X2ap.getPERAlignedCoder();
	coder.enableAutomaticEncoding();
	coder.enableAutomaticDecoding();
	coder.enableEncoderDebugging();
	coder.enableDecoderDebugging();

	// An optional parameter includes the path to all the files that are used by
	// the program.
	String path = (args.length > 0) ? args[0] : null;

	try {
	    testX2AP(path, "X2AP-PDU_HandoverRequest_bin.per");
	} catch (Exception e) {
	    System.out.println(e);
	    System.exit(1);
	}

	System.out.println("\nTesting successful");
    }

    /*
     * testX2AP() is used to test X2AP message, the input serialized pdu is
     * deserialized and printed, then an outcome message is created, printed
     * and encoded.
     */
    static void testX2AP(String path, String filename) throws IOException, Exception
    {
	OSS_X2AP_PDU request;
	File file = new File(path, filename);
	if (!file.exists()) {
	    throw new IOException("Failed to open the " + file.toString() + " file. " +
		"Restart the sample program using as input parameter the name of the directory " +
		"where the '" + file.getName() + "' file is located.\n");
	}
	FileInputStream source = new FileInputStream(file);

	System.out.println("============================================================================");
	/* Read serialized message from file */
	System.out.println("Read encoding from file: " + filename + "\n");

	System.out.println("Deserialize request");
	System.out.println(border);
	/* Deserialize input message */
        request = (OSS_X2AP_PDU)coder.decode(source, new OSS_X2AP_PDU());
	source.close();
	System.out.println("\nDeserialized request");
	System.out.println(border);
	/* Print deserialized message */
	System.out.println(request);
	/* Parse and print input message */
	printHandoverRequestMsg(request);
	/* Create successful outcome message */
	OSS_X2AP_PDU response = createSuccessResponse(request);

	/* Print outcome message */
	System.out.println(response);
	System.out.println("Serialize response");
	System.out.println(border);
	/* Serialize outcome message */
	ByteArrayOutputStream out = new ByteArrayOutputStream();
	try {
	    coder.encode(response, out);
	} catch (Exception e) {
	    System.out.println("Encoding failed: " + e);
	    System.exit(1);
	}

	/* Print serialized outcome message */
	System.out.println("\nSerialized response "
				+ "(" + out.size() + " bytes):");
	System.out.println(HexTool.getHex(out.toByteArray()));
    }

    /*
     * Prints X2AP pdu which contains HandoverRequest message. The
     * function is not intended to handle other types of messages.
     */
    static void printHandoverRequestMsg(OSS_X2AP_PDU pdu) throws Exception
    {
	OSS_X2AP_HandoverRequest hr_value;
	System.out.println("\nGet message information");
	System.out.println(border);
	/* Get identifier of message stored in PDU */
	if (!pdu.hasInitiatingMessage())
	    throw new Exception("Unexpected type of message");

	OpenType msg_value = ((OSS_X2AP_InitiatingMessage)
	    pdu.getChosenValue()).getValue();

	if (msg_value.getDecodedValue() != null) {
	    if (msg_value.getDecodedValue() instanceof OSS_X2AP_HandoverRequest)
		hr_value = (OSS_X2AP_HandoverRequest)msg_value.getDecodedValue();
	    else
		throw new Exception("Unexpected message");
	} else
	    throw new Exception("Incorrect message");

	System.out.println("Message type is HandoverRequest\n");

	if (hr_value.getProtocolIEs() == null)
	    throw new Exception("Incorrect message");

	printProtocolIEs(hr_value.getProtocolIEs(), 0);
    }

    /*
     * Creates X2AP successful outcome message for given
     * HandoverRequest request.
     */
    static OSS_X2AP_PDU createSuccessResponse(OSS_X2AP_PDU request) throws Exception
    {
	if (!request.hasInitiatingMessage())
	    throw new Exception("Unexpected type of message");

	OpenType msg_value = ((OSS_X2AP_InitiatingMessage)
	    request.getChosenValue()).getValue();
	OSS_X2AP_HandoverRequest hr_value =
	    (OSS_X2AP_HandoverRequest)msg_value.getDecodedValue();

	if (hr_value == null || msg_value.getEncodedValue() != null)
	    throw new Exception("Unexpected HandoverRequest request data");

	if (hr_value.getProtocolIEs() == null
		|| hr_value.getProtocolIEs().getSize() == 0)
	    throw new Exception("No IEs in HandoverRequest request");

	OSS_X2AP_ProtocolIE_Container reqies = hr_value.getProtocolIEs();

	System.out.println("Create response");
	System.out.println(border);
	/*
         * Create successful outcome message from initiating message. Copy
         * some IEs from input to output.
         */
        OSS_X2AP_ProtocolIE_Container respies =
    	     new OSS_X2AP_ProtocolIE_Container();
    	OSS_X2AP_ProtocolIE_Field element;

        for (int i = 0; i < reqies.getSize(); i++) {
    	    if (reqies.get(i).getId().equalTo(
    		    OSS_X2AP_X2AP_Constants.OSS_X2AP_id_Old_eNB_UE_X2AP_ID)) {
		element = new OSS_X2AP_ProtocolIE_Field(
			    reqies.get(i).getId(),
			    OSS_X2AP_Criticality.ignore,
			    (OpenType)reqies.get(i).getValue().clone());
		respies.add(element);
	    }
	}

	OSS_X2AP_ProtocolIE_ID id;
	OSS_X2AP_Criticality criticality;

	/* Add IE with id-New-eNB-UE-X2AP-ID to outcome message */
	id = OSS_X2AP_X2AP_Constants.OSS_X2AP_id_New_eNB_UE_X2AP_ID;
	criticality = OSS_X2AP_Criticality.ignore;
	OSS_X2AP_UE_X2AP_ID ueX2apId = new OSS_X2AP_UE_X2AP_ID(456);
	element = new OSS_X2AP_ProtocolIE_Field(
		    id, criticality, new OpenType(ueX2apId));
	respies.add(element);

	/* Add E_RABs-Admitted-List IE to outcome message */
	id = OSS_X2AP_X2AP_Constants.OSS_X2AP_id_E_RABs_Admitted_List;
	criticality = OSS_X2AP_Criticality.ignore;

	OSS_X2AP_E_RAB_ID e_RAB_ID = new OSS_X2AP_E_RAB_ID(999);

	OSS_X2AP_TransportLayerAddress transportLayerAddress =
	    new OSS_X2AP_TransportLayerAddress(new byte[] {(byte)0x55}, 7);
	OSS_X2AP_GTP_TEI gTP_TEID = new OSS_X2AP_GTP_TEI
	    (new byte[] {(byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04});
	OSS_X2AP_GTPtunnelEndpoint uL_GTP_TunnelEndpoint =
	    new OSS_X2AP_GTPtunnelEndpoint(transportLayerAddress, gTP_TEID);

	transportLayerAddress = new OSS_X2AP_TransportLayerAddress(
		new byte[] {(byte)0x55, (byte)0x55}, 11);
	gTP_TEID = new OSS_X2AP_GTP_TEI
	    (new byte[] {(byte)0x05, (byte)0x06, (byte)0x07, (byte)0x08});
	OSS_X2AP_GTPtunnelEndpoint dL_GTP_TunnelEndpoint =
	    new OSS_X2AP_GTPtunnelEndpoint(transportLayerAddress, gTP_TEID);

	OSS_X2AP_E_RABs_Admitted_Item eRabAdmItem =
		    new OSS_X2AP_E_RABs_Admitted_Item(e_RAB_ID);
	eRabAdmItem.setUL_GTP_TunnelEndpoint(uL_GTP_TunnelEndpoint);
	eRabAdmItem.setDL_GTP_TunnelEndpoint(dL_GTP_TunnelEndpoint);

	OSS_X2AP_ProtocolIE_Field field =
	    new OSS_X2AP_ProtocolIE_Field(
		    OSS_X2AP_X2AP_Constants.OSS_X2AP_id_E_RABs_Admitted_Item,
		    OSS_X2AP_Criticality.ignore,
		    new OpenType(eRabAdmItem));
	OSS_X2AP_E_RABs_Admitted_List eRabAdmList =
		new OSS_X2AP_E_RABs_Admitted_List();
	eRabAdmList.add(field);

	element = new OSS_X2AP_ProtocolIE_Field(
		    id, criticality, new OpenType(eRabAdmList));
	respies.add(element);

	/* Add TargeteNBtoSource-eNBTransparentContainer IE to outcome message */
	id = OSS_X2AP_X2AP_Constants.OSS_X2AP_id_TargeteNBtoSource_eNBTransparentContainer;
	criticality = OSS_X2AP_Criticality.ignore;
	OSS_X2AP_TargeteNBtoSource_eNBTransparentContainer trValue =
	    new OSS_X2AP_TargeteNBtoSource_eNBTransparentContainer(
		    new byte[] {(byte)0x55});

	element = new OSS_X2AP_ProtocolIE_Field(
		    id, criticality, new OpenType(trValue));
	respies.add(element);

	OSS_X2AP_ProcedureCode procedureCode = ((OSS_X2AP_InitiatingMessage)
				request.getChosenValue()).getProcedureCode();
	criticality = OSS_X2AP_Criticality.reject;
        OSS_X2AP_HandoverRequestAcknowledge handoverRequestAcknowledge =
	    new OSS_X2AP_HandoverRequestAcknowledge(respies);
	OSS_X2AP_SuccessfulOutcome successfulOutcome =
	    new OSS_X2AP_SuccessfulOutcome(
		    procedureCode,
		    criticality,
		    new OpenType(handoverRequestAcknowledge));
	OSS_X2AP_PDU response =
	    OSS_X2AP_PDU.createOSS_X2AP_PDUWithSuccessfulOutcome(successfulOutcome);
	return response;
    }

    /*
     * Prints ProtocolIE_Container data.
     */
    static void printProtocolIEs(OSS_X2AP_ProtocolIE_Container ies, int indent)
    {
	System.out.println("protocolIEs includes the following IEs:\n");
	indent++;
	/* Print each IE */
        for (int i = 0; i < ies.getSize(); i++) {
	    OSS_X2AP_ProtocolIE_Field field =
		(OSS_X2AP_ProtocolIE_Field )ies.get(i).clone();
	    OpenType value = field.getValue();
	    long fieldId = field.getId().longValue();
	    printIndent(indent++);
	    System.out.println("#" + (i + 1) + ": id = " + fieldId +
				", criticality = " +
				Criticalities[(int)field.getCriticality().longValue()]);

	    /* Print UE-X2AP-ID IE */
	    printIndent(indent);
    	    if (field.getId().equalTo(OSS_X2AP_X2AP_Constants.OSS_X2AP_id_Old_eNB_UE_X2AP_ID)) {
		System.out.println("value UE-X2AP-ID: " +
		    ((OSS_X2AP_UE_X2AP_ID)value.getDecodedValue()).longValue());
	    /* Cause IE */
    	    } else if (field.getId().equalTo(OSS_X2AP_X2AP_Constants.OSS_X2AP_id_Cause)) {
		OSS_X2AP_Cause pcause = (OSS_X2AP_Cause)value.getDecodedValue();

		/*
		 * Named values can be printed below instead of numbers for all
		 * Cause components
		 */
		System.out.print("value Cause: ");
		/* radioNetwork */
		if (pcause.hasRadioNetwork())
		    System.out.println("radioNetwork: " +
			((OSS_X2AP_CauseRadioNetwork)pcause.getChosenValue()).longValue());
		/* transport */
		else if (pcause.hasTransport())
		    System.out.println("transport: " +
			((OSS_X2AP_CauseTransport)pcause.getChosenValue()).longValue());
		/* protocol */
		else if (pcause.hasProtocol())
		    System.out.println("Protocol: " +
			((OSS_X2AP_CauseProtocol)pcause.getChosenValue()).longValue());
		/* misc */
		else if (pcause.hasMisc())
		    System.out.println("misc: " +
			((OSS_X2AP_CauseMisc)pcause.getChosenValue()).longValue());
	    /* ECGI IE */
    	    } else if (field.getId().equalTo(
    			OSS_X2AP_X2AP_Constants.OSS_X2AP_id_TargetCell_ID)) {
		OSS_X2AP_ECGI ptarget = (OSS_X2AP_ECGI)value.getDecodedValue();
		System.out.println("value ECGI: ");
		indent++;
		/* pLMN-Identity */
		printDataWithIndent(indent, "pLMN-Identity: " +
		    toHstring(ptarget.getPLMN_Identity().byteArrayValue()));
		/* eUTRANcellIdentifier */
		printDataWithIndent(indent, "eUTRANcellIdentifier: " +
		    toHstring(ptarget.getEUTRANcellIdentifier().byteArrayValue()));
		/* iE_Extensions is optional */
		if (ptarget.hasIE_Extensions())
		    printProtocolExtensions(ptarget.getIE_Extensions(), indent);

		indent--;
	    /* GUMMEI IE */
	    } else if (field.getId().equalTo(OSS_X2AP_X2AP_Constants.OSS_X2AP_id_GUMMEI_ID)) {
		OSS_X2AP_GUMMEI pgummei = (OSS_X2AP_GUMMEI)value.getDecodedValue();

		System.out.println("value GUMMEI: ");
		indent++;
		/* gU-Group-ID */
		printDataWithIndent(indent, "gU-Group-ID: ");
		OSS_X2AP_GU_Group_ID pgroup = pgummei.getGU_Group_ID();

		indent++;
		/* pLMN-Identity */
		printDataWithIndent(indent, "pLMN_Identity: " +
		    toHstring(pgroup.getPLMN_Identity().byteArrayValue()));
		/* pLMN-Identity */
		printDataWithIndent(indent, "mME-Group-ID: " +
		    toHstring(pgroup.getMME_Group_ID().byteArrayValue()));
		/* iE_Extensions is optional */
		if (pgroup.hasIE_Extensions())
		    printProtocolExtensions(pgroup.getIE_Extensions(), indent);
		indent--;

		/* mME-Code */
		printDataWithIndent(indent, "mME-Code: " +
		    toHstring(pgummei.getMME_Code().byteArrayValue()));

		/* iE_Extensions is optional */
		if (pgummei.hasIE_Extensions())
		    printProtocolExtensions(pgummei.getIE_Extensions(), indent);
		indent--;
	    /* UE-ContextInformation IE */
	    } else if (field.getId().equalTo(
		    OSS_X2AP_X2AP_Constants.OSS_X2AP_id_UE_ContextInformation)) {
		OSS_X2AP_UE_ContextInformation pinfo =
		    (OSS_X2AP_UE_ContextInformation)value.getDecodedValue();

		System.out.println("value UE-ContextInformation: ");
		indent++;
		/*  mME-UE-S1AP-ID */
		printDataWithIndent(indent, "mME-UE-S1AP-ID: " +
		    pinfo.getMME_UE_S1AP_ID().longValue());
		/* uESecurityCapabilities */
		printDataWithIndent(indent, "uESecurityCapabilities: ");
		{
		    OSS_X2AP_UESecurityCapabilities pseccap =
					pinfo.getUESecurityCapabilities();

		    indent++;
		    /* encryptionAlgorithms */
		    printDataWithIndent(indent, "encryptionAlgorithms: " +
			toHstring(pseccap.getEncryptionAlgorithms().byteArrayValue()));

		    /* integrityProtectionAlgorithms */
		    printDataWithIndent(indent, "integrityProtectionAlgorithms: " +
			toHstring(pseccap.getIntegrityProtectionAlgorithms().byteArrayValue()));

		    /* iE_Extensions is optional */
		    if (pseccap.hasIE_Extensions())
			printProtocolExtensions(pseccap.getIE_Extensions(), indent);
		    indent--;
		}

		/* aS_SecurityInformation */
		printDataWithIndent(indent, "aS_SecurityInformation: ");
		{
		    OSS_X2AP_AS_SecurityInformation psecinf =
					pinfo.getAS_SecurityInformation();

		    indent++;
		    /* key_eNB */
		    printDataWithIndent(indent, "key_eNB: " +
			toHstring(psecinf.getKey_eNodeB_star().byteArrayValue()));

		    /* nextHopChainingCounter */
		    printDataWithIndent(indent, "nextHopChainingCounter: " +
			psecinf.getNextHopChainingCount().longValue());

		    /* iE_Extensions is optional */
		    if (psecinf.hasIE_Extensions())
			printProtocolExtensions(psecinf.getIE_Extensions(), indent);

		    indent--;
		}

		/* uEaggregateMaximumBitRate */
		printDataWithIndent(indent, "uEaggregateMaximumBitRate: ");
		{
		    OSS_X2AP_UEAggregateMaximumBitRate prate =
					pinfo.getUEaggregateMaximumBitRate();
		    indent++;
		    /* uEaggregateMaximumBitRateDownlink */
		    printDataWithIndent(indent, "uEaggregateMaximumBitRateDownlink: " +
			prate.getUEaggregateMaximumBitRateDownlink().longValue());

		    /* uEaggregateMaximumBitRateUplink */
		    printDataWithIndent(indent, "uEaggregateMaximumBitRateUplink: " +
			prate.getUEaggregateMaximumBitRateUplink().longValue());

		    /* iE_Extensions is optional */
		    if (prate.hasIE_Extensions())
			printProtocolExtensions(prate.getIE_Extensions(), indent);

		    indent--;
		}

		/* subscriberProfileIDforRFP is optional */
		if (pinfo.hasSubscriberProfileIDforRFP()) {
		    printDataWithIndent(indent, "subscriberProfileIDforRFP: " +
			pinfo.getSubscriberProfileIDforRFP().longValue());
		}

		/* e-RABs-ToBeSetup-List */
		printE_RABs_ToBeSetup_List(
				pinfo.getE_RABs_ToBeSetup_List(), indent);

		/* rRC-Context */
		printDataWithIndent(indent, "rRC-Context: " +
		    toHstring(pinfo.getRRC_Context().byteArrayValue()));

		/* handoverRestrictionList is optional */
		if (pinfo.hasHandoverRestrictionList()) {
		    OSS_X2AP_HandoverRestrictionList plist =
				pinfo.getHandoverRestrictionList();

		    printDataWithIndent(indent, "handoverRestrictionList: ");
		    indent++;
		    /* servingPLMN */
		    printDataWithIndent(indent, "servingPLMN: " +
			toHstring(plist.getServingPLMN().byteArrayValue()));

		    /* equivalentPLMNs is optional */
		    if (plist.hasEquivalentPLMNs()) {
			OSS_X2AP_EPLMNs peplmns = plist.getEquivalentPLMNs();
			printDataWithIndent(indent,
			    "equivalentPLMNs includes the following PLMN-Identity elements:");
			/* Print each list element */
    			for (int j = 0; j < peplmns.getSize(); j++) {
			    printDataWithIndent(indent, " #" + (j+1) + ": " +
				toHstring(peplmns.get(j).byteArrayValue()));
			}
		    }

		    /* forbiddenTAs is optional */
		    if (plist.hasForbiddenTAs()) {
			printDataWithIndent(indent,
				"forbiddenTAs includes ForbiddenTAs-Item elements:");
			/* Miss printing of ForbiddenTAs-Item data */
			printDataWithIndent(indent, " ...");
		    }
		    /* forbiddenLAs is optional */
		    if (plist.hasForbiddenLAs()) {
			printDataWithIndent(indent,
				"forbiddenLAs includes ForbiddenLAs-Item elements:");
			/* Miss printing of ForbiddenTAs-Item data */
			printDataWithIndent(indent, " ...");
		    }

		    /* forbiddenInterRATs is optional */
		    if (plist.hasForbiddenInterRATs()) {
			printDataWithIndent(indent, "forbiddenInterRATs: " +
			    plist.getForbiddenInterRATs().longValue());
		    }

		    /* iE_Extensions is optional */
		    if (plist.hasIE_Extensions())
			printProtocolExtensions(plist.getIE_Extensions(), indent);

		    indent--;
		}

		/* locationReportingInformation is optional */
		if (pinfo.hasLocationReportingInformation()) {
		    OSS_X2AP_LocationReportingInformation ploc =
				pinfo.getLocationReportingInformation();

		    printDataWithIndent(indent, "locationReportingInformation:");
		    indent++;
		    /* eventType */
		    printDataWithIndent(indent, "eventType: " +
			((ploc.getEventType().longValue() == 0) ?
			"change-of-serving-cell" : "unknown"));

		    /* reportArea */
		    printDataWithIndent(indent, "reportArea: " +
			((ploc.getReportArea().longValue() == 0) ?
					    "ecgi" : "unknown"));

		    /* iE_Extensions is optional */
		    if (ploc.hasIE_Extensions())
			printProtocolExtensions(ploc.getIE_Extensions(), indent);

		    indent--;
		}

		/* iE_Extensions is optional */
		if (pinfo.hasIE_Extensions())
			printProtocolExtensions(pinfo.getIE_Extensions(), indent);

		indent--;
	    /* UE-HistoryInformation IE */
	    } else if (field.getId().equalTo(
		    OSS_X2AP_X2AP_Constants.OSS_X2AP_id_UE_HistoryInformation)) {
		printHistoryInformation((OSS_X2AP_UE_HistoryInformation)
					    value.getDecodedValue(), indent);

	    /* TraceActivation IE */
	    } else if (field.getId().equalTo(
		    OSS_X2AP_X2AP_Constants.OSS_X2AP_id_TraceActivation)) {
		OSS_X2AP_TraceActivation ptrace =
			(OSS_X2AP_TraceActivation)value.getDecodedValue();

		System.out.println("value TraceActivation: ");
		indent++;
		/* eUTRANTraceID */
		    printDataWithIndent(indent, "eUTRANTraceID: " +
			toHstring(ptrace.getEUTRANTraceID().byteArrayValue()));

		/* interfacesToTrace */
		    printDataWithIndent(indent, "interfacesToTrace: " +
			toHstring(ptrace.getInterfacesToTrace().byteArrayValue()));

		/* traceDepth */
		printDataWithIndent(indent, "traceDepth: " +
			ptrace.getTraceDepth().longValue());

		/* traceCollectionEntityIPAddress */
		    printDataWithIndent(indent, "traceCollectionEntityIPAddress: " +
			toHstring(ptrace.getTraceCollectionEntityIPAddress().byteArrayValue()));

		/* iE_Extensions is optional */
		if (ptrace.hasIE_Extensions())
		    printProtocolExtensions(ptrace.getIE_Extensions(), indent);
		indent--;
	    /* CSGMembershipStatus IE has been added in the 10th release */
	    } else if (field.getId().equalTo(
		OSS_X2AP_X2AP_Constants.OSS_X2AP_id_CSGMembershipStatus)) {
		OSS_X2AP_CSGMembershipStatus membstat =
				(OSS_X2AP_CSGMembershipStatus)value.getDecodedValue();

		System.out.println(membstat);
	    /* MobilityInformation IE has been added in the 11th release */
	    } else if (field.getId().equalTo(
		OSS_X2AP_X2AP_Constants.OSS_X2AP_id_MobilityInformation)) {
		OSS_X2AP_MobilityInformation mobilityInformation =
				(OSS_X2AP_MobilityInformation)value.getDecodedValue();

		System.out.println(mobilityInformation);
	    /* Masked-IMEISV IE has been added in the 12th release */
	    } else if (field.getId().equalTo(
		OSS_X2AP_X2AP_Constants.OSS_X2AP_id_Masked_IMEISV)) {
		OSS_X2AP_Masked_IMEISV maskedIMEISV =
                    (OSS_X2AP_Masked_IMEISV)value.getDecodedValue();

		System.out.println(maskedIMEISV);
	    /* other IEs are printed as ASN.1 value notation */
	    } else if (value.getDecodedValue() != null) {
		System.out.print(value.getDecodedValue());
	    } else
		System.out.println("PDU is not decoded");
	    System.out.println();
	    indent--;
	}
    }

    /*
     * Prints ProtocolExtensionContainer data.
     */
    static void printProtocolExtensions(
	    OSS_X2AP_ProtocolExtensionContainer ie_ext, int indent)
    {
	printDataWithIndent(indent++, "iE-Extensions includes the following IEs:");
        for (int i = 0; i < ie_ext.getSize(); i++) {
    	    OSS_X2AP_ProtocolExtensionField field = ie_ext.get(i);
	    OpenType value = field.getExtensionValue();
	    long fieldId = field.getId().longValue();
	    printIndent(indent++);
	    System.out.println("#" + (i + 1) + ": id = " + fieldId +
				", criticality = " +
				Criticalities[(int)field.getCriticality().longValue()]);
	    if (value.getDecodedValue() != null)
		System.out.println(value.getDecodedValue());
	    else
		System.out.println("PDU is not decoded");
	}
    }

    /*
     * Prints E_RABs_ToBeSetup_List data.
     */
    static void printE_RABs_ToBeSetup_List(
				OSS_X2AP_E_RABs_ToBeSetup_List lst,
				int indent)
    {

	printDataWithIndent(indent, "e_RABs-ToBeSetup-List includes the following IEs:");
	indent++;
	/* Print each IE in the list */
        for (int i = 0; i < lst.getSize(); i++) {
	    OSS_X2AP_ProtocolIE_Field extval = lst.get(i);
	    OpenType value = extval.getValue();
	    long fieldId = extval.getId().longValue();
	    printIndent(indent++);
	    System.out.println("#" + (i + 1) + ": id = " + fieldId +
				", criticality = " +
				Criticalities[(int)extval.getCriticality().longValue()]);
	    if (value.getDecodedValue() != null)
		System.out.println(value.getDecodedValue());
	    else
		System.out.println("PDU is not decoded");
	}
    }

    /*
     * Prints HistoryInformation data
     */
    static void printHistoryInformation(
				OSS_X2AP_UE_HistoryInformation lst,
				int indent)
    {
        OSS_X2AP_LastVisitedCell_Item lv_item;
	System.out.println("HistoryInformation includes the following IEs:");
	indent++;
	/* Print each IE in the list */
        for (int i = 0; i < lst.getSize(); i++) {
	    lv_item = lst.get(i);

	    if (lv_item.hasE_UTRAN_Cell()) {
		OSS_X2AP_LastVisitedEUTRANCellInformation cell_inf =
		    (OSS_X2AP_LastVisitedEUTRANCellInformation)lv_item.getChosenValue();
		printDataWithIndent(indent, "#" + (i+1) + " LastVisitedCell-Item: e-UTRAN-Cell:");
		printDataWithIndent(++indent, "global-Cell-ID:");
		System.out.println(cell_inf.getGlobal_Cell_ID());
		printDataWithIndent(indent, "CellType:");
		printDataWithIndent(++indent, "Cell-Size: "
		    + cell_inf.getCellType().getCell_Size().longValue());

		if (cell_inf.getCellType().hasIE_Extensions())
		    printProtocolExtensions(cell_inf.getCellType().getIE_Extensions(), 1);

		printDataWithIndent(--indent, "time-UE-StayedInCell: "
			    + cell_inf.getTime_UE_StayedInCell().longValue());
		/* iE_Extensions is optional */
		if (cell_inf.hasIE_Extensions())
		    printProtocolExtensions(cell_inf.getIE_Extensions(), indent);
		indent--;
	    } else if (lv_item.hasUTRAN_Cell()) {
		OSS_X2AP_LastVisitedUTRANCellInformation cell_inf =
		    (OSS_X2AP_LastVisitedUTRANCellInformation)lv_item.getChosenValue();
		printDataWithIndent(indent, "#" + (i+1) + "LastVisitedCell-Item: uTRAN_Cell:");
		printDataWithIndent(indent, toHstring(cell_inf.byteArrayValue()));
	    } else if (lv_item.hasGERAN_Cell()) {
		OSS_X2AP_LastVisitedGERANCellInformation cell_inf =
		    (OSS_X2AP_LastVisitedGERANCellInformation)lv_item.getChosenValue();
		printDataWithIndent(indent, "#" + (i+1) + "LastVisitedCell-Item: gERAN_Cell:");
		if (cell_inf.hasUndefined()) {
		    printDataWithIndent(indent, "undefined: " +
			cell_inf.getChosenValue());
		} else
		    System.out.println("Incorrect value");
	    } else
		System.out.println("Incorrect value");
	}
    }

    /*
     * Helper method. Converts byte[] array to the Hstring format, like '12345'H.
     */
    static String toHstring(byte[] value)
    {
	return "'" + HexTool.getHex(value) + "'H";
    }

    /*
     * Performs indentation.
     * @param indentlevel indentation level.
     */
    public static void printIndent(int indentlevel)
    {
	for (int i = 0; i < indentlevel; i++)
	    System.out.print(' ');
    }

    /*
     * Print indentation with following data.
     */
    public static void printDataWithIndent(int indentlevel, Object data)
    {
	printIndent(indentlevel);
	System.out.println(data);
    }
}

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]
}

-- **************************************************************
--
-- Interface PDU Definition
--
-- **************************************************************

X2AP-PDU ::= CHOICE {
	initiatingMessage	InitiatingMessage,
	successfulOutcome	SuccessfulOutcome,
	unsuccessfulOutcome	UnsuccessfulOutcome,
	...
}

InitiatingMessage ::= SEQUENCE {
	procedureCode	X2AP-ELEMENTARY-PROCEDURE.&procedureCode		({X2AP-ELEMENTARY-PROCEDURES}),
	criticality		X2AP-ELEMENTARY-PROCEDURE.&criticality			({X2AP-ELEMENTARY-PROCEDURES}{@procedureCode}),
	value			X2AP-ELEMENTARY-PROCEDURE.&InitiatingMessage	({X2AP-ELEMENTARY-PROCEDURES}{@procedureCode})
}

SuccessfulOutcome ::= SEQUENCE {
	procedureCode	X2AP-ELEMENTARY-PROCEDURE.&procedureCode		({X2AP-ELEMENTARY-PROCEDURES}),
	criticality		X2AP-ELEMENTARY-PROCEDURE.&criticality			({X2AP-ELEMENTARY-PROCEDURES}{@procedureCode}),
	value			X2AP-ELEMENTARY-PROCEDURE.&SuccessfulOutcome	({X2AP-ELEMENTARY-PROCEDURES}{@procedureCode})
}

UnsuccessfulOutcome ::= SEQUENCE {
	procedureCode	X2AP-ELEMENTARY-PROCEDURE.&procedureCode		({X2AP-ELEMENTARY-PROCEDURES}),
	criticality		X2AP-ELEMENTARY-PROCEDURE.&criticality			({X2AP-ELEMENTARY-PROCEDURES}{@procedureCode}),
	value			X2AP-ELEMENTARY-PROCEDURE.&UnsuccessfulOutcome	({X2AP-ELEMENTARY-PROCEDURES}{@procedureCode})
}

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 to a runnable shell script.

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