Main Content

Generate CU-Plane Messages for O-RAN Fronthaul Test

This example shows how to generate fronthaul control and user (CU) 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, which transmit an NR test model waveform, as defined in TS 38.141-1. 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 with third-party packet analysis tools. In this example, Wireshark is used to verify that the content of the CU-plane messages is as expected.

workflow5.png

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

GenerateCUPlaneMessagesForORANFronthaulTestPacketGeneration.png

Set Configuration Parameters

The data frame to transmit consists of a full band 5G NR test model waveform, as defined in TS 38.141-1. You can set the test model, 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 advance between C-plane message and U-plane message (Tcp_adv_dl), and the maximum supported numerology.

% Select the NR test model waveform parameters
waveConfig = struct();
waveConfig.tm  = "NR-FR1-TM1.1";  % Test model (must be full band)
waveConfig.bw  = "100MHz";  % Channel bandwidth (MHz)
waveConfig.scs = "30kHz";  % Subcarrier spacing (kHz)

% O-RAN configuration
% Set the compression parameters
oranConfig = struct();
oranConfig.method = 'BFP';      % U-plane compression method
oranConfig.IQWidth = 24;                       % IQ samples bit-width before or without compression
oranConfig.cIQWidth =14; % Compressed IQ samples bit-width (1 to 16)
oranConfig.SectionType = 1; % C-plane message Section Type

% eCPRI configuration
% Set the eAxC ID values to be used, in terms of the DU_Port_ID, BandSector_ID, CC_ID and RU_Port_ID subfields.
% The same messages will be sent on all eAxC dataflows specified. 
% The eAxCIDBits field of the mPlaneConfig structure defines the bit-width of each ID part.
% Specify multiple eAxC ID by using vectors of ID values. 
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
ethernetConfig = struct();
% Set Ethernet MTU size
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)
 
% Select the MAC source and destination addresses
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)

% Set the M-plane and general 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.Tcp_adv_dl = 0.00012;                 % C-plane timing advance (secs)
mPlaneConfig.MaxNumerology = -1; % Highest supported numerology for mixed numerology using section type 3 C-plane messages 

% 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] = 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 by using the nrORANBlockCompress function. Compression method options include block floating point (BFP), block scaling, and mu-law, as defined in TS O-RAN.WG4.CUS Annex A.1.1, A.2.1, and A.3.1, respectively. Before applying the compression, scale the IQ samples in the resource grid to the bit-width specified by oranConfig.IQWidth.

% Scale the IQ samples in the resource grid using IQWidth
peak = max(abs([real(grid(:)); imag(grid(:))]));
scaleFactor = peak / (0.95*(2^(oranConfig.IQWidth-1)-1));
oranConfig.scaledGrid = round(grid/scaleFactor);

% Apply compression to the scaled resource grid if selected
if ~strcmp(oranConfig.method,'No compression')
    [oranConfig.cGrid,oranConfig.cParam] = nrORANBlockCompress(oranConfig.scaledGrid, ...
        oranConfig.method,oranConfig.cIQWidth,oranConfig.IQWidth);
       
    % Decompress the resulting grid, if required for comparison
    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));
fprintf('Created %s file.',cufilename);
Created CUMessages.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 sumnmarised 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