Files
openairinterface5g/openair3/NAS/TEST/MSC/msc_gen.py
T
2015-10-06 16:53:42 +00:00

355 lines
14 KiB
Python
Executable File

#!/usr/bin/python
# -*- coding: utf-8 -*-
# Lionel GAUTHIER
# This script is a downgrade of a python script written for the openair stack, generating sequence diagrams charts, displaying
# messages exchanged between LTE access stratum protocol entities.
# This script needs mscgen tool (http://www.mcternan.me.uk/mscgen/).
#
# The aim of this script is to collect some traces from oaisim stack and generate a mscgen script, then generate a sequence diagram
# image (png or jpeg) based on the scripts generated.
# An example of how it can be invoqued: msc_gen.py /tmp/msc_log.txt /tmp/msc_log2.txt msc_logx.txt are input text files,
# They/It are/is generated by the execution of executables in linux user space. May be it is better to operate on log files 'grepped' with MSC:
# ./my_exe.exe | grep \[MSC > /tmp/msc_log1.txt
# Now, examples of how to generate a mscgen trace in a C executable:
# -First you have to declare the instance(s) of the protocol(s) that will send or receive messages.
# This is done with the following line:
# [MSC_NEW][system time][protocol_name=instance_name]
# examples:
# printf("[MSC_NEW][%s][MIH-F=%s]\n", getTimeStamp4Log(), g_mihf_id); for declaring a new instance of a protocol entity of type MIH-F
# with an instance name g_mihf_id (of type char*)
# printf("[MSC_NEW][%s][NAS=%s]\n", getTimeStamp4Log(), "nas"); other example.
# This declaration of instances of protocols is mandatory to for this script to work.
#
# -Then for tracing a message you have to log a line following this format:
# [MSC_MSG][system time][source instance_name][--- message_name --->][destination instance_name]
# Note:
# ---> means a message that has been received correctly by destination
# ---x means a message lost by destination
# example
# NOTICE("[MSC_MSG][%s][%s][--- Link_Register.indication\\n%s ---x][%s]\n",getTimeStamp4Log(),g_link_id,g_msc_gen_buf,g_mihf_id);
#
import sys
import subprocess
import re
import socket
import datetime
import os.path
from datetime import date
MSCGEN_OUTPUT_TYPE = "png"
MAX_MESSAGES_PER_PAGE = 36
SYSTEM_FRAME_NUMBER_STR = 'FRAME'
MODULE_STR = 'MOD'
RADIO_BEARER_STR = 'RB'
MSC_NEW_STR = '[MSC_NEW]'
MSC_MSG_STR = '[MSC_MSG]'
MSC_NBOX_STR = '[MSC_NBOX]'
MSC_BOX_STR = '[MSC_BOX]'
MSC_ABOX_STR = '[MSC_ABOX]'
MSC_RBOX_STR = '[MSC_RBOX]'
# This dic is filled as follow : g_entities_dic[protocol_instance_name].append(protocol_name)
# where protocol_name can be any of the following MI-USER, MIH-F, RAL, LINK-SAP
g_entities_dic = {}
g_reverse_entities_dic = {}
# g_messages is filled with dictionnaries:
# message_dic['entity_src'] = protocol_entity_src
# message_dic['entity_dst'] = protocol_entity_dest
# message_dic['msg'] = message
# message_dic['line_color'] = g_display_color[entity_name]
# message_dic['text_color'] = g_display_color[entity_name]
# message_dic['time'] = system_frame_number
# message_dic['seq_no'] = sequence_number_generator()
# g_messages.append(message_dic)
g_messages = []
g_messages_dic = {}
# g_display_order_dic is a dictionnary where the order of the display of entities sharing the same module identifier is hardcoded
#MAC and PHY valus have to be above num max radio bearer value
#g_display_order_dic = {'MIH-USER': 0, 'MIH-F': 1, 'RAL': 3, 'NAS': 4}
g_display_order_dic = {'NAS-UE': 0, 'AS': 1, 'NAS-MME': 3}
# Display color of messages of sending entities
g_display_color = {'IP': '\"teal\"',
'RRC_UE': '\"red\"',
'MIH-USER': '\"black\"',
'MIH-F': '\"black\"',
'RAL': '\"black\"',
'RAL_M': '\"black\"',
'RLC_UM': '\"navy\"',
'RLC_TM': '\"navy\"',
'NAS': '\"black\"',
'MAC_eNB': '\"indigo\"',
'PHY': '\"purple\"',
'NAS-UE': '\"black\"',
'NAS-MME': '\"black\"',
'AS': '\"black\"'}
g_final_display_order_list = []
g_sequence_generator = 0
def sequence_number_generator():
global g_sequence_generator
l_seq = g_sequence_generator
g_sequence_generator = g_sequence_generator + 1
return l_seq
def parse_log_file_for_discovering_protocol_entities(filename):
global g_entities_dic
global g_entities
global g_messages
global g_final_display_order_list
#open TXT file that contain OAI filtered traces for mscgen
fhandle = open(filename, 'r')
fcontent = fhandle.read()
fhandle.close()
# split file content in lines
lines = fcontent.splitlines()
for line in lines:
system_time = 'unknown'
# if line is a trace of the creation of a new protocol instance
if MSC_NEW_STR in line:
partition = line.rpartition(MSC_NEW_STR)
msc_log_string = partition[2]
#print (" %s " % msc_log_string)
partition = msc_log_string.split('[')
print ("\n\n %s \n" % partition)
#if len(partition) == 2:
item = partition[1]
item = item.strip()
item = item.strip(']')
system_time = item.split(' ')[-1]
print ("NEW system_time %s " % system_time)
item = partition[2]
item = item.strip()
item = item.strip(']')
protocol_entity_type = item.split('=')[0]
protocol_entity_name = item.split('=')[-1]
print ("NEW protocol_entity_type %s " % protocol_entity_type)
print ("NEW protocol_entity_name %s " % protocol_entity_name)
if protocol_entity_name not in g_entities_dic:
g_entities_dic[protocol_entity_name] = protocol_entity_type
if protocol_entity_type not in g_reverse_entities_dic:
g_reverse_entities_dic[protocol_entity_type] = protocol_entity_name
else:
entity_name_list = g_reverse_entities_dic[protocol_entity_type]
entity_name_list.append(protocol_entity_name)
g_reverse_entities_dic[protocol_entity_type] = entity_name_list
#print (" g_entities_dic[%d][%d].append(%s)" % (module_id_int, radio_bearer_id_int, entity_name_src))
print (" g_entities_dic= %s\n\n" % (g_entities_dic))
print (" g_reverse_entities_dic= %s\n\n" % (g_reverse_entities_dic))
#g_entities.append(protocol_entity_type)
#print (" %s \n" % protocol_entity)
def parse_log_file(filename):
global g_entities_dic
global g_entities
global g_messages
global g_final_display_order_list
#open TXT file that contain OAI filtered traces for mscgen
fhandle = open(filename, 'r')
fcontent = fhandle.read()
fhandle.close()
# split file content in lines
lines = fcontent.splitlines()
for line in lines:
system_time = 'unknown'
message = 'unknown'
entity_name_src = 'unknown'
entity_name_dest = 'unknown'
# if line is a trace of the creation of a new protocol instance
if MSC_MSG_STR in line:
partition = line.strip().rpartition(MSC_MSG_STR)
msc_log_string = partition[2].strip()
print (" ++++ %s " % msc_log_string)
partition = msc_log_string.split('[')
print (" ++++ %s " % partition)
#if len(partition) == 9:
message_dic = {}
system_time = partition[1].strip().split(' ')[-1].strip(']')
message_dic['display_time'] = system_time
seconds_int = int(system_time.split(':')[0])
micro_seconds_int = int(system_time.split(':')[-1])
system_time_int = seconds_int*1000000 + micro_seconds_int
system_time=str(system_time_int)
print ('system_time %s' % system_time)
entity_name_src = partition[2].strip().split(' ')[-1].strip(']')
print ('entity_name_src %s' % entity_name_src)
message = partition[3].strip().strip(']').strip()
if (message[-1] == 'x') or (message[-1] == 'X'):
message_dic['arc'] = '-x'
elif message[-1] == '>':
message_dic['arc'] = '=>'
message = message.strip('<').strip('>').strip('x').strip('X').strip('-').strip('=').strip()
print ('message %s' % message)
entity_name_dest = partition[4].strip().split(' ')[-1].strip(']')
print ('entity_name_dest %s' % entity_name_dest)
message_dic['entity_src'] = entity_name_src
message_dic['entity_dst'] = entity_name_dest
message_dic['msg'] = message
message_dic['line_color'] = g_display_color[g_entities_dic[entity_name_src]]
message_dic['text_color'] = g_display_color[g_entities_dic[entity_name_src]]
message_dic['time'] = system_time
#message_dic['seq_no'] = sequence_number_generator()
print ('%s\n\n' % message_dic)
g_messages_dic[system_time_int] = message_dic
#g_messages.append(message_dic)
#TODO !!!
if MSC_RBOX_STR in line:
partition = line.strip().rpartition(MSC_RBOX_STR)
msc_log_string = partition[2].strip()
print (" ==== %s " % msc_log_string)
partition = msc_log_string.split('[')
print (" ==== %s " % partition)
#TODO !!!
def generate_sorted_message_list():
first_time_stamp = 0
for system_time_int in sorted(g_messages_dic.iterkeys()):
if first_time_stamp == 0:
first_time_stamp = system_time_int
message_dic = g_messages_dic[system_time_int]
message_dic['seq_no'] = sequence_number_generator()
message_dic['display_time'] = str(system_time_int - first_time_stamp)
g_messages.append(message_dic)
def generate_sorted_entity_display_list():
module_display_order_dic = {}
for entity_name in sorted(g_entities_dic.iterkeys()):
module_display_order_dic[g_display_order_dic[g_entities_dic[entity_name]]] = entity_name
print("------------------------------------")
print(" %s " % (module_display_order_dic))
for display_priority in sorted(module_display_order_dic.iterkeys()):
g_final_display_order_list.append(module_display_order_dic[display_priority])
def msc_chart_write_header(fileP):
global g_final_display_order_list
fileP.write("msc {\n")
fileP.write("width = \"2048\";\n")
entity_line_list_str = ''
for entity in g_final_display_order_list:
entity_line_list_str = entity_line_list_str + ' ' + entity + ','
entity_line_list_str = entity_line_list_str.rstrip().strip(',')
fileP.write(" %s;" % (entity_line_list_str))
def msc_chart_write_footer(fileP):
fileP.write("\n}\n")
def msc_chart_generate(file_nameP):
global MSCGEN_OUTPUT_TYPE
command_line = "mscgen -T " + MSCGEN_OUTPUT_TYPE + " -i " + file_nameP + "; chmod 777 " +file_nameP + ";"
print("Command Line: %s " % (command_line))
fi,fo,fe=os.popen3(command_line)
for i in fe.readlines():
print "error:",i
def get_nem_file_descriptor():
global g_base_file_name
global g_page_index
l_file_name = g_base_file_name + str(g_page_index)+'.txt'
l_file = open(l_file_name, "w", 0777)
return l_file
###### MAIN START HERE #################
num_args = len(sys.argv)
if num_args < 2: # the program name and the arguments
# stop the program and print an error message
sys.exit("Must provide at least one file to parse")
for i in range(1,num_args):
print sys.argv[i]
for i in range(1,num_args):
parse_log_file_for_discovering_protocol_entities(sys.argv[i])
for i in range(1,num_args):
parse_log_file(sys.argv[i])
generate_sorted_message_list()
generate_sorted_entity_display_list()
g_page_index = 0
g_message_index = 0
g_message_index_in_current_page = 0
g_now = datetime.datetime.now()
g_now_formated = g_now.strftime("%Y-%m-%d_%H.%M.%S")
g_currentdir = os.curdir
g_resultdir = os.path.join(g_currentdir, g_now_formated)
os.mkdir(g_resultdir, 0777)
os.chdir(g_resultdir)
g_base_file_name = 'mih_mscgen_page_'
g_file = get_nem_file_descriptor()
msc_chart_write_header(g_file)
for message in g_messages:
if 'msg' in message:
print ('message %s' % message)
g_file.write(" %s%s%s [ label = \"(%d) T%s %s\", linecolour=%s , textcolour=%s ] ;\n" % (message['entity_src'], message['arc'], message['entity_dst'], message['seq_no'], message['display_time'], message['msg'], message['line_color'], message['text_color']))
elif 'box' in message:
g_file.write(" %s %s %s [ label = \"%s\", textbgcolour=%s , textcolour=%s ] ;\n" % (message['entity_src'], message['box_type'], message['entity_dst'], message['box'], message['textbg_color'], message['text_color']))
g_message_index = g_message_index + 1
g_message_index_in_current_page = g_message_index_in_current_page + 1
if (g_message_index_in_current_page == MAX_MESSAGES_PER_PAGE):
msc_chart_write_footer(g_file)
g_file.close()
msc_chart_generate(g_file.name)
g_page_index = g_page_index + 1
g_message_index_in_current_page = 0
g_file = get_nem_file_descriptor()
msc_chart_write_header(g_file)
msc_chart_write_footer(g_file)
g_file.close()
if g_message_index_in_current_page >= 1:
msc_chart_generate(g_file.name)
else:
print("Removing empty seq diagram file: %s " % (g_file.name))
os.remove(g_file.name)