enb.c 13 KB
Newer Older
1
2
3
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
4
#include <pthread.h>
5
6
7
8
9
10
11
12
13
#include "database.h"
#include "event.h"
#include "handler.h"
#include "logger/logger.h"
#include "view/view.h"
#include "gui/gui.h"
#include "utils.h"
#include "../T_defs.h"
#include "event_selector.h"
Cedric Roux's avatar
Cedric Roux committed
14
#include "openair_logo.h"
15
#include "config.h"
16

Cedric Roux's avatar
Cedric Roux committed
17
18
typedef struct {
  view *rrcview;
Cedric Roux's avatar
Cedric Roux committed
19
  view *legacy;
Cedric Roux's avatar
Cedric Roux committed
20
21
} enb_gui;

22
23
24
25
26
27
28
typedef struct {
  int socket;
  int *is_on;
  int nevents;
  pthread_mutex_t lock;
} enb_data;

29
#define DEFAULT_REMOTE_IP "127.0.0.1"
30
31
#define DEFAULT_REMOTE_PORT 2021

32
33
34
35
36
37
38
39
40
41
void is_on_changed(void *_d)
{
  enb_data *d = _d;
  char t;

  if (pthread_mutex_lock(&d->lock)) abort();

  if (d->socket == -1) goto no_connection;

  t = 1;
42
43
44
45
  if (socket_send(d->socket, &t, 1) == -1 ||
      socket_send(d->socket, &d->nevents, sizeof(int)) == -1 ||
      socket_send(d->socket, d->is_on, d->nevents * sizeof(int)) == -1)
    abort();
46
47
48
49
50

no_connection:
  if (pthread_mutex_unlock(&d->lock)) abort();
}

51
52
53
54
55
56
57
58
59
60
61
62
void usage(void)
{
  printf(
"options:\n"
"    -d <database file>        this option is mandatory\n"
"    -on <GROUP or ID>         turn log ON for given GROUP or ID\n"
"    -off <GROUP or ID>        turn log OFF for given GROUP or ID\n"
"    -ON                       turn all logs ON\n"
"    -OFF                      turn all logs OFF\n"
"                              note: you may pass several -on/-off/-ON/-OFF,\n"
"                                    they will be processed in order\n"
"                                    by default, all is off\n"
63
64
"    -ip <host>                connect to given IP address (default %s)\n"
"    -p <port>                 connect to given port (default %d)\n"
65
"    -debug-gui                activate GUI debug logs\n",
66
  DEFAULT_REMOTE_IP,
67
68
69
70
71
72
73
74
75
76
77
78
  DEFAULT_REMOTE_PORT
  );
  exit(1);
}

static void *gui_thread(void *_g)
{
  gui *g = _g;
  gui_loop(g);
  return NULL;
}

Cedric Roux's avatar
Cedric Roux committed
79
static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database)
80
81
82
{
  widget *main_window;
  widget *top_container;
Cedric Roux's avatar
Cedric Roux committed
83
  widget *line, *col;
Cedric Roux's avatar
Cedric Roux committed
84
  widget *logo;
85
86
87
  widget *input_signal_plot;
  logger *input_signal_log;
  view *input_signal_view;
Cedric Roux's avatar
Cedric Roux committed
88
  widget *timeline_plot;
89
90
91
  logger *timelog;
  view *timeview;
  view *subview;
Cedric Roux's avatar
Cedric Roux committed
92
93
  widget *text;
  view *textview;
Cedric Roux's avatar
Cedric Roux committed
94
  int i;
95
96
97
98
99
100
101

  main_window = new_toplevel_window(g, 800, 600, "eNB tracer");
  top_container = new_container(g, VERTICAL);
  widget_add_child(g, main_window, top_container, -1);

  line = new_container(g, HORIZONTAL);
  widget_add_child(g, top_container, line, -1);
Cedric Roux's avatar
Cedric Roux committed
102
103
  logo = new_image(g, openair_logo_png, openair_logo_png_len);
  widget_add_child(g, line, logo, -1);
104
105
106
107
108
109
110
111
112
113
114
115
  input_signal_plot = new_xy_plot(g, 256, 55, "input signal", 20);
  widget_add_child(g, line, input_signal_plot, -1);
  xy_plot_set_range(g, input_signal_plot, 0, 7680*10, 20, 70);
  input_signal_log = new_framelog(h, database,
      "ENB_INPUT_SIGNAL", "subframe", "rxdata");
  /* a skip value of 10 means to process 1 frame over 10, that is
   * more or less 10 frames per second
   */
  framelog_set_skip(input_signal_log, 10);
  input_signal_view = new_view_xy(7680*10, 10,
      g, input_signal_plot, new_color(g, "#0c0c72"));
  logger_add_view(input_signal_log, input_signal_view);
Cedric Roux's avatar
Cedric Roux committed
116

117
  /* downlink UE DCIs */
Cedric Roux's avatar
Cedric Roux committed
118
119
  widget_add_child(g, top_container,
      new_label(g,"DL/UL TICK/DCI/ACK/NACK "), -1);
Cedric Roux's avatar
Cedric Roux committed
120
121
  line = new_container(g, HORIZONTAL);
  widget_add_child(g, top_container, line, -1);
Cedric Roux's avatar
Cedric Roux committed
122
  timeline_plot = new_timeline(g, 512, 8, 5);
Cedric Roux's avatar
Cedric Roux committed
123
124
  widget_add_child(g, line, timeline_plot, -1);
  container_set_child_growable(g, line, timeline_plot, 1);
Cedric Roux's avatar
Cedric Roux committed
125
  for (i = 0; i < 8; i++)
Cedric Roux's avatar
Cedric Roux committed
126
    timeline_set_subline_background_color(g, timeline_plot, i,
Cedric Roux's avatar
Cedric Roux committed
127
        new_color(g, i==0 || i==4 ? "#aaf" : "#eee"));
128
  timeview = new_view_time(3600, 10, g, timeline_plot);
Cedric Roux's avatar
Cedric Roux committed
129
130
  /* tick logging */
  timelog = new_timelog(h, database, "ENB_DL_TICK");
Cedric Roux's avatar
Cedric Roux committed
131
  subview = new_subview_time(timeview, 0, new_color(g, "#77c"), 3600*1000);
132
  logger_add_view(timelog, subview);
Cedric Roux's avatar
Cedric Roux committed
133
134
  /* DCI logging */
  timelog = new_timelog(h, database, "ENB_DLSCH_UE_DCI");
135
  subview = new_subview_time(timeview, 1, new_color(g, "#228"), 3600*1000);
Cedric Roux's avatar
Cedric Roux committed
136
  logger_add_view(timelog, subview);
137
138
  /* ACK */
  timelog = new_timelog(h, database, "ENB_DLSCH_UE_ACK");
139
  subview = new_subview_time(timeview, 2, new_color(g, "#282"), 3600*1000);
140
141
142
  logger_add_view(timelog, subview);
  /* NACK */
  timelog = new_timelog(h, database, "ENB_DLSCH_UE_NACK");
143
  subview = new_subview_time(timeview, 3, new_color(g, "#f22"), 3600*1000);
144
  logger_add_view(timelog, subview);
145
146
147

  /* uplink UE DCIs */
  timelog = new_timelog(h, database, "ENB_UL_TICK");
Cedric Roux's avatar
Cedric Roux committed
148
  subview = new_subview_time(timeview, 4, new_color(g, "#77c"), 3600*1000);
149
  logger_add_view(timelog, subview);
Cedric Roux's avatar
Cedric Roux committed
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205

  /* phy/mac/rlc/pdcp/rrc textlog */
  line = new_container(g, HORIZONTAL);
  widget_add_child(g, top_container, line, -1);
  container_set_child_growable(g, top_container, line, 1);

  /* phy */
  col = new_container(g, VERTICAL);
  widget_add_child(g, line, col, -1);
  container_set_child_growable(g, line, col, 1);
  widget_add_child(g, col, new_label(g, "PHY"), -1);
  text = new_textlist(g, 100, 10, new_color(g, "#afa"));
  widget_add_child(g, col, text, -1);
  container_set_child_growable(g, col, text, 1);
  textview = new_view_textlist(10000, 10, g, text);

  /* mac */
  col = new_container(g, VERTICAL);
  widget_add_child(g, line, col, -1);
  container_set_child_growable(g, line, col, 1);
  widget_add_child(g, col, new_label(g, "MAC"), -1);
  text = new_textlist(g, 100, 10, new_color(g, "#adf"));
  widget_add_child(g, col, text, -1);
  container_set_child_growable(g, col, text, 1);
  textview = new_view_textlist(10000, 10, g, text);

  /* rlc */
  col = new_container(g, VERTICAL);
  widget_add_child(g, line, col, -1);
  container_set_child_growable(g, line, col, 1);
  widget_add_child(g, col, new_label(g, "RLC"), -1);
  text = new_textlist(g, 100, 10, new_color(g, "#aff"));
  widget_add_child(g, col, text, -1);
  container_set_child_growable(g, col, text, 1);
  textview = new_view_textlist(10000, 10, g, text);

  /* pdcp */
  col = new_container(g, VERTICAL);
  widget_add_child(g, line, col, -1);
  container_set_child_growable(g, line, col, 1);
  widget_add_child(g, col, new_label(g, "PDCP"), -1);
  text = new_textlist(g, 100, 10, new_color(g, "#ed9"));
  widget_add_child(g, col, text, -1);
  container_set_child_growable(g, col, text, 1);
  textview = new_view_textlist(10000, 10, g, text);

  /* rrc */
  col = new_container(g, VERTICAL);
  widget_add_child(g, line, col, -1);
  container_set_child_growable(g, line, col, 1);
  widget_add_child(g, col, new_label(g, "RRC"), -1);
  text = new_textlist(g, 100, 10, new_color(g, "#fdb"));
  widget_add_child(g, col, text, -1);
  container_set_child_growable(g, col, text, 1);
  textview = new_view_textlist(10000, 10, g, text);
  e->rrcview = textview;
Cedric Roux's avatar
Cedric Roux committed
206
207
208
209
210
211
212

  /* legacy logs (LOG_I, LOG_D, ...) */
  widget_add_child(g, top_container, new_label(g, "LEGACY"), -1);
  text = new_textlist(g, 100, 10, new_color(g, "#eeb"));
  widget_add_child(g, top_container, text, -1);
  container_set_child_growable(g, top_container, text, 1);
  e->legacy = new_view_textlist(10000, 10, g, text);
Cedric Roux's avatar
Cedric Roux committed
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
}

void view_add_log(view *v, char *log, event_handler *h, void *database,
    int *is_on)
{
  logger *textlog;
  char *name, *desc;

  database_get_generic_description(database,
      event_id_from_name(database, log), &name, &desc);
  textlog = new_textlog(h, database, name, desc);
  logger_add_view(textlog, v);
  free(name);
  free(desc);

  on_off(database, log, is_on, 1);
229
230
231
232
233
234
235
}

int main(int n, char **v)
{
  extern int volatile gui_logd;
  char *database_filename = NULL;
  void *database;
236
  char *ip = DEFAULT_REMOTE_IP;
237
238
239
240
241
242
243
244
245
  int port = DEFAULT_REMOTE_PORT;
  char **on_off_name;
  int *on_off_action;
  int on_off_n = 0;
  int *is_on;
  int number_of_events;
  int i;
  event_handler *h;
  gui *g;
Cedric Roux's avatar
Cedric Roux committed
246
  enb_gui eg;
247
  enb_data enb_data;
248
249
250
251
252
253
254
255

  on_off_name = malloc(n * sizeof(char *)); if (on_off_name == NULL) abort();
  on_off_action = malloc(n * sizeof(int)); if (on_off_action == NULL) abort();

  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; }
256
    if (!strcmp(v[i], "-ip")) { if (i > n-2) usage(); ip = v[++i]; continue; }
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
    if (!strcmp(v[i], "-p"))
      { if (i > n-2) usage(); port = atoi(v[++i]); continue; }
    if (!strcmp(v[i], "-on")) { if (i > n-2) usage();
      on_off_name[on_off_n]=v[++i]; on_off_action[on_off_n++]=1; continue; }
    if (!strcmp(v[i], "-off")) { if (i > n-2) usage();
      on_off_name[on_off_n]=v[++i]; on_off_action[on_off_n++]=0; continue; }
    if (!strcmp(v[i], "-ON"))
      { on_off_name[on_off_n]=NULL; on_off_action[on_off_n++]=1; continue; }
    if (!strcmp(v[i], "-OFF"))
      { on_off_name[on_off_n]=NULL; on_off_action[on_off_n++]=0; continue; }
    if (!strcmp(v[i], "-debug-gui")) { gui_logd = 1; continue; }
    usage();
  }

  if (database_filename == NULL) {
    printf("ERROR: provide a database file (-d)\n");
    exit(1);
  }

  database = parse_database(database_filename);

278
279
  store_config_file(database_filename);

280
281
282
283
284
285
286
287
288
  number_of_events = number_of_ids(database);
  is_on = calloc(number_of_events, sizeof(int));
  if (is_on == NULL) abort();

  h = new_handler(database);

  g = gui_init();
  new_thread(gui_thread, g);

Cedric Roux's avatar
Cedric Roux committed
289
  enb_main_gui(&eg, g, h, database);
290

Cedric Roux's avatar
Cedric Roux committed
291
292
293
294
295
296
297
298
299
300
301
  for (i = 0; i < number_of_events; i++) {
    logger *textlog;
    char *name, *desc;
    database_get_generic_description(database, i, &name, &desc);
    if (strncmp(name, "LEGACY_", 7) != 0) continue;
    textlog = new_textlog(h, database, name, desc);
    logger_add_view(textlog, eg.legacy);
    free(name);
    free(desc);
  }

302
303
304
  on_off(database, "ENB_INPUT_SIGNAL", is_on, 1);
  on_off(database, "ENB_UL_TICK", is_on, 1);
  on_off(database, "ENB_DL_TICK", is_on, 1);
Cedric Roux's avatar
Cedric Roux committed
305
  on_off(database, "ENB_DLSCH_UE_DCI", is_on, 1);
306
307
  on_off(database, "ENB_DLSCH_UE_ACK", is_on, 1);
  on_off(database, "ENB_DLSCH_UE_NACK", is_on, 1);
308

309
310
311
312
  on_off(database, "LEGACY_RRC_INFO", is_on, 1);
  on_off(database, "LEGACY_RRC_ERROR", is_on, 1);
  on_off(database, "LEGACY_RRC_WARNING", is_on, 1);

Cedric Roux's avatar
Cedric Roux committed
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
  view_add_log(eg.rrcview, "ENB_RRC_CONNECTION_SETUP_COMPLETE",
      h, database, is_on);
  view_add_log(eg.rrcview, "ENB_RRC_SECURITY_MODE_COMMAND",
      h, database, is_on);
  view_add_log(eg.rrcview, "ENB_RRC_UE_CAPABILITY_ENQUIRY",
      h, database, is_on);
  view_add_log(eg.rrcview, "ENB_RRC_CONNECTION_REJECT",
      h, database, is_on);
  view_add_log(eg.rrcview, "ENB_RRC_CONNECTION_REESTABLISHMENT_REJECT",
      h, database, is_on);
  view_add_log(eg.rrcview, "ENB_RRC_CONNECTION_RELEASE",
      h, database, is_on);
  view_add_log(eg.rrcview, "ENB_RRC_CONNECTION_RECONFIGURATION",
      h, database, is_on);
  view_add_log(eg.rrcview, "ENB_RRC_MEASUREMENT_REPORT",
      h, database, is_on);
  view_add_log(eg.rrcview, "ENB_RRC_HANDOVER_PREPARATION_INFORMATION",
      h, database, is_on);
  view_add_log(eg.rrcview, "ENB_RRC_CONNECTION_RECONFIGURATION_COMPLETE",
      h, database, is_on);
  view_add_log(eg.rrcview, "ENB_RRC_CONNECTION_SETUP",
      h, database, is_on);
  view_add_log(eg.rrcview, "ENB_RRC_UL_CCCH_DATA_IN",
      h, database, is_on);
  view_add_log(eg.rrcview, "ENB_RRC_UL_DCCH_DATA_IN",
      h, database, is_on);
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
  view_add_log(eg.rrcview, "ENB_RRC_SECURITY_MODE_COMPLETE",
      h, database, is_on);
  view_add_log(eg.rrcview, "ENB_RRC_SECURITY_MODE_FAILURE",
      h, database, is_on);
  view_add_log(eg.rrcview, "ENB_RRC_UE_CAPABILITY_INFORMATION",
      h, database, is_on);
  view_add_log(eg.rrcview, "ENB_RRC_CONNECTION_REQUEST",
      h, database, is_on);
  view_add_log(eg.rrcview, "ENB_RRC_CONNECTION_REESTABLISHMENT_REQUEST",
      h, database, is_on);
  view_add_log(eg.rrcview, "ENB_RRC_CONNECTION_REESTABLISHMENT_COMPLETE",
      h, database, is_on);
  view_add_log(eg.rrcview, "ENB_RRC_UL_HANDOVER_PREPARATION_TRANSFER",
      h, database, is_on);
  view_add_log(eg.rrcview, "ENB_RRC_UL_INFORMATION_TRANSFER",
      h, database, is_on);
  view_add_log(eg.rrcview, "ENB_RRC_COUNTER_CHECK_RESPONSE",
      h, database, is_on);
  view_add_log(eg.rrcview, "ENB_RRC_UE_INFORMATION_RESPONSE_R9",
      h, database, is_on);
  view_add_log(eg.rrcview, "ENB_RRC_PROXIMITY_INDICATION_R9",
      h, database, is_on);
  view_add_log(eg.rrcview, "ENB_RRC_RECONFIGURATION_COMPLETE_R10",
      h, database, is_on);
  view_add_log(eg.rrcview, "ENB_RRC_MBMS_COUNTING_RESPONSE_R10",
      h, database, is_on);
  view_add_log(eg.rrcview, "ENB_RRC_INTER_FREQ_RSTD_MEASUREMENT_INDICATION",
      h, database, is_on);
  view_add_log(eg.rrcview, "ENB_RRC_UNKNOW_MESSAGE",
      h, database, is_on);
Cedric Roux's avatar
Cedric Roux committed
369

370
371
372
  for (i = 0; i < on_off_n; i++)
    on_off(database, on_off_name[i], is_on, on_off_action[i]);

373
374
375
376
377
  enb_data.socket = -1;
  enb_data.is_on = is_on;
  enb_data.nevents = number_of_events;
  if (pthread_mutex_init(&enb_data.lock, NULL)) abort();
  setup_event_selector(g, database, is_on, is_on_changed, &enb_data);
378

379
  enb_data.socket = connect_to(ip, port);
380

381
382
  /* send the first message - activate selected traces */
  is_on_changed(&enb_data);
383
384
385
386
387

  /* read messages */
  while (1) {
    char v[T_BUFFER_MAX];
    event e;
388
    e = get_event(enb_data.socket, v, database);
389
    if (e.type == -1) abort();
390
391
392
393
394
    handle_event(h, e);
  }

  return 0;
}