Main Content

Generate CU-Plane Messages for O-RAN Fronthaul Test

This example shows how to generate fronthaul control plane and user plane (CU-Plane) plane messages for open radio access network (O-RAN) conformance tests using 5G Toolbox™. These O-RAN compliant messages are considered as split option 7.2x test vectors generated from an O-RAN distributed unit (O-DU). The example generates a packet capture (PCAP) file that contains these messages.

Introduction

This example shows how to build the O-RAN fronthaul CU-Plane messages, as defined in TS O-RAN.WG4.CUS, to transmit an NR test model or an uplink FRC, as defined in TS 38.141-1 and TS 38.104, respectively. These O-RAN compliant messages are considered as split option 7.2x test vectors generated from an O-DU. The example generates a PCAP file, which contains the messages. You can use the generated packets to test an O-RAN radio unit (O-RU) following the conformance test specifications in TS O-RAN.WG4.CONF. You can also analyze the generated PCAP file by using the Analyze CU-Plane Messages for O-RAN Fronthaul Testing example or third-party packet analysis tools. In this example, Wireshark is used to verify that the content of the CU-Plane messages is as expected.

A diagram showing a 5G grid being generated with the 5G toolbox then being packaged into CU-Plane message and placed in a PCAP file. The PCAP file is then sent to a packet analyzer for analysis.

This example builds the CU-Plane messages required to transmit the specified NR test model or uplink FRC waveform. The example generates at least one control plane (C-Plane) message for every extended antenna-carrier identifier (eAxC ID) per slot. Each C-Plane message is associated with one or more user plane (U-Plane) messages per symbol, depending on the Ethernet MTU size. You can send the C-Plane messages as section type 1 (for most data) or section type 3 (for mixed numerology data). The U-Plane messages encapsulate the IQ data using a single section per message. This diagram illustrates the flow of the generated CU-Plane messages for a single eAxC ID using section type 1 C-Plane messages.

Two timing diagrams, one for downlink and one for uplink, that show the flow of CU-Plane message from the O-DU to O-RU.

Set Configuration Parameters

The constructed data frames consist of the entire grid of a 5G NR test model or an uplink FRC, as defined in TS 38.141-1 and TS 38.104, respectively. You can set the waveform, the channel bandwidth, and the subcarrier spacing of the test waveform. This example supports FDD duplex mode only and does not apply any precoding or beamforming.

The generated PCAP file includes the Ethernet, eCPRI, and O-RAN protocols. In this section, you can configure parameters available in the three protocols:

  • O-RAN — Set the compression method and the IQ samples bit-width before and after compression.

  • eCPRI — Set the eAxC ID fields. To create multiple data streams, use a vector of IDs to replicate the waveform on each CU-Plane stream.

  • Ethernet — Set the Ethernet MTU, VLAN tag, and the MAC source and destination addresses.

This example does not generate management plane (M-Plane) messages. However, the example enables you to set these M-Plane parameters: compression mode, byte order, number of bits per field in eAxC ID, the timing between a C-Plane message and U-Plane message, and the maximum supported numerology.

Waveform Configuration

Select the reference waveform parameters.

waveConfig = struct();
waveConfig.tm  = "NR-FR1-TM1.1";  % Test model (TM) or uplink FRC (G)
waveConfig.bw  = "100MHz";  % Channel bandwidth (MHz)li
waveConfig.scs = "30kHz";  % Subcarrier spacing (kHz)

O-RAN Configuration

Set the compression parameters.

oranConfig = struct();
oranConfig.method      = 'BFP'; % U-Plane compression method. For modulation compression, SectionType must be 1.
oranConfig.SectionType = 1; % C-Plane message Section Type
oranConfig.IQWidth     = 24; % IQ samples bit-width before or without compression  

The cIQWidth field only applies to BFP, block scaling, and mu-Law compression methods.

oranConfig.cIQWidth =14; % Compressed IQ samples bit-width (1 to 16). 

eCPRI Configuration

Set the eAxC ID values in terms of the DU_Port_ID, BandSector_ID, CC_ID and RU_Port_ID subfields. The eAxCIDBits field of the mPlaneConfig structure defines the bit-width of each ID part.

To specify multiple eAxC ID values, use a vector of values in each ID field. In that case, the same messages are sent on all specified eAxC dataflows.

eCPRIConfig = struct();
eCPRIConfig.DUPortID     = 0; % Distributed unit identifiers
eCPRIConfig.BandSectorID = 0; % Band and sector identifiers
eCPRIConfig.CCID         = 0; % Component carrier identifiers
eCPRIConfig.RUPortID     = 0; % Spatial stream identifiers

Expand any vectors of values in the four eAxC ID subfields into combinations of individual values, where each combination is a single eAxC ID. Each eAxC ID is returned as a separate element of a structure array.

eCPRIConfig = eAxCIDConfigExpand(eCPRIConfig);

Ethernet Configuration

Set Ethernet MTU size in bytes.

ethernetConfig = struct();
ethernetConfig.MTU = 1500;

Select the Ethernet VLAN tag.

ethernetConfig.TPID     = 0x8100;   % Tag protocol identifier
ethernetConfig.priority =7; % Priority level (0 to 7)
ethernetConfig.DEI      = 0;   % Drop eligible indicator
ethernetConfig.VID      = 1;   % Unique VLAN identifier (0 to 4095)

Set the MAC source and destination addresses. The source address represents the O-DU, and the destination address represents the O-RU.

ethernetConfig.sourceAddress = [0x56 0x3b 0xbe 0xa9 0x92 0x4c]; % MAC source address (hex or string input)
ethernetConfig.destAddress = [0xda 0x14 0xde 0xb0 0x55 0x63];   % MAC destination address (hex or string input)

M-Plane Configuration

Set the general M-Plane parameters.

mPlaneConfig = struct();
mPlaneConfig.compMode      = 1; % Compression mode (statically configured over M-Plane or dynamic in the messages)
mPlaneConfig.byteOrder     = 0; % Byte order of U-Plane IQ data
mPlaneConfig.eAxCIDBits    = [2 6 4 4]; % Bits per field in eAxC ID (DUPortID,BandSectorID,CCID,RUPortID)
mPlaneConfig.MaxNumerology = -1; % Highest supported numerology for mixed numerology using section type 3 C-Plane messages

Configure the time between the transmission of the C-Plane messages and the arrival of the first associated U-Plane message. For downlink configurations, set the Tcp_adv_dl parameter, and for uplink configurations, set the T1a_cp_ul and Ta3_up_ul parameters. For further information on CU-Plane timing, see TS O-RAN.WG4.CUS Section 4.4.3 [2].

mPlaneConfig.Tcp_adv_dl = 0.00012; % DL CU-Plane timing advance (secs)
mPlaneConfig.T1a_cp_ul  = 0.00009; % UL C-Plane timing advance (secs)
mPlaneConfig.Ta3_up_ul  = 0.00003; % UL U-Plane timing delay (secs)

Packet Capture File

Set the name and format of the PCAP/PCAPNG file.

pcapFileName = 'CUMessages';  % PCAP file name
pcapFormat   = 0;  % PCAP or PCAPNG file format

Generate U-Plane Data

Use the hNRReferenceWaveformGenerator class to generate the complete 5G NR waveform that you selected in the previous section. The resource grid of the NR frame (split option 7.2x) is the data carried in the U-Plane messages.

tmWaveGen = hNRReferenceWaveformGenerator(waveConfig.tm,waveConfig.bw, ...
    waveConfig.scs,"FDD");

% Generate waveform and get resource grid of one frame of data
[~,gridSet,wInfo] = generateWaveform(tmWaveGen);
grid = gridSet.ResourceGridBWP;

% Get the number of symbols per slot and the number of slots per subframe
waveConfig.ModulationInfo = gridSet.Info;

Compress U-Plane Data

Next, compress the generated resource grid by using the hORANModulationCompressionCoder.encode function or the nrORANBlockCompress function depending on the compression method that you selected. Compression method options include block floating point (BFP), block scaling, mu-law, and modulation compression as defined in TS O-RAN.WG4.CUS Annex A.1, A.2, A.3, and A.5, respectively.

Before applying compression, scale the IQ samples in the resource grid to full scale, as defined in TS O-RAN.WG4.CUS section 8.1.3.1, and to the bit-width specified by the oranConfig.IQWidth parameter.

peakPower = sqrt(max(grid.*conj(grid),[],'all'));
scaleFactor = peakPower/2^(oranConfig.IQWidth-1);
oranConfig.scaledGrid = round(grid/scaleFactor);

% Apply compression to the scaled resource grid, if selected
switch oranConfig.method
    case 'modulationCompression'

        [oranConfig.cGrid,oranConfig.cIQWidth,oranConfig.CPlaneInfo] = ...
        hORANModulationCompressionCoder.encode(oranConfig.scaledGrid,oranConfig.IQWidth,tmWaveGen.Config,wInfo);

        decompressedGrid = hORANModulationCompressionCoder.decode(oranConfig.cGrid,oranConfig.CPlaneInfo, ...
            oranConfig.cIQWidth,oranConfig.IQWidth);
    case {'BFP','blockScaling','muLaw'}

        [oranConfig.cGrid,oranConfig.cParam] = nrORANBlockCompress(oranConfig.scaledGrid, ...
        oranConfig.method,oranConfig.cIQWidth,oranConfig.IQWidth);
       
        decompressedGrid = nrORANBlockDecompress(oranConfig.cGrid,oranConfig.cParam, ...
            oranConfig.method,oranConfig.cIQWidth,oranConfig.IQWidth);
end

Create CU-Plane Message Structures

Use the hORANProtocolBuilder.getCUMessages function to create CU-Plane message data structures:

  • Ethernet header

  • eCPRI header

  • eCPRI payload (O-RAN application data)

[cMessages,uMessages] = hORANProtocolBuilder.getCUMessages(waveConfig,mPlaneConfig,...
    oranConfig,eCPRIConfig,ethernetConfig);

Encode CU-Plane Messages

The hORANProtocolBuilder.encodeMessagesToFile function encodes the CU-Plane message structures and writes the packet octets to a PCAP file. The function also returns a high-level summary of the generated O-RAN packets which is saved to a .json file as a reference.

% Encode CU-Plane messages and write the packets to PCAP file
[cufilename,summary] = hORANProtocolBuilder.encodeMessagesToFile(waveConfig,cMessages,uMessages,...
                                                    mPlaneConfig,pcapFileName,pcapFormat,eCPRIConfig(2:end));
Warning: The specified filename is already in use. Writing to file CUMessages1.pcap.
fprintf('Created %s file.',cufilename);
Created CUMessages1.pcap file.

Analyze Generated CU-Plane Messages

You can check the summary of the CU-Plane packets to ensure that the time, length, protocol, eAxC ID and message info summarized within the PCAP file are correct.

struct2table(summary)
ans=2540×5 table
      Time       Length     Protocol           eAxCID                                Info                        
    _________    ______    ___________    ________________    ___________________________________________________

            0       60     {'C-Plane'}    0    0    0    0    "C-Plane, Type: 1, Id: 0 (all PRBs, Symbols: 0-13)"
      0.00012     1496     {'U-Plane'}    0    0    0    0    "U-Plane, Id: 0 (PRB: 0-33, Symbols: 0)"           
      0.00012     1496     {'U-Plane'}    0    0    0    0    "U-Plane, Id: 0 (PRB: 34-67, Symbols: 0)"          
      0.00012     1496     {'U-Plane'}    0    0    0    0    "U-Plane, Id: 0 (PRB: 68-101, Symbols: 0)"         
      0.00012     1496     {'U-Plane'}    0    0    0    0    "U-Plane, Id: 0 (PRB: 102-135, Symbols: 0)"        
      0.00012     1496     {'U-Plane'}    0    0    0    0    "U-Plane, Id: 0 (PRB: 136-169, Symbols: 0)"        
      0.00012     1496     {'U-Plane'}    0    0    0    0    "U-Plane, Id: 0 (PRB: 170-203, Symbols: 0)"        
      0.00012     1496     {'U-Plane'}    0    0    0    0    "U-Plane, Id: 0 (PRB: 204-237, Symbols: 0)"        
      0.00012     1496     {'U-Plane'}    0    0    0    0    "U-Plane, Id: 0 (PRB: 238-271, Symbols: 0)"        
      0.00012       77     {'U-Plane'}    0    0    0    0    "U-Plane, Id: 0 (PRB: 272, Symbols: 0)"            
    0.0001562     1496     {'U-Plane'}    0    0    0    0    "U-Plane, Id: 0 (PRB: 0-33, Symbols: 1)"           
    0.0001562     1496     {'U-Plane'}    0    0    0    0    "U-Plane, Id: 0 (PRB: 34-67, Symbols: 1)"          
    0.0001562     1496     {'U-Plane'}    0    0    0    0    "U-Plane, Id: 0 (PRB: 68-101, Symbols: 1)"         
    0.0001562     1496     {'U-Plane'}    0    0    0    0    "U-Plane, Id: 0 (PRB: 102-135, Symbols: 1)"        
    0.0001562     1496     {'U-Plane'}    0    0    0    0    "U-Plane, Id: 0 (PRB: 136-169, Symbols: 1)"        
    0.0001562     1496     {'U-Plane'}    0    0    0    0    "U-Plane, Id: 0 (PRB: 170-203, Symbols: 1)"        
      ⋮

%winopen(cufilename)   % Uncomment to open the file in Wireshark on Windows

You can also open the PCAP file containing the generated CU-Plane messages in a packet analyzer and compare the PCAP file content with the displayed summary. The generated PCAP file content must match the O-RAN fronthaul protocol preferences in Wireshark. These figures show the analysis of two captured CU-Plane messages in Wireshark.

First C-Plane Message

First U-Plane Message

References

  1. 3GPP TS 38.141-1. "NR; Base Station (BS) conformance testing Part 1: Conducted conformance testing." 3rd Generation Partnership Project; Technical Specification Group Radio Access Network.

  2. TS O-RAN.WG4.CUS. "O-RAN Fronthaul Working Group - Control, User and Synchronization Plane Specification".

  3. TS O-RAN.WG4.CONF. "O-RAN Fronthaul Working Group - Conformance Test Specification".

  4. Wireshark : https://www.wireshark.org/. Accessed 21 July 2023.

Local Functions

function eCPRIConfig = eAxCIDConfigExpand(eCPRIConfig)
    % Expands the eCPRIConfig structure for all eAxC IDs 
    % including all combinations of DUPortID, BandSectorID, CCID, and RUPortID 
    % such that every unique eAxC ID has a corresponding structure.
    eAxCIDFields=fieldnames(eCPRIConfig);

    % Iterate through each subfield of the eAxC ID
    for fieldIndex=length(eAxCIDFields):-1:1                       
        ids = eCPRIConfig.(eAxCIDFields{fieldIndex});                       % Take IDs in each subfield
        eAxCIDSubField = num2cell(repmat(ids,length(eCPRIConfig),1));       % Create a cell for the subfield
        eCPRIConfig = repmat(eCPRIConfig,1,length(ids));                    % Expand the array of structures        
        [eCPRIConfig.(eAxCIDFields{fieldIndex})] = eAxCIDSubField{:};       % Assign subfield values across entire eCPRI structure
    end
end

See Also

Functions

Related Topics