Python

 

 

 

 

Python - Deconding LTE RLC Decoder 

 

This example has several different purpose. First one is to give you a little bit of real-life example of Python programming. Another purpose is to give you a chance to apply LTE RLC Header structure in LTE RLC Page. However, this is not a complete program at all. This code decodes only the initial portions of RLC PDU and minimum information contained in RLC header. You can freely add/revise the code if you want to make it more complete code (At least, this code did a good job for my current need). If you are familiar with Python struct for bit packing/unpacking, you may make it more complete/professional, but in many cases the basic style coding like this would be easier to read / understand.

 

The input file that is used in this example has following format. (For your trial, I posted the input file here . This is a hugh text file. Don't try to open it with Notepad which will take long time. Notepad++ would be better if you want to open it).

 

I marked several locations in different colors. I only used these color coded parts in my program and all the other parts will be ignored and discarded. The meaning of each color code is as follows.

  • RED : This shows the keyword that I try to find in each line. If I find any of these keyword, I do some meaningful process.
  • BLUE : This shows the data that I extract and save in output file
  • PINK : This shows the part that will be processed further and then be saved it to output file.
  • GREED : This parts will be removed and the remaining part of the line will be saved in the output file. This part is RLC PDU and it will be passed into decodeRlcAmHeader() function for decoding header information.
  • BLACK : All of these parts will be ignored and discarded.

 

 |   |   |   |   |   |   |--------------------------------------------------------------------------------------------------------

 |   |-->|   |   |   |   |  0000020110  1   LTE_MAC_DATA_IND            LTE_UL_DTCH          0                        00:00:59.911

 |   |   |   |   |   |   |      Sender:020   Receiver:030   Type:80210015   Unit:80000001   Channel:86000005   CH_No:0000...

 |   |   |   |   |   |   |      ----- Option Data  (Length:20) -----

 |   |   |   |   |   |   |      30 00 00 03 03 66 00 07 00 00 00 00 00 00 00 00  00 00 00 00

 |   |   |   |   |   |   |      ----- Message Data (Length:109) -----

 |   |   |   |   |   |   |      A4 01 02 A0 80 01 46 00 00 28 00 01 00 00 01 02  DF 0E 64 A8 01 02 E0 00 00 16 94 04 00 00 22 00

 |   |   |   |   |   |   |      F9 01 00 00 00 01 04 00 00 00 E0 00 00 FC 80 02  45 00 00 3D 00 02 00 00 01 11 73 08 64 A8 01 02

 |   |   |   |   |   |   |      E0 00 00 FC C5 3A 14 EB 00 29 FF 6F 31 7A 00 00  00 01 00 00 00 00 00 00 0F 43 41 52 4D 44 2D 45

 |   |   |   |   |   |   |      4C 2D 30 30 31 35 35 32 00 00 FF 00 01

 |   |   |   |   |   |   |--------------------------------------------------------------------------------------------------------

 |   |<--|   |   |   |   |  0000020116  1   LTE_MAC_DATA_REQ            LTE_DL_DTCH          0                        00:00:59.912

 |   |   |   |   |   |   |      Sender:030   Receiver:020   Type:80200015   Unit:80000001   Channel:82000005   CH_No:0000  

 |   |   |   |   |   |   |      ----- Option Data  (Length:100) -----

 |   |   |   |   |   |   |      30 00 00 03 00 00 00 00 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

 |   |   |   |   |   |   |      00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

 |   |   |   |   |   |   |      00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00 00 00 00 00 82 00 00 05

 |   |   |   |   |   |   |      00 00 00 00

 |   |   |   |   |   |   |      ----- Message Data (Length:2) -----

 |   |   |   |   |   |   |      00 08

 

Following is the source code to analyze the input file. You may easily understand what the code says if you keep in mind on the color coding that I explained above. If there is any functions or operators that you are not faimilar, refer to my Python tutorial parts.

 

# (1) Import a package that is necessary to convert HEX String into Byte Array

import binascii

 

# (2) The Funtion to decode RLC AMD PDU Type. (Refer to LTE RLC - AMD Structure)

def decodeRlcAmHeader(rlcStr):

   rlcStr = rlcStr.replace(" ","")

   rlcStr = rlcStr.replace("\n","")

   rlcBytes = bytearray(binascii.a2b_hex(rlcStr))

   

   pduType = rlcBytes[0] >> 7

   if pduType == 0 : #Control PDU

      decodedHeader = "D/C=0"

      CPT = (rlcBytes[0] >> 4) & 0x07

      if CPT == 0 :

         decodedHeader = decodedHeader + "|CPT=000"

         SN = ((rlcBytes[0] & 0x0F) << 6) + ((rlcBytes[1] >> 2) & 0x3F)

         decodedHeader = decodedHeader + "|SN=" + str(SN)

      else :

         decodedHeader = decodedHeader + "|CPT=XXX"

   else :  # Data PDU

      decodedHeader = "D/C=1"

      RF = (rlcBytes[0] >> 6) & 0x01  # Decode RF Field and Print the value

      if RF == 0 :

         decodedHeader = decodedHeader + "|RF=0"

      else :

         decodedHeader = decodedHeader + "|RF=1"

      P = (rlcBytes[0] >> 5) & 0x01

      if P == 0 : # Decode P Field and Print the value

         decodedHeader = decodedHeader + "|P=0"

      else :

         decodedHeader = decodedHeader + "|P=1"

      FI = (rlcBytes[0] >> 3) & 0x03 # Decode FI Field and Print the value

      if FI == 0 :

         decodedHeader = decodedHeader + "|FI=00"

      elif FI == 1 :

         decodedHeader = decodedHeader + "|FI=01"

      elif FI == 2 :

         decodedHeader = decodedHeader + "|FI=10"

      else :

         decodedHeader = decodedHeader + "|FI=11"

      E = (rlcBytes[0] >> 2) & 0x01

      if E == 0 : # Decode E Field and Print the value

         decodedHeader = decodedHeader + "|E=0"

      else :

         decodedHeader = decodedHeader + "|E=1"

      SN = (((rlcBytes[0]) & 0x03) << 8 )  + rlcBytes[1] # Decode SN Field and Print the value

      decodedHeader = decodedHeader + "|SN=" + str(SN)

      

   return decodedHeader # End of decodeRlcAmHeader

 

# Open files for input and output. Rlc.txt is the file that contains RLC log files shown above.

# If you have different file name, change "Rlc.txt" to whatever your file is

# "RlcOut.csv" is the file to which the extracted/decoded RLC information. I am writing the output

# in CSV format so that I can do further post processing in Microsoft Excel.

fHandleOut = open("RlcOut.csv","w")

fHandleIn = open("Rlc.txt","r")

 

# Write column titles as the first line of the output file.

outStr = "DIR,Time,Header,Length,PDU\n"

fHandleOut.write(outStr)

 

# Read the input file line by line and check if the line contains any information that I need.

# If it contains any information that I need, extract the information and do processing.

# Otherwise, discard the read line and read next line.

for readStr in fHandleIn :

    outStr = ""

    if readStr.find("LTE_MAC_DATA_REQ") >= 0 :

       outStr = outStr + "DL," + readStr[len(readStr)-12:len(readStr)-1] + ","

       for readStr in fHandleIn :

          if readStr.find("Message Data") >= 0 :

             rlcLen = readStr[readStr.find("Length:")+7:readStr.find(")")]

             readStr = fHandleIn.readline()

             readStr = readStr.replace(" |   |   |   |   |   |   |      ","")

             rlcHeader = decodeRlcAmHeader(readStr)

             outStr = outStr + rlcHeader + "," + rlcLen + "," + readStr

             break

    elif readStr.find("LTE_MAC_DATA_IND") >= 0 :

       outStr = outStr + "UL," + readStr[len(readStr)-12:len(readStr)-1] + ","

       for readStr in fHandleIn :

          if readStr.find("Message Data") >= 0 :

             rlcLen = readStr[readStr.find("Length:")+7:readStr.find(")")]

             readStr = fHandleIn.readline()

             readStr = readStr.replace(" |   |   |   |   |   |   |      ","")

             rlcHeader = decodeRlcAmHeader(readStr)

             outStr = outStr + rlcHeader + "," + rlcLen + "," + readStr

             break

    if outStr != ""  :

       fHandleOut.write(outStr)

 

# After reading and processing all the lines in the input file, close both input and output file

fHandleOut.close()

fHandleIn.close()