Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

5G DCI Message Decoding and Analysis #123

Open
wants to merge 35 commits into
base: 5g-dci
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
aa01320
added 5G DCI Message log packet type and associated name
MattBM7 Nov 4, 2022
d86ea2a
create entry for nr_dci_analyzer
LzokChen Nov 6, 2022
72e5044
Merge pull request #1 from LzokChen/5g-dci
MattBM7 Nov 6, 2022
97931c8
dci format and decoding up to DCI Info
MattBM7 Nov 6, 2022
f88b385
changed to big endian formatting
MattBM7 Nov 7, 2022
6d34584
general DCI message decoding and UL_0_1 decoding, not tested yet
MattBM7 Nov 7, 2022
31e183b
added DL decoding, not tested yet
MattBM7 Nov 7, 2022
5a0dcea
changed format to little endian
MattBM7 Nov 8, 2022
8bf50e9
mostly successful decoding
MattBM7 Nov 8, 2022
23e459e
added MacVersion structure
MattBM7 Nov 8, 2022
de52049
added Version 131077 and Log Fields Change structures
MattBM7 Nov 8, 2022
dd976fa
added System Time object
MattBM7 Nov 8, 2022
4d74ac5
added Raw DCI Payload, UL, DL structures
MattBM7 Nov 8, 2022
aa85d30
DAI 1 mask fix, clean up
MattBM7 Nov 8, 2022
ea06ca8
added DCI Params structure
MattBM7 Nov 8, 2022
c34c424
added dynamic version number structure
MattBM7 Nov 8, 2022
d5980c8
add evalution method for decoder
lc4324 Nov 9, 2022
40ec5ac
5G dci simple analysis of assignment pattern and UL throughput
LzokChen Dec 3, 2022
02ef325
5G dci simple analysis of DL throughput
LzokChen Dec 5, 2022
e644d5c
adjust evaluate.py for latest format change
lc4324 Dec 9, 2022
94db159
modify nr_dci_analyzer: draw the data for a time interval
LzokChen Dec 9, 2022
c13f240
modify nr_dci_analyzer: draw the data for a time interval
LzokChen Dec 9, 2022
1ff79f4
add new plot methods
lc4324 Dec 9, 2022
75fc674
added 5G PDCP DL Data Pdu packet type and associated name
MattBM7 Feb 3, 2023
ab69251
added nr PDCP DL data PDU decoding and files
MattBM7 Feb 3, 2023
dbd8c8c
added Fmt and ValueName structures
MattBM7 Feb 3, 2023
9c416e7
decoded except for RX Timestick float calculation
MattBM7 Feb 4, 2023
77eb1b0
made analyzer
MattBM7 Feb 4, 2023
0b6bb66
working decoded for basic version structure
MattBM7 Feb 6, 2023
9fa7e10
successful decoding up to PDCP State
MattBM7 Feb 7, 2023
7f386d1
decoded except for RX Timetick and top level Versions structure
MattBM7 Feb 7, 2023
03de1a6
decoded except for RX Timetick float value
MattBM7 Feb 7, 2023
eb6538e
comments and cleanup
MattBM7 Feb 7, 2023
909d67f
PDCP analysis and testing
MattBM7 Mar 3, 2023
de14d30
more analysis
MattBM7 Mar 14, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
build/
examples/
wireshark-3.4.0/
MobileInsight.egg-info/
dist/MobileInsight-6.0.0-py3.9-macosx-10.9-x86_64.egg
ws-3.4.0-radio-bearer-config.patch
ws_dissector/ws_dissector
examples/test.txt
*.db
.DS_Store
41 changes: 41 additions & 0 deletions dci_proj_test/5g_dci_analysis_testing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/usr/bin/python
# Filename: 5g_dci_analysis_testing.py
import os
import sys
import math

"""
Offline analysis by replaying logs
"""

# Import MobileInsight modules
from mobile_insight.monitor import OfflineReplayer
from mobile_insight.analyzer import MsgLogger, NrDciAnalyzer
if __name__ == "__main__":

# Initialize a monitor
src = OfflineReplayer()
src.set_input_path("./logs/")
# src.enable_log_all()

src.enable_log("NR_DCI_Message")

logger = MsgLogger()
logger.set_decode_format(MsgLogger.DICT)
logger.set_dump_type(MsgLogger.FILE_ONLY)
logger.save_decoded_msg_as("./decoded_dci.txt")
logger.set_source(src)

# # Analyzers
nr_dci_analyzer = NrDciAnalyzer()
nr_dci_analyzer.set_source(src) # bind with the monitor

src.run()

start_time = 0
end_time = math.inf
nr_dci_analyzer.draw_assignment_pattern(figure_size=(35,4), start_time=start_time, end_time=end_time)
nr_dci_analyzer.draw_throughput_ul(figure_size=(30,7), outlier_filter_m=3, start_time=start_time, end_time=end_time, fillzero=True)
nr_dci_analyzer.draw_throughput_dl(figure_size=(30,7), outlier_filter_m=3, start_time=start_time, end_time=end_time, fillzero=True)
nr_dci_analyzer.draw_aggregated_frame()
nr_dci_analyzer.reset()
165 changes: 165 additions & 0 deletions dci_proj_test/evaluate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
import ast
import datetime
from deepdiff import DeepDiff
from pprint import pprint

"""
Test the decoder by comparing all messages with the corresponding ground truth.
Note that the input test.txt file should be in DICT format.
"""

# helper function for get_msg_gt. read dci according to format
def read_dci(fields):
dci = {}
dci['Carrier ID'] = int(fields[0])
dci['RNTI Type'] = fields[1]
dci['DCI Format'] = fields[2]
dci['Aggregation Level'] = fields[3]
dci['Raw DCI Included'] = int(fields[4])
dci['DCI Params'] = {}
if dci['DCI Format'] == 'DL_1_0':
dci['DCI Params']['DL'] = {}
dci['DCI Params']['DL']['Bandwidth Part Indicator'] = int(fields[5])
dci['DCI Params']['DL']['Time Resource Assignment'] = int(fields[6])
dci['DCI Params']['DL']['TB 1 MCS'] = int(fields[7])
dci['DCI Params']['DL']['TB 1 New Data Indicator'] = int(fields[8])
dci['DCI Params']['DL']['DL Assignment Index'] = int(fields[9])
dci['DCI Params']['DL']['TPC Command For Sched PUCCH'] = int(fields[10])
dci['DCI Params']['DL']['PUCCH Resource Indicator'] = int(fields[11])
dci['DCI Params']['DL']['PDSCH Harq Feedback Timing'] = int(fields[12])
dci['DCI Params']['DL']['CBG Transmission Info'] = int(fields[13])
dci['DCI Params']['DL']['CBG Flushing Out Info'] = int(fields[14])
dci['DCI Params']['DL']['Transmission Config Ind'] = int(fields[15])
dci['DCI Params']['DL']['SRS Request'] = int(fields[16])
dci['DCI Params']['DL']['Carrier ID'] = int(fields[17])
dci['DCI Params']['DL']['HARQ ID'] = int(fields[18])
elif dci['DCI Format'] == 'UL_0_1':
dci['Raw DCI[2]'] = fields[5]
dci['Raw DCI[1]'] = fields[6]
dci['Raw DCI[0]'] = fields[7]
dci['Raw DCI Payload'] = {}
dci['Raw DCI Payload']['Raw DCI Payload[2]'] = int(dci['Raw DCI[2]'], base=16)
dci['Raw DCI Payload']['Raw DCI Payload[1]'] = int(dci['Raw DCI[1]'], base=16)
dci['Raw DCI Payload']['Raw DCI Payload[0]'] = int(dci['Raw DCI[0]'], base=16)
dci['DCI Params']['UL'] = {}
dci['DCI Params']['UL']['DCI Format'] = dci['DCI Format']
dci['DCI Params']['UL']['Carrier ID'] = int(fields[8])
dci['DCI Params']['UL']['NDI'] = int(fields[9])
dci['DCI Params']['UL']['MCS'] = int(fields[10])
dci['DCI Params']['UL']['Freq Hopping Flag'] = int(fields[11])
dci['DCI Params']['UL']['RV'] = int(fields[12])
dci['DCI Params']['UL']['HARQ ID'] = int(fields[13])
dci['DCI Params']['UL']['PUSCH TPC'] = int(fields[14])
dci['DCI Params']['UL']['UL SUL Ind'] = int(fields[15])
dci['DCI Params']['UL']['Symbol Alloc Index'] = int(fields[16])
dci['DCI Params']['UL']['BWP Ind'] = int(fields[17])
dci['DCI Params']['UL']['PTRS DMRS Association'] = int(fields[18])
dci['DCI Params']['UL']['Beta Offset Ind'] = int(fields[19])
dci['DCI Params']['UL']['RB Assignment'] = int(fields[20])
dci['DCI Params']['UL']['UL SCH Ind'] = int(fields[21])
dci['DCI Params']['UL']['DAI 1'] = int(fields[22])
dci['DCI Params']['UL']['DAI 2'] = int(fields[23])
dci['DCI Params']['UL']['SRS Resource Indication'] = int(fields[24])
dci['DCI Params']['UL']['Precoding Layer Info'] = int(fields[25])
dci['DCI Params']['UL']['Antenna Ports'] = int(fields[26])
dci['DCI Params']['UL']['DMRS Seq Init Flag'] = int(fields[27])
dci['DCI Params']['UL']['SRS Request'] = int(fields[28])
dci['DCI Params']['UL']['CSI Request'] = int(fields[29])
dci['DCI Params']['UL']['CBGTI'] = int(fields[30])
dci['DCI Params']['UL']['Reserved MCE Enable'] = int(fields[31])
dci['DCI Params']['UL']['RA Type'] = int(fields[32])
dci['DCI Params']['UL']['Prune Reason'] = fields[33]
dci['DCI Params']['UL']['Pruned Mask'] = fields[34]
elif dci['DCI Format'] == 'DL_1_1':
dci['DCI Params']['DL'] = {}
dci['DCI Params']['DL']['Bandwidth Part Indicator'] = int(fields[5])
dci['DCI Params']['DL']['Time Resource Assignment'] = int(fields[6])
dci['DCI Params']['DL']['TB 1 MCS'] = int(fields[7])
dci['DCI Params']['DL']['TB 1 New Data Indicator'] = int(fields[8])
dci['DCI Params']['DL']['DL Assignment Index'] = int(fields[9])
dci['DCI Params']['DL']['TPC Command For Sched PUCCH'] = int(fields[10])
dci['DCI Params']['DL']['PUCCH Resource Indicator'] = int(fields[11])
dci['DCI Params']['DL']['PDSCH Harq Feedback Timing'] = int(fields[12])
dci['DCI Params']['DL']['CBG Transmission Info'] = int(fields[13])
dci['DCI Params']['DL']['CBG Flushing Out Info'] = int(fields[14])
dci['DCI Params']['DL']['Transmission Config Ind'] = int(fields[15])
dci['DCI Params']['DL']['SRS Request'] = int(fields[16])
dci['DCI Params']['DL']['Carrier ID'] = int(fields[17])
dci['DCI Params']['DL']['HARQ ID'] = int(fields[18])
return dci

# get the groud truth from the example logs
def get_msg_gt():
f_groundtruth = open("diag_log_20221101_141847_68b329da9893e34099c7d8ad5cb9c940_Google-Pixel5_.txt", "r")
groundtruth = f_groundtruth.readlines()
f_groundtruth.close()
msg_gt = []
for i in range(len(groundtruth)):
if "Major.Minor Version" in groundtruth[i]:
m = {}
m['MacVersion'] = {}
tmp1 = [x.strip() for x in groundtruth[i].split()]
m['MacVersion']['Major Version'] = int(tmp1[-2][:-1])
m['MacVersion']['Minor Version'] = int(tmp1[-1])
m['MacVersion']['Major.Minor Version'] = m['MacVersion']['Major Version']
m['MacVersion']['{id: 2026230 }'] = m['MacVersion']['Minor Version']
tmp2 = [x.strip() for x in groundtruth[i+1].split()]
m['Version 131077'] = {}
m['Version 131077']['Log Fields Change BMask'] = int(tmp2[-1])
tmp3 = [x.strip() for x in groundtruth[i+2].split()]
m['Version 131077']['Num Records'] = int(tmp3[-1])
m['Records'] = []
idx = 0
for j in range(m['Version 131077']['Num Records']):
record = {}
fields = [x.strip() for x in groundtruth[i+13+idx].split('|') if x.strip() != '']
idx += 1
record['System Time'] = {}
record['System Time']['Slot'] = int(fields[1])
record['System Time']['Num'] = fields[2]
record['System Time']['Frame'] = int(fields[3])
record['Num DCI'] = int(fields[4])
record['DCI Info'] = [read_dci(fields[5:])]
if record['Num DCI'] > 0:
for k in range(record['Num DCI']-1):
record['DCI Info'].append(read_dci([x.strip() for x in groundtruth[i+13+idx].split('|') if x.strip() != '']))
idx += 1
m['Records'].append(record)
tmp4 = [x.strip() for x in groundtruth[i+13+idx+3].split()]
m['log_msg_len'] = int(tmp4[-1])
msg_gt.append(m)
return msg_gt


# ----------------------------------------------------------------------------------------------------------------------------------------

f = open("decoded_dci.txt", "r")

# ground truth
msg_gt = get_msg_gt()

all_match = True

# compare all messages
for i in range(len(msg_gt)):
gt = msg_gt[i]
line = f.readline()
msg = eval(line)
# skip the packets that are not NR_DCI_Message
while msg['type_id'] != 'NR_DCI_Message':
line = f.readline()
msg = eval(line)
# remove fields we don't care about
msg.pop('type_id', None)
msg.pop('timestamp', None)
msg['Version 131077'].pop('Log Fields Change', None)
comparison = DeepDiff(gt, msg)
if comparison != {}:
all_match = False
print("MSG", i, "differs:")
pprint(comparison, indent=2)

f.close()

if all_match:
print("All {} decoded messages match the ground truth!".format(len(msg_gt)))
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
7 changes: 7 additions & 0 deletions dm_collector_c/consts.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ enum LogPacketType {

// 5G PDCP
NR_PDCP_UL_Control_Pdu = 0xB861,
NR_PDCP_DL_Data_Pdu = 0xB840,

// 5G L2
NR_L2_UL_TB = 0xB872,
Expand All @@ -164,6 +165,8 @@ enum LogPacketType {
NR_ML1_Searcher_Measurement_Database_Update_Ext = 0xB97F,
NR_ML1_Serving_Cell_Beam_Management = 0xB975,

// 5G DCI
NR_DCI_Message = 0xB885,
};

// Mapping type IDs to names
Expand Down Expand Up @@ -387,6 +390,8 @@ const ValueName LogPacketTypeID_To_Name [] = {

{NR_PDCP_UL_Control_Pdu,
"5G_NR_PDCP_UL_Control_Pdu", true},
{NR_PDCP_DL_Data_Pdu,
"NR_PDCP_DL_Data_Pdu", true},

{NR_L2_UL_TB,
"5G_NR_L2_UL_TB", true},
Expand All @@ -412,6 +417,8 @@ const ValueName LogPacketTypeID_To_Name [] = {
{ NR_ML1_Serving_Cell_Beam_Management,
"5G_NR_ML1_Serving_Cell_Beam_Management", true },

{ NR_DCI_Message,
"NR_DCI_Message", true },

{Modem_debug_message,
"Modem_debug_message", false},
Expand Down
10 changes: 9 additions & 1 deletion dm_collector_c/log_packet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@
#include "nr_rlc_dl_stats.h"
#include "nr_nas_mm5g_state.h"
#include "nr_pdcp_ul_control_pdu.h"
#include "nr_pdcp_dl_data_pdu.h"
#include "nr_dci_message.h"
#include "gnss_bds_measurement_report.h"
#include "gnss_gps_measurement_report.h"
#include "gnss_glonass_measurement_report.h"
Expand Down Expand Up @@ -12259,6 +12261,9 @@ on_demand_decode (const char *b, size_t length, LogPacketType type_id, PyObject*
b, offset, length, result);
offset += _decode_nr_pdcp_ul_control_pdu_payload(b, offset, length, result);
break;
case NR_PDCP_DL_Data_Pdu:
offset += _decode_nr_pdcp_dl_data_pdu(b, offset, length, result);
break;
case NR_NAS_MM5G_State:
offset += _decode_by_fmt(NrNasMm5gState_Fmt,
ARRAY_SIZE(NrNasMm5gState_Fmt, Fmt),
Expand Down Expand Up @@ -12288,7 +12293,10 @@ on_demand_decode (const char *b, size_t length, LogPacketType type_id, PyObject*
ARRAY_SIZE(GnssGal_Fmt, Fmt),
b, offset, length, result);
offset += _decode_gnss_gal_payload(b, offset, length, result);
break;
break;
case NR_DCI_Message:
offset += _decode_nr_DCI(b, offset, length, result);
break;
default:
break;
};
Expand Down
Loading