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()