T: add a tracer 'gnb_mac'
To see MAC scheduling decisions. May be useful for debugging.
This commit is contained in:
committed by
Robert Schmidt
parent
c4562df2e7
commit
fcd0013981
@@ -3,6 +3,7 @@
|
||||
genids
|
||||
tracer/enb
|
||||
tracer/gnb
|
||||
tracer/gnb_mac
|
||||
tracer/extract_config
|
||||
tracer/record
|
||||
tracer/replay
|
||||
|
||||
@@ -62,6 +62,10 @@ if(T_TRACER_GUI)
|
||||
tracer_logger tracer_view tracer_events)
|
||||
target_link_libraries(gnb PRIVATE png)
|
||||
|
||||
add_executable(gnb_mac gnb_mac.c)
|
||||
target_link_libraries(gnb_mac PRIVATE tracer_utils tracer_filter tracer_gui
|
||||
tracer_logger tracer_view tracer_events)
|
||||
|
||||
add_executable(ue ue.c)
|
||||
target_link_libraries(ue PRIVATE tracer_utils tracer_view tracer_gui
|
||||
tracer_logger tracer_filter tracer_events)
|
||||
@@ -77,5 +81,5 @@ if(T_TRACER_GUI)
|
||||
|
||||
add_subdirectory(gui)
|
||||
|
||||
add_dependencies(T_tools enb gnb ue vcd to_vcd)
|
||||
add_dependencies(T_tools enb gnb gnb_mac ue vcd to_vcd)
|
||||
endif()
|
||||
|
||||
@@ -8,7 +8,7 @@ XLIBS=-lX11 -lpng -lXft
|
||||
|
||||
all: record replay extract_config textlog enb ue vcd macpdu2wireshark \
|
||||
extract_input_subframe extract_output_subframe to_vcd extract multi \
|
||||
gnb t_tracer_app_gnb t_tracer_app_ue
|
||||
gnb t_tracer_app_gnb t_tracer_app_ue gnb_mac
|
||||
|
||||
record: utils.o record.o database.o configuration.o
|
||||
$(CC) $(CFLAGS) -o record $^ $(LIBS)
|
||||
@@ -65,14 +65,18 @@ gnb: utils.o gnb.o database.o event.o handler.o configuration.o \
|
||||
filter/filter.a
|
||||
$(CC) $(CFLAGS) -o gnb $^ $(LIBS) $(XLIBS)
|
||||
|
||||
t_tracer_app_gnb: utils.o t_tracer_app_gnb.o database.o event.o handler.o configuration.o \
|
||||
logger/logger.a filter/filter.a
|
||||
t_tracer_app_gnb: utils.o t_tracer_app_gnb.o database.o event.o handler.o \
|
||||
configuration.o logger/logger.a filter/filter.a
|
||||
$(CC) $(CFLAGS) -o t_tracer_app_gnb $^ $(LIBS) $(XLIBS)
|
||||
|
||||
t_tracer_app_ue: utils.o t_tracer_app_ue.o database.o event.o handler.o configuration.o \
|
||||
logger/logger.a filter/filter.a
|
||||
t_tracer_app_ue: utils.o t_tracer_app_ue.o database.o event.o handler.o \
|
||||
configuration.o logger/logger.a filter/filter.a
|
||||
$(CC) $(CFLAGS) -o t_tracer_app_ue $^ $(LIBS) $(XLIBS)
|
||||
|
||||
gnb_mac: gnb_mac.o gui/gui.a view/view.a logger/logger.a filter/filter.a \
|
||||
utils.o database.o configuration.o handler.o event.o
|
||||
$(CC) $(CFLAGS) -o gnb_mac $^ $(LIBS) $(XLIBS)
|
||||
|
||||
multi.o: ../incgen/T_IDs.h
|
||||
|
||||
../incgen/T_IDs.h: ../T_messages.txt
|
||||
@@ -98,7 +102,8 @@ filter/filter.a:
|
||||
clean:
|
||||
rm -f *.o core tracer_remote textlog enb ue vcd record replay
|
||||
rm -f extract_config macpdu2wireshark extract_input_subframe
|
||||
rm -f extract_output_subframe to_vcd extract multi gnb t_tracer_app_gnb t_tracer_app_ue
|
||||
rm -f extract_output_subframe to_vcd extract multi gnb
|
||||
rm -f t_tracer_app_gnb t_tracer_app_ue gnb_mac
|
||||
cd gui && $(MAKE) clean
|
||||
cd view && $(MAKE) clean
|
||||
cd logger && $(MAKE) clean
|
||||
|
||||
@@ -0,0 +1,332 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "gui/gui.h"
|
||||
#include "view/view.h"
|
||||
#include "logger/logger.h"
|
||||
#include "filter/filter.h"
|
||||
#include "database.h"
|
||||
#include "configuration.h"
|
||||
#include "handler.h"
|
||||
|
||||
typedef struct {
|
||||
int used;
|
||||
} ue_list_item;
|
||||
|
||||
typedef struct {
|
||||
widget *container;
|
||||
} gnb_gui;
|
||||
|
||||
typedef struct {
|
||||
int socket;
|
||||
gui *g;
|
||||
gnb_gui *gg;
|
||||
event_handler *h;
|
||||
void *database;
|
||||
ue_list_item ues[65536];
|
||||
int rnti_arg;
|
||||
} gnb_data;
|
||||
|
||||
void *gui_thread(void *_g)
|
||||
{
|
||||
gui *g = _g;
|
||||
gui_loop(g);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void add_ue(gnb_data *gd, int rnti, int lcid)
|
||||
{
|
||||
event_handler *h = gd->h;
|
||||
void *database = gd->database;
|
||||
gnb_gui *gg = gd->gg;
|
||||
gui *g = gd->g;
|
||||
widget *line;
|
||||
widget *w, *w2, *col;
|
||||
view *v;
|
||||
logger *l;
|
||||
|
||||
gd->ues[rnti].used = 1;
|
||||
|
||||
line = new_container(g, HORIZONTAL);
|
||||
widget_add_child(g, gg->container, line, -1);
|
||||
|
||||
/* label */
|
||||
char s[512];
|
||||
sprintf(s, "UE %d", rnti);
|
||||
widget *label = new_label(g, s);
|
||||
widget_add_child(g, line, label, -1);
|
||||
|
||||
/* DL MCS */
|
||||
w = new_xy_plot(g, 128, 55, "DL mcs", 20);
|
||||
xy_plot_set_range(g, w, 0, 1024*20, -2, 30);
|
||||
widget_add_child(g, line, w, -1);
|
||||
l = new_ticked_ttilog(h, database, "GNB_PHY_DL_TICK", "frame", "slot",
|
||||
"GNB_MAC_DL", "mcs", 0, -1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 20);
|
||||
logger_add_view(l, v);
|
||||
logger_set_filter(l,
|
||||
filter_eq(
|
||||
filter_evarg(database, "GNB_MAC_DL", "rnti"),
|
||||
filter_int(rnti)));
|
||||
|
||||
/* DL TBS */
|
||||
col = new_container(g, VERTICAL);
|
||||
widget_add_child(g, line, col, -1);
|
||||
w = new_xy_plot(g, 70, 10, "DL tbs", 35);
|
||||
w2 = new_textarea(g, 70, 11, 64);
|
||||
xy_plot_set_range(g, w, 0, 1024*20, 0, 1000);
|
||||
xy_plot_set_tick_type(g, w, XY_PLOT_SCROLL_TICK);
|
||||
widget_add_child(g, col, w2, -1);
|
||||
widget_add_child(g, col, w, -1);
|
||||
container_set_child_growable(g, col, w, 1);
|
||||
l = new_ticked_ttilog(h, database, "GNB_PHY_DL_TICK", "frame", "slot",
|
||||
"GNB_MAC_DL", "tbs", 0, -1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 20);
|
||||
view_tti_enable_automax(v, w2);
|
||||
logger_add_view(l, v);
|
||||
logger_set_filter(l,
|
||||
filter_eq(
|
||||
filter_evarg(database, "GNB_MAC_DL", "rnti"),
|
||||
filter_int(rnti)));
|
||||
|
||||
/* DL lcid throughput */
|
||||
col = new_container(g, VERTICAL);
|
||||
widget_add_child(g, line, col, -1);
|
||||
sprintf(s, "DL lcid %d", lcid);
|
||||
w = new_xy_plot(g, 70, 10, s, 35);
|
||||
w2 = new_textarea(g, 70, 11, 64);
|
||||
xy_plot_set_range(g, w, 0, 1000, 0, 100000);
|
||||
xy_plot_set_tick_type(g, w, XY_PLOT_SCROLL_TICK);
|
||||
widget_add_child(g, col, w2, -1);
|
||||
widget_add_child(g, col, w, -1);
|
||||
container_set_child_growable(g, col, w, 1);
|
||||
l = new_throughputlog(h, database, "GNB_PHY_DL_TICK", "frame", "slot",
|
||||
"GNB_MAC_LCID_DL", "data_size", 20);
|
||||
v = new_view_scrolltti(10, g, w, new_color(g, "#0c0c72"), w2, 20);
|
||||
logger_add_view(l, v);
|
||||
logger_set_filter(l,
|
||||
filter_and(
|
||||
filter_eq(
|
||||
filter_evarg(database, "GNB_MAC_LCID_DL", "rnti"),
|
||||
filter_int(rnti)),
|
||||
filter_eq(
|
||||
filter_evarg(database, "GNB_MAC_LCID_DL", "lcid"),
|
||||
filter_int(lcid))));
|
||||
|
||||
/* UL MCS */
|
||||
w = new_xy_plot(g, 128, 55, "UL mcs", 20);
|
||||
xy_plot_set_range(g, w, 0, 1024*20, -2, 30);
|
||||
widget_add_child(g, line, w, -1);
|
||||
/* GNB_PHY_DL_TICK (and not UL) because GNB_MAC_UL is from DCI */
|
||||
l = new_ticked_ttilog(h, database, "GNB_PHY_DL_TICK", "frame", "slot",
|
||||
"GNB_MAC_UL", "mcs", 0, -1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 20);
|
||||
logger_add_view(l, v);
|
||||
logger_set_filter(l,
|
||||
filter_eq(
|
||||
filter_evarg(database, "GNB_MAC_UL", "rnti"),
|
||||
filter_int(rnti)));
|
||||
|
||||
/* UL TBS */
|
||||
col = new_container(g, VERTICAL);
|
||||
widget_add_child(g, line, col, -1);
|
||||
w = new_xy_plot(g, 70, 10, "UL tbs", 35);
|
||||
w2 = new_textarea(g, 70, 11, 64);
|
||||
xy_plot_set_range(g, w, 0, 1024*20, 0, 1000);
|
||||
xy_plot_set_tick_type(g, w, XY_PLOT_SCROLL_TICK);
|
||||
widget_add_child(g, col, w2, -1);
|
||||
widget_add_child(g, col, w, -1);
|
||||
container_set_child_growable(g, col, w, 1);
|
||||
/* GNB_PHY_DL_TICK (and not UL) because GNB_MAC_UL is from DCI */
|
||||
l = new_ticked_ttilog(h, database, "GNB_PHY_DL_TICK", "frame", "slot",
|
||||
"GNB_MAC_UL", "tbs", 0, -1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 20);
|
||||
view_tti_enable_automax(v, w2);
|
||||
logger_add_view(l, v);
|
||||
logger_set_filter(l,
|
||||
filter_eq(
|
||||
filter_evarg(database, "GNB_MAC_UL", "rnti"),
|
||||
filter_int(rnti)));
|
||||
|
||||
/* UL lcid throughput */
|
||||
col = new_container(g, VERTICAL);
|
||||
widget_add_child(g, line, col, -1);
|
||||
sprintf(s, "UL lcid %d", lcid);
|
||||
w = new_xy_plot(g, 70, 10, s, 35);
|
||||
w2 = new_textarea(g, 70, 11, 64);
|
||||
xy_plot_set_range(g, w, 0, 1000, 0, 100000);
|
||||
xy_plot_set_tick_type(g, w, XY_PLOT_SCROLL_TICK);
|
||||
widget_add_child(g, col, w2, -1);
|
||||
widget_add_child(g, col, w, -1);
|
||||
container_set_child_growable(g, col, w, 1);
|
||||
l = new_throughputlog(h, database, "GNB_PHY_UL_TICK", "frame", "slot",
|
||||
"GNB_MAC_LCID_UL", "data_size", 20);
|
||||
v = new_view_scrolltti(10, g, w, new_color(g, "#0c0c72"), w2, 20);
|
||||
logger_add_view(l, v);
|
||||
logger_set_filter(l,
|
||||
filter_and(
|
||||
filter_eq(
|
||||
filter_evarg(database, "GNB_MAC_LCID_UL", "rnti"),
|
||||
filter_int(rnti)),
|
||||
filter_eq(
|
||||
filter_evarg(database, "GNB_MAC_LCID_UL", "lcid"),
|
||||
filter_int(lcid))));
|
||||
|
||||
/* lcid RLC tx buffer occupancy */
|
||||
col = new_container(g, VERTICAL);
|
||||
widget_add_child(g, line, col, -1);
|
||||
sprintf(s, "rlc tx %d", lcid);
|
||||
w = new_xy_plot(g, 70, 10, s, 35);
|
||||
w2 = new_textarea(g, 70, 11, 64);
|
||||
xy_plot_set_range(g, w, 0, 1024*20, 0, 1000);
|
||||
xy_plot_set_tick_type(g, w, XY_PLOT_SCROLL_TICK);
|
||||
widget_add_child(g, col, w2, -1);
|
||||
widget_add_child(g, col, w, -1);
|
||||
container_set_child_growable(g, col, w, 1);
|
||||
l = new_ticked_ttilog(h, database, "GNB_PHY_DL_TICK", "frame", "slot",
|
||||
"GNB_MAC_LCID_DL", "tx_list_occupancy", 0, -1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 20);
|
||||
view_tti_enable_automax(v, w2);
|
||||
logger_add_view(l, v);
|
||||
logger_set_filter(l,
|
||||
filter_and(
|
||||
filter_eq(
|
||||
filter_evarg(database, "GNB_MAC_LCID_DL", "rnti"),
|
||||
filter_int(rnti)),
|
||||
filter_eq(
|
||||
filter_evarg(database, "GNB_MAC_LCID_DL", "lcid"),
|
||||
filter_int(lcid))));
|
||||
}
|
||||
|
||||
void build_gui(gnb_gui *gg, gui *g)
|
||||
{
|
||||
widget *main_window;
|
||||
|
||||
main_window = new_toplevel_window(g, 900, 1000, "gNB MAC tracer");
|
||||
gg->container = new_container(g, VERTICAL);
|
||||
widget_add_child(g, main_window, gg->container, -1);
|
||||
}
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
printf(
|
||||
"options:\n"
|
||||
" -d <database file> this option is mandatory\n"
|
||||
" -ip <host> connect to given IP address (default %s)\n"
|
||||
" -p <port> connect to given port (default %d)\n",
|
||||
DEFAULT_REMOTE_IP,
|
||||
DEFAULT_REMOTE_PORT
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void check_new_ue(void *_gd, event e)
|
||||
{
|
||||
gnb_data *gd = _gd;
|
||||
int rnti = e.e[gd->rnti_arg].i;
|
||||
if (!gd->ues[rnti].used)
|
||||
add_ue(gd, rnti, 4);
|
||||
}
|
||||
|
||||
int main(int n, char **v)
|
||||
{
|
||||
gui *g;
|
||||
gnb_gui gg;
|
||||
gnb_data *gd;
|
||||
char *database_filename = NULL;
|
||||
void *database;
|
||||
char *ip = DEFAULT_REMOTE_IP;
|
||||
int port = DEFAULT_REMOTE_PORT;
|
||||
event_handler *h;
|
||||
int *is_on;
|
||||
int number_of_events;
|
||||
int i;
|
||||
|
||||
for (i = 1; i < n; i++) {
|
||||
if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) usage();
|
||||
if (!strcmp(v[i], "-d")) { if (i > n-2) usage(); database_filename = v[++i]; continue; }
|
||||
if (!strcmp(v[i], "-ip")) { if (i > n-2) usage(); ip = v[++i]; continue; }
|
||||
if (!strcmp(v[i], "-p")) { if (i > n-2) usage(); port = atoi(v[++i]); continue; }
|
||||
usage();
|
||||
}
|
||||
|
||||
if (database_filename == NULL) {
|
||||
printf("ERROR: provide a database file (-d)\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
database = parse_database(database_filename);
|
||||
|
||||
load_config_file(database_filename);
|
||||
|
||||
number_of_events = number_of_ids(database);
|
||||
is_on = calloc(number_of_events, sizeof(int));
|
||||
if (is_on == NULL) abort();
|
||||
|
||||
on_off(database, "GNB_PHY_DL_TICK", is_on, 1);
|
||||
on_off(database, "GNB_MAC_DL", is_on, 1);
|
||||
on_off(database, "GNB_MAC_LCID_DL", is_on, 1);
|
||||
on_off(database, "GNB_PHY_UL_TICK", is_on, 1);
|
||||
on_off(database, "GNB_MAC_UL", is_on, 1);
|
||||
on_off(database, "GNB_MAC_LCID_UL", is_on, 1);
|
||||
|
||||
gd = calloc(1, sizeof(*gd)); if (!gd) abort();
|
||||
|
||||
h = new_handler(database);
|
||||
|
||||
g = gui_init();
|
||||
new_thread(gui_thread, g);
|
||||
|
||||
build_gui(&gg, g);
|
||||
|
||||
gd->g = g;
|
||||
gd->gg = ≫
|
||||
gd->h = h;
|
||||
gd->database = database;
|
||||
|
||||
/* get rnti_arg from event GNB_MAC_DL */
|
||||
int event_id = event_id_from_name(database, "GNB_MAC_DL");
|
||||
database_event_format f = get_format(database, event_id);
|
||||
gd->rnti_arg = -1;
|
||||
for (i = 0; i < f.count; i++) {
|
||||
if (!strcmp(f.name[i], "rnti")) gd->rnti_arg = i;
|
||||
}
|
||||
if (gd->rnti_arg == -1) {
|
||||
printf("fatal: event 'GNB_MAC_DL' does not have argument 'rnti'\n");
|
||||
exit(1);
|
||||
}
|
||||
if (strcmp(f.type[gd->rnti_arg], "int") != 0) {
|
||||
printf("fatal: argument 'rnti' of event 'GNB_MAC_DL' is not 'int'\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
register_handler_function(h, event_id, check_new_ue, gd);
|
||||
|
||||
OBUF ebuf = {.osize = 0, .omaxsize = 0, .obuf = NULL};
|
||||
|
||||
gd->socket = -1;
|
||||
|
||||
restart:
|
||||
clear_remote_config();
|
||||
if (gd->socket != -1) close(gd->socket);
|
||||
gd->socket = connect_to(ip, port);
|
||||
|
||||
/* send the first message - activate selected traces */
|
||||
int t = 1;
|
||||
if (socket_send(gd->socket, &t, 1) == -1 ||
|
||||
socket_send(gd->socket, &number_of_events, sizeof(int)) == -1 ||
|
||||
socket_send(gd->socket, is_on, number_of_events * sizeof(int)) == -1)
|
||||
goto restart;
|
||||
|
||||
while (1) {
|
||||
event e;
|
||||
e = get_event(gd->socket, &ebuf, database);
|
||||
if (e.type == -1) goto restart;
|
||||
handle_event(h, e);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user