2 * Copyright 2009 Martin Mathieson
3 * (originally based upon wlan_stat_dlg.c)
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
32 #include "ui/gtk/gtkglobals.h"
34 #include <epan/packet.h>
35 #include <epan/packet_info.h>
37 #include <epan/dissectors/packet-mac-lte.h>
39 #include "ui/simple_dialog.h"
40 #include "../stat_menu.h"
42 #include "ui/gtk/dlg_utils.h"
43 #include "ui/gtk/gui_stat_menu.h"
44 #include "ui/gtk/tap_param_dlg.h"
45 #include "ui/gtk/gui_utils.h"
46 #include "ui/gtk/help_dlg.h"
47 #include "ui/gtk/main.h"
49 #include "ui/gtk/old-gtk-compat.h"
51 /**********************************************/
52 /* Table column identifiers and title strings */
61 UL_PADDING_PERCENT_COLUMN
,
62 UL_RETX_FRAMES_COLUMN
,
66 DL_PADDING_PERCENT_COLUMN
,
68 DL_CRC_HIGH_CODE_RATE_COLUMN
,
69 DL_CRC_PDSCH_LOST_COLUMN
,
70 DL_CRC_DUPLICATE_NONZERO_RV
,
71 DL_RETX_FRAMES_COLUMN
,
92 static const gchar
*ue_titles
[] = { "RNTI", "Type", "UEId",
93 "UL Frames", "UL Bytes", "UL MBit/sec", "UL Padding %", "UL ReTX",
94 "DL Frames", "DL Bytes", "DL MBit/sec", "DL Padding %", "DL CRC Failed",
95 "DL CRC High Code Rate", "DL CRC PDSCH Lost", "DL CRC Dup NonZero RV", "DL ReTX"};
97 static const gchar
*channel_titles
[] = { "CCCH",
98 "LCID 1", "LCID 2", "LCID 3", "LCID 4", "LCID 5",
99 "LCID 6", "LCID 7", "LCID 8", "LCID 9", "LCID 10",
103 /* Stats for one UE */
104 typedef struct mac_lte_row_data
{
105 /* Key for matching this row */
110 gboolean is_predefined_data
;
113 guint32 UL_raw_bytes
; /* all bytes */
114 guint32 UL_total_bytes
; /* payload */
115 nstime_t UL_time_start
;
116 nstime_t UL_time_stop
;
117 guint32 UL_padding_bytes
;
118 guint32 UL_CRC_errors
;
119 guint32 UL_retx_frames
;
122 guint32 DL_raw_bytes
; /* all bytes */
123 guint32 DL_total_bytes
;
124 nstime_t DL_time_start
;
125 nstime_t DL_time_stop
;
126 guint32 DL_padding_bytes
;
127 guint32 DL_CRC_failures
;
128 guint32 DL_CRC_high_code_rate
;
129 guint32 DL_CRC_PDSCH_lost
;
130 guint32 DL_CRC_Duplicate_Nonzero_rv
;
131 guint32 DL_retx_frames
;
133 guint32 UL_bytes_for_lcid
[11];
134 guint32 UL_sdus_for_lcid
[11];
135 guint32 DL_bytes_for_lcid
[11];
136 guint32 DL_sdus_for_lcid
[11];
140 /* One row/UE in the UE table */
141 typedef struct mac_lte_ep
{
142 struct mac_lte_ep
*next
;
143 struct mac_lte_row_data stats
;
149 /* Common channel stats */
150 typedef struct mac_lte_common_stats
{
157 guint32 pch_paging_ids
;
161 guint16 max_ul_ues_in_tti
;
162 guint16 max_dl_ues_in_tti
;
163 } mac_lte_common_stats
;
166 static const char *selected_ue_row_names
[] = {"UL SDUs", "UL Bytes", "DL SDUs", "DL Bytes"};
169 /* Used to keep track of whole MAC LTE statistics window */
170 typedef struct mac_lte_stat_t
{
171 /* Stats window itself */
172 GtkWidget
*mac_lte_stat_dlg_w
;
177 GtkWidget
*mac_lte_stat_ues_lb
;
178 GtkWidget
*ul_filter_bt
;
179 GtkWidget
*dl_filter_bt
;
180 GtkWidget
*uldl_filter_bt
;
182 GtkWidget
*show_mac_rach_cb
;
183 GtkWidget
*show_mac_srs_cb
;
184 GtkWidget
*show_dct_errors_cb
;
185 GtkWidget
*dct_error_substring_lb
;
186 GtkWidget
*dct_error_substring_te
;
188 GtkWidget
*ul_max_ues_per_tti
;
189 GtkWidget
*dl_max_ues_per_tti
;
192 mac_lte_common_stats common_stats
;
193 GtkWidget
*common_mib_frames
;
194 GtkWidget
*common_sib_frames
;
195 GtkWidget
*common_sib_bytes
;
196 GtkWidget
*common_pch_frames
;
197 GtkWidget
*common_pch_bytes
;
198 GtkWidget
*common_pch_paging_ids
;
199 GtkWidget
*common_rar_frames
;
200 GtkWidget
*common_rar_entries
;
202 /* Keep track of unique rntis & ueids */
203 guint8 used_ueids
[65535];
204 guint8 used_rntis
[65535];
205 guint16 number_of_ueids
;
206 guint16 number_of_rntis
;
208 guint16 selected_rnti
;
209 guint16 selected_ueid
;
211 /* Labels in selected UE 'table' */
212 GtkWidget
*selected_ue_column_entry
[NUM_CHANNEL_COLUMNS
][5];
214 GtkTreeView
*ue_table
;
215 mac_lte_ep_t
*ep_list
;
219 /* Reset the statistics window */
220 static void mac_lte_stat_reset(void *phs
)
222 mac_lte_stat_t
*mac_lte_stat
= (mac_lte_stat_t
*)phs
;
223 mac_lte_ep_t
*list
= mac_lte_stat
->ep_list
;
230 if (mac_lte_stat
->mac_lte_stat_dlg_w
!= NULL
) {
231 display_name
= cf_get_display_name(&cfile
);
232 g_snprintf(title
, sizeof(title
), "Wireshark: LTE MAC Traffic Statistics: %s (filter=\"%s\")",
234 strlen(mac_lte_stat
->filter
) ? mac_lte_stat
->filter
: "none");
235 g_free(display_name
);
236 gtk_window_set_title(GTK_WINDOW(mac_lte_stat
->mac_lte_stat_dlg_w
), title
);
239 g_snprintf(title
, sizeof(title
), "UL/DL-SCH data (0 entries)");
240 gtk_frame_set_label(GTK_FRAME(mac_lte_stat
->mac_lte_stat_ues_lb
), title
);
242 /* Reset counts of unique ueids & rntis */
243 memset(mac_lte_stat
->used_ueids
, 0, 65535);
244 mac_lte_stat
->number_of_ueids
= 0;
245 memset(mac_lte_stat
->used_rntis
, 0, 65535);
246 mac_lte_stat
->number_of_rntis
= 0;
248 /* Zero common stats */
249 memset(&(mac_lte_stat
->common_stats
), 0, sizeof(mac_lte_common_stats
));
251 /* Remove all entries from the UE list */
252 store
= GTK_LIST_STORE(gtk_tree_view_get_model(mac_lte_stat
->ue_table
));
253 gtk_list_store_clear(store
);
259 mac_lte_stat
->ep_list
= NULL
;
261 /* Set all of the channel counters to 0 */
262 for (n
=1; n
<=4; n
++) {
263 for (i
=CCCH_COLUMN
; i
< NUM_CHANNEL_COLUMNS
; i
++) {
264 gtk_label_set_text(GTK_LABEL(mac_lte_stat
->selected_ue_column_entry
[i
][n
]), "0");
270 /* Allocate a mac_lte_ep_t struct to store info for new UE */
271 static mac_lte_ep_t
* alloc_mac_lte_ep(const struct mac_lte_tap_info
*si
, packet_info
*pinfo _U_
)
280 if (!(ep
= (mac_lte_ep_t
*)g_malloc(sizeof(mac_lte_ep_t
)))) {
284 /* Copy SI data into ep->stats */
285 ep
->stats
.rnti
= si
->rnti
;
286 ep
->stats
.rnti_type
= si
->rntiType
;
287 ep
->stats
.ueid
= si
->ueid
;
289 /* Counts for new UE are all 0 */
290 ep
->stats
.UL_frames
= 0;
291 ep
->stats
.DL_frames
= 0;
292 ep
->stats
.UL_total_bytes
= 0;
293 ep
->stats
.UL_raw_bytes
= 0;
294 ep
->stats
.DL_raw_bytes
= 0;
295 ep
->stats
.UL_padding_bytes
= 0;
296 ep
->stats
.DL_padding_bytes
= 0;
297 ep
->stats
.DL_total_bytes
= 0;
298 ep
->stats
.UL_CRC_errors
= 0;
299 ep
->stats
.DL_CRC_failures
= 0;
300 ep
->stats
.DL_CRC_high_code_rate
= 0;
301 ep
->stats
.DL_CRC_PDSCH_lost
= 0;
302 ep
->stats
.DL_CRC_Duplicate_Nonzero_rv
= 0;
303 ep
->stats
.UL_retx_frames
= 0;
304 ep
->stats
.DL_retx_frames
= 0;
306 for (n
=0; n
< 11; n
++) {
307 ep
->stats
.UL_sdus_for_lcid
[n
] = 0;
308 ep
->stats
.UL_bytes_for_lcid
[n
] = 0;
310 ep
->stats
.DL_total_bytes
= 0;
311 for (n
=0; n
< 11; n
++) {
312 ep
->stats
.DL_sdus_for_lcid
[n
] = 0;
313 ep
->stats
.DL_bytes_for_lcid
[n
] = 0;
318 ep
->iter_valid
= FALSE
;
324 /* Update counts of unique rntis & ueids */
325 static void update_ueid_rnti_counts(guint16 rnti
, guint16 ueid
, mac_lte_stat_t
*hs
)
327 if (!hs
->used_ueids
[ueid
]) {
328 hs
->used_ueids
[ueid
] = TRUE
;
329 hs
->number_of_ueids
++;
331 if (!hs
->used_rntis
[rnti
]) {
332 hs
->used_rntis
[rnti
] = TRUE
;
333 hs
->number_of_rntis
++;
338 /* Process stat struct for a MAC LTE frame */
339 static int mac_lte_stat_packet(void *phs
, packet_info
*pinfo
, epan_dissect_t
*edt _U_
,
344 /* Get reference to stat window instance */
345 mac_lte_stat_t
*hs
= (mac_lte_stat_t
*)phs
;
346 mac_lte_ep_t
*tmp
= NULL
, *te
= NULL
;
348 /* Cast tap info struct */
349 const struct mac_lte_tap_info
*si
= (const struct mac_lte_tap_info
*)phi
;
355 hs
->common_stats
.all_frames
++;
357 /* For common channels, just update global counters */
358 switch (si
->rntiType
) {
360 hs
->common_stats
.pch_frames
++;
361 hs
->common_stats
.pch_bytes
+= si
->single_number_of_bytes
;
362 hs
->common_stats
.pch_paging_ids
+= si
->number_of_paging_ids
;
365 hs
->common_stats
.sib_frames
++;
366 hs
->common_stats
.sib_bytes
+= si
->single_number_of_bytes
;
369 hs
->common_stats
.mib_frames
++;
372 hs
->common_stats
.rar_frames
++;
373 hs
->common_stats
.rar_entries
+= si
->number_of_rars
;
377 /* Drop through for per-UE update */
385 /* Check max UEs/tti counter */
386 switch (si
->direction
) {
387 case DIRECTION_UPLINK
:
388 hs
->common_stats
.max_ul_ues_in_tti
=
389 MAX(hs
->common_stats
.max_ul_ues_in_tti
, si
->ueInTTI
);
391 case DIRECTION_DOWNLINK
:
392 hs
->common_stats
.max_dl_ues_in_tti
=
393 MAX(hs
->common_stats
.max_dl_ues_in_tti
, si
->ueInTTI
);
397 /* For per-UE data, must create a new row if none already existing */
399 /* Allocate new list */
400 hs
->ep_list
= alloc_mac_lte_ep(si
, pinfo
);
401 /* Make it the first/only entry */
404 /* Update counts of unique ueids & rntis */
405 update_ueid_rnti_counts(si
->rnti
, si
->ueid
, hs
);
407 /* Look among existing rows for this RNTI */
408 for (tmp
= hs
->ep_list
;(tmp
!= NULL
); tmp
= tmp
->next
) {
409 /* Match only by RNTI and UEId together */
410 if ((tmp
->stats
.rnti
== si
->rnti
) &&
411 (tmp
->stats
.ueid
== si
->ueid
)) {
417 /* Not found among existing, so create a new one anyway */
419 if ((te
= alloc_mac_lte_ep(si
, pinfo
))) {
420 /* Add new item to end of list */
421 mac_lte_ep_t
*p
= hs
->ep_list
;
428 /* Update counts of unique ueids & rntis */
429 update_ueid_rnti_counts(si
->rnti
, si
->ueid
, hs
);
434 /* Really should have a row pointer by now */
439 /* Update entry with details from si */
440 te
->stats
.rnti
= si
->rnti
;
441 te
->stats
.is_predefined_data
= si
->isPredefinedData
;
444 if (si
->direction
== DIRECTION_UPLINK
) {
446 te
->stats
.UL_retx_frames
++;
450 if (si
->crcStatusValid
&& (si
->crcStatus
!= crc_success
)) {
451 te
->stats
.UL_CRC_errors
++;
455 /* Update time range */
456 if (te
->stats
.UL_frames
== 0) {
457 te
->stats
.UL_time_start
= si
->time
;
459 te
->stats
.UL_time_stop
= si
->time
;
461 te
->stats
.UL_frames
++;
463 te
->stats
.UL_raw_bytes
+= si
->raw_length
;
464 te
->stats
.UL_padding_bytes
+= si
->padding_bytes
;
466 if (si
->isPredefinedData
) {
467 te
->stats
.UL_total_bytes
+= si
->single_number_of_bytes
;
470 for (n
=0; n
< 11; n
++) {
471 te
->stats
.UL_sdus_for_lcid
[n
] += si
->sdus_for_lcid
[n
];
472 te
->stats
.UL_bytes_for_lcid
[n
] += si
->bytes_for_lcid
[n
];
473 te
->stats
.UL_total_bytes
+= si
->bytes_for_lcid
[n
];
481 te
->stats
.DL_retx_frames
++;
485 if (si
->crcStatusValid
&& (si
->crcStatus
!= crc_success
)) {
486 switch (si
->crcStatus
) {
488 te
->stats
.DL_CRC_failures
++;
490 case crc_high_code_rate
:
491 te
->stats
.DL_CRC_high_code_rate
++;
494 te
->stats
.DL_CRC_PDSCH_lost
++;
496 case crc_duplicate_nonzero_rv
:
497 te
->stats
.DL_CRC_Duplicate_Nonzero_rv
++;
501 /* Something went wrong! */
507 /* Update time range */
508 if (te
->stats
.DL_frames
== 0) {
509 te
->stats
.DL_time_start
= si
->time
;
511 te
->stats
.DL_time_stop
= si
->time
;
513 te
->stats
.DL_frames
++;
515 te
->stats
.DL_raw_bytes
+= si
->raw_length
;
516 te
->stats
.DL_padding_bytes
+= si
->padding_bytes
;
518 if (si
->isPredefinedData
) {
519 te
->stats
.DL_total_bytes
+= si
->single_number_of_bytes
;
522 for (n
=0; n
< 11; n
++) {
523 te
->stats
.DL_sdus_for_lcid
[n
] += si
->sdus_for_lcid
[n
];
524 te
->stats
.DL_bytes_for_lcid
[n
] += si
->bytes_for_lcid
[n
];
525 te
->stats
.DL_total_bytes
+= si
->bytes_for_lcid
[n
];
534 /* Draw the UE details table according to the current UE selection */
535 static void mac_lte_ue_details(mac_lte_ep_t
*mac_stat_ep
, mac_lte_stat_t
*hs
)
539 guint8 show_dct_errors
;
541 /**********************************/
542 /* Set data one row at a time */
545 for (n
=0; n
< PREDEFINED_COLUMN
-1; n
++) {
546 g_snprintf(buff
, sizeof(buff
), "%u",
547 (mac_stat_ep
!= NULL
) ? mac_stat_ep
->stats
.UL_sdus_for_lcid
[n
] : 0);
548 gtk_label_set_text(GTK_LABEL(hs
->selected_ue_column_entry
[n
+1][1]), buff
);
552 if (mac_stat_ep
!= NULL
) {
553 g_snprintf(buff
, sizeof(buff
), "%u",
554 mac_stat_ep
->stats
.is_predefined_data
? mac_stat_ep
->stats
.UL_frames
: 0);
557 g_snprintf(buff
, sizeof(buff
), "%u", 0);
559 gtk_label_set_text(GTK_LABEL(hs
->selected_ue_column_entry
[PREDEFINED_COLUMN
][1]), buff
);
563 for (n
=0; n
< PREDEFINED_COLUMN
-1; n
++) {
564 g_snprintf(buff
, sizeof(buff
), "%u",
565 (mac_stat_ep
!= NULL
) ? mac_stat_ep
->stats
.UL_bytes_for_lcid
[n
] : 0);
566 gtk_label_set_text(GTK_LABEL(hs
->selected_ue_column_entry
[n
+1][2]), buff
);
570 if (mac_stat_ep
!= NULL
) {
571 g_snprintf(buff
, sizeof(buff
), "%u",
572 mac_stat_ep
->stats
.is_predefined_data
? mac_stat_ep
->stats
.UL_total_bytes
: 0);
575 g_snprintf(buff
, sizeof(buff
), "%u", 0);
577 gtk_label_set_text(GTK_LABEL(hs
->selected_ue_column_entry
[PREDEFINED_COLUMN
][2]), buff
);
581 for (n
=0; n
< PREDEFINED_COLUMN
-1; n
++) {
582 g_snprintf(buff
, sizeof(buff
), "%u",
583 (mac_stat_ep
!= NULL
) ? mac_stat_ep
->stats
.DL_sdus_for_lcid
[n
] : 0);
584 gtk_label_set_text(GTK_LABEL(hs
->selected_ue_column_entry
[n
+1][3]), buff
);
587 if (mac_stat_ep
!= NULL
) {
588 g_snprintf(buff
, sizeof(buff
), "%u",
589 mac_stat_ep
->stats
.is_predefined_data
? mac_stat_ep
->stats
.DL_frames
: 0);
592 g_snprintf(buff
, sizeof(buff
), "%u", 0);
594 gtk_label_set_text(GTK_LABEL(hs
->selected_ue_column_entry
[PREDEFINED_COLUMN
][3]), buff
);
598 for (n
=0; n
< PREDEFINED_COLUMN
-1; n
++) {
599 g_snprintf(buff
, sizeof(buff
), "%u",
600 (mac_stat_ep
!= NULL
) ? mac_stat_ep
->stats
.DL_bytes_for_lcid
[n
] : 0);
601 gtk_label_set_text(GTK_LABEL(hs
->selected_ue_column_entry
[n
+1][4]), buff
);
604 if (mac_stat_ep
!= NULL
) {
605 g_snprintf(buff
, sizeof(buff
), "%u",
606 mac_stat_ep
->stats
.is_predefined_data
? mac_stat_ep
->stats
.DL_total_bytes
: 0);
609 g_snprintf(buff
, sizeof(buff
), "%u", 0);
611 gtk_label_set_text(GTK_LABEL(hs
->selected_ue_column_entry
[PREDEFINED_COLUMN
][4]), buff
);
613 /* Remember selected UE */
615 hs
->selected_rnti
= mac_stat_ep
->stats
.rnti
;
616 hs
->selected_ueid
= mac_stat_ep
->stats
.ueid
;
619 /* Enable/disable filter controls */
620 gtk_widget_set_sensitive(hs
->ul_filter_bt
, mac_stat_ep
!= NULL
);
621 gtk_widget_set_sensitive(hs
->dl_filter_bt
, mac_stat_ep
!= NULL
);
622 gtk_widget_set_sensitive(hs
->uldl_filter_bt
, mac_stat_ep
!= NULL
);
623 gtk_widget_set_sensitive(hs
->show_mac_rach_cb
, mac_stat_ep
!= NULL
);
624 gtk_widget_set_sensitive(hs
->show_mac_srs_cb
, mac_stat_ep
!= NULL
);
625 gtk_widget_set_sensitive(hs
->show_dct_errors_cb
, mac_stat_ep
!= NULL
);
627 /* Enabling substring control only if errors enabled */
628 show_dct_errors
= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(hs
->show_dct_errors_cb
));
629 gtk_widget_set_sensitive(hs
->dct_error_substring_lb
, show_dct_errors
&& (mac_stat_ep
!= NULL
));
630 gtk_widget_set_sensitive(hs
->dct_error_substring_te
, show_dct_errors
&& (mac_stat_ep
!= NULL
));
634 /* Calculate and return a bandwidth figure, in Mbs */
635 static float calculate_bw(nstime_t
*start_time
, nstime_t
*stop_time
, guint32 bytes
)
637 /* Can only calculate bandwidth if have time delta */
638 if (memcmp(start_time
, stop_time
, sizeof(nstime_t
)) != 0) {
639 float elapsed_ms
= (((float)stop_time
->secs
- (float)start_time
->secs
) * 1000) +
640 (((float)stop_time
->nsecs
- (float)start_time
->nsecs
) / 1000000);
642 /* Only really meaningful if have a few frames spread over time...
643 For now at least avoid dividing by something very close to 0.0 */
644 if (elapsed_ms
< 2.0) {
647 return ((bytes
* 8) / elapsed_ms
) / 1000;
655 /* (Re)draw the whole dialog window */
656 static void mac_lte_stat_draw(void *phs
)
659 guint16 number_of_ues
= 0;
663 /* Look up the statistics window */
664 mac_lte_stat_t
*hs
= (mac_lte_stat_t
*)phs
;
665 mac_lte_ep_t
*list
= hs
->ep_list
, *tmp
= 0;
667 GtkListStore
*ues_store
;
668 GtkTreeSelection
*sel
;
673 g_snprintf(buff
, sizeof(buff
), "Max UL UEs/TTI: %u", hs
->common_stats
.max_ul_ues_in_tti
);
674 gtk_label_set_text(GTK_LABEL(hs
->ul_max_ues_per_tti
), buff
);
675 g_snprintf(buff
, sizeof(buff
), "Max DL UEs/TTI: %u", hs
->common_stats
.max_dl_ues_in_tti
);
676 gtk_label_set_text(GTK_LABEL(hs
->dl_max_ues_per_tti
), buff
);
678 /* Common channel data */
679 g_snprintf(buff
, sizeof(buff
), "MIBs: %u", hs
->common_stats
.mib_frames
);
680 gtk_label_set_text(GTK_LABEL(hs
->common_mib_frames
), buff
);
681 g_snprintf(buff
, sizeof(buff
), "SIB Frames: %u", hs
->common_stats
.sib_frames
);
682 gtk_label_set_text(GTK_LABEL(hs
->common_sib_frames
), buff
);
683 g_snprintf(buff
, sizeof(buff
), "SIB Bytes: %u", hs
->common_stats
.sib_bytes
);
684 gtk_label_set_text(GTK_LABEL(hs
->common_sib_bytes
), buff
);
685 g_snprintf(buff
, sizeof(buff
), "PCH Frames: %u", hs
->common_stats
.pch_frames
);
686 gtk_label_set_text(GTK_LABEL(hs
->common_pch_frames
), buff
);
687 g_snprintf(buff
, sizeof(buff
), "PCH Bytes: %u", hs
->common_stats
.pch_bytes
);
688 gtk_label_set_text(GTK_LABEL(hs
->common_pch_bytes
), buff
);
689 g_snprintf(buff
, sizeof(buff
), "PCH Paging Ids: %u", hs
->common_stats
.pch_paging_ids
);
690 gtk_label_set_text(GTK_LABEL(hs
->common_pch_paging_ids
), buff
);
691 g_snprintf(buff
, sizeof(buff
), "RAR Frames: %u", hs
->common_stats
.rar_frames
);
692 gtk_label_set_text(GTK_LABEL(hs
->common_rar_frames
), buff
);
693 g_snprintf(buff
, sizeof(buff
), "RAR Entries: %u", hs
->common_stats
.rar_entries
);
694 gtk_label_set_text(GTK_LABEL(hs
->common_rar_entries
), buff
);
697 /* Per-UE table entries */
698 ues_store
= GTK_LIST_STORE(gtk_tree_view_get_model(hs
->ue_table
));
700 /* Set title that shows how many UEs currently in table */
701 for (tmp
= list
; (tmp
!=NULL
); tmp
=tmp
->next
, number_of_ues
++);
702 g_snprintf(title
, sizeof(title
), "UL/DL-SCH data (%u entries - %u unique RNTIs, %u unique UEIds)",
703 number_of_ues
, hs
->number_of_rntis
, hs
->number_of_ueids
);
704 gtk_frame_set_label(GTK_FRAME(hs
->mac_lte_stat_ues_lb
), title
);
706 /* Update title to include number of UEs and frames */
707 display_name
= cf_get_display_name(&cfile
);
708 g_snprintf(title
, sizeof(title
), "Wireshark: LTE MAC Traffic Statistics: %s (%u UEs, %u frames) (filter=\"%s\")",
711 hs
->common_stats
.all_frames
,
712 strlen(hs
->filter
) ? hs
->filter
: "none");
713 g_free(display_name
);
714 gtk_window_set_title(GTK_WINDOW(hs
->mac_lte_stat_dlg_w
), title
);
717 for (tmp
= list
; tmp
; tmp
=tmp
->next
) {
719 /* Calculate bandwidth */
720 float UL_bw
= calculate_bw(&tmp
->stats
.UL_time_start
,
721 &tmp
->stats
.UL_time_stop
,
722 tmp
->stats
.UL_total_bytes
);
723 float DL_bw
= calculate_bw(&tmp
->stats
.DL_time_start
,
724 &tmp
->stats
.DL_time_stop
,
725 tmp
->stats
.DL_total_bytes
);
727 if (tmp
->iter_valid
!= TRUE
) {
728 /* Add to list control if not drawn this UE before */
729 gtk_list_store_append(ues_store
, &tmp
->iter
);
730 tmp
->iter_valid
= TRUE
;
733 /* Set each column for this row */
734 gtk_list_store_set(ues_store
, &tmp
->iter
,
735 RNTI_COLUMN
, tmp
->stats
.rnti
,
737 (tmp
->stats
.rnti_type
== C_RNTI
) ? "C-RNTI" : "SPS-RNTI",
738 UEID_COLUMN
, tmp
->stats
.ueid
,
739 UL_FRAMES_COLUMN
, tmp
->stats
.UL_frames
,
740 UL_BYTES_COLUMN
, tmp
->stats
.UL_total_bytes
,
742 UL_PADDING_PERCENT_COLUMN
,
743 tmp
->stats
.UL_raw_bytes
?
744 (((float)tmp
->stats
.UL_padding_bytes
/ (float)tmp
->stats
.UL_raw_bytes
) * 100.0) :
746 UL_RETX_FRAMES_COLUMN
, tmp
->stats
.UL_retx_frames
,
747 DL_FRAMES_COLUMN
, tmp
->stats
.DL_frames
,
748 DL_BYTES_COLUMN
, tmp
->stats
.DL_total_bytes
,
750 DL_PADDING_PERCENT_COLUMN
,
751 tmp
->stats
.DL_raw_bytes
?
752 (((float)tmp
->stats
.DL_padding_bytes
/ (float)tmp
->stats
.DL_raw_bytes
) * 100.0) :
754 DL_CRC_FAILED_COLUMN
, tmp
->stats
.DL_CRC_failures
,
755 DL_CRC_HIGH_CODE_RATE_COLUMN
, tmp
->stats
.DL_CRC_high_code_rate
,
756 DL_CRC_PDSCH_LOST_COLUMN
, tmp
->stats
.DL_CRC_PDSCH_lost
,
757 DL_CRC_DUPLICATE_NONZERO_RV
, tmp
->stats
.DL_CRC_Duplicate_Nonzero_rv
,
758 DL_RETX_FRAMES_COLUMN
, tmp
->stats
.DL_retx_frames
,
764 if (hs
->selected_rnti
!= 0) {
765 GtkTreeIter
*ue_iter
= NULL
;
766 mac_lte_ep_t
*ep
= hs
->ep_list
;
768 if ((ep
->stats
.ueid
== hs
->selected_ueid
) &&
769 (ep
->stats
.rnti
== hs
->selected_rnti
)) {
775 if (ue_iter
!= NULL
) {
777 gtk_tree_selection_select_iter(gtk_tree_view_get_selection(hs
->ue_table
),
782 /* If there is a UE selected, update its counters in details window */
783 sel
= gtk_tree_view_get_selection(GTK_TREE_VIEW(hs
->ue_table
));
784 if (gtk_tree_selection_get_selected(sel
, &model
, &iter
)) {
787 gtk_tree_model_get(model
, &iter
, TABLE_COLUMN
, &ep
, -1);
788 mac_lte_ue_details(ep
, hs
);
793 /* Compose and set appropriate display filter */
794 typedef enum Direction_t
{UL_Only
, DL_Only
, UL_and_DL
} Direction_t
;
796 static void set_filter_expression(guint16 ueid
,
798 Direction_t direction
,
802 const gchar
*DCTErrorSubstring
,
805 #define MAX_FILTER_LEN 512
806 static char buffer
[MAX_FILTER_LEN
];
809 /* Create the filter expression */
811 /* Show MAC RACH (preamble attempts and RAR PDUs) */
813 offset
+= g_snprintf(buffer
+offset
, MAX_FILTER_LEN
-offset
,
814 "(mac-lte.rar or (mac-lte.preamble-sent and mac-lte.ueid == %u)) or (",
820 offset
+= g_snprintf(buffer
+offset
, MAX_FILTER_LEN
-offset
,
821 "(mac-lte.sr-req and mac-lte.ueid == %u) or (",
827 if (strlen(DCTErrorSubstring
) > 0) {
828 offset
+= g_snprintf(buffer
+offset
, MAX_FILTER_LEN
-offset
,
829 "(dct2000.error-comment and (dct2000.comment contains \"%s\")) or (",
833 offset
+= g_snprintf(buffer
+offset
, MAX_FILTER_LEN
-offset
,
834 "dct2000.error-comment or (");
838 /* Filter expression */
839 if (strlen(hs
->filter
)) {
840 offset
+= g_snprintf(buffer
+offset
, MAX_FILTER_LEN
-offset
, "%s and ", hs
->filter
);
846 offset
+= g_snprintf(buffer
+offset
, MAX_FILTER_LEN
-offset
, "(mac-lte.direction == 0) and ");
849 offset
+= g_snprintf(buffer
+offset
, MAX_FILTER_LEN
-offset
, "(mac-lte.direction == 1) and ");
856 offset
+= g_snprintf(buffer
+offset
, MAX_FILTER_LEN
-offset
,
857 "mac-lte.rnti == %u and mac-lte.ueid == %u",
860 /* Close () if open */
862 offset
+= g_snprintf(buffer
+offset
, MAX_FILTER_LEN
-offset
, ")");
865 /* Close () if open */
867 offset
+= g_snprintf(buffer
+offset
, MAX_FILTER_LEN
-offset
, ")");
871 /* Close () if open */
873 /*offset +=*/ g_snprintf(buffer
+offset
, MAX_FILTER_LEN
-offset
, ")");
876 /* Set its value to our new string */
877 gtk_entry_set_text(GTK_ENTRY(main_display_filter_widget
), buffer
);
880 main_filter_packets(&cfile
, buffer
, TRUE
);
883 /* Respond to UL filter button being clicked by building and using filter */
884 static void ul_filter_clicked(GtkWindow
*win _U_
, mac_lte_stat_t
* hs
)
886 GtkTreeSelection
*sel
;
890 /* If there is a UE selected, update its counters in details window */
891 sel
= gtk_tree_view_get_selection(GTK_TREE_VIEW(hs
->ue_table
));
892 if (gtk_tree_selection_get_selected(sel
, &model
, &iter
)) {
895 /* Get the UE details */
896 gtk_tree_model_get(model
, &iter
, TABLE_COLUMN
, &ep
, -1);
898 set_filter_expression(ep
->stats
.ueid
, ep
->stats
.rnti
, UL_Only
,
899 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(hs
->show_mac_rach_cb
)),
900 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(hs
->show_mac_srs_cb
)),
901 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(hs
->show_dct_errors_cb
)),
902 gtk_entry_get_text(GTK_ENTRY(hs
->dct_error_substring_te
)),
907 /* Respond to DL filter button being clicked by building and using filter */
908 static void dl_filter_clicked(GtkWindow
*win _U_
, mac_lte_stat_t
*hs
)
910 GtkTreeSelection
*sel
;
914 /* If there is a UE selected, update its counters in details window */
915 sel
= gtk_tree_view_get_selection(GTK_TREE_VIEW(hs
->ue_table
));
916 if (gtk_tree_selection_get_selected(sel
, &model
, &iter
)) {
919 /* Get the UE details */
920 gtk_tree_model_get(model
, &iter
, TABLE_COLUMN
, &ep
, -1);
922 set_filter_expression(ep
->stats
.ueid
, ep
->stats
.rnti
, DL_Only
,
923 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(hs
->show_mac_rach_cb
)),
924 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(hs
->show_mac_srs_cb
)),
925 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(hs
->show_dct_errors_cb
)),
926 gtk_entry_get_text(GTK_ENTRY(hs
->dct_error_substring_te
)),
932 /* Respond to UL/DL filter button being clicked by building and using filter */
933 static void uldl_filter_clicked(GtkWindow
*win _U_
, mac_lte_stat_t
*hs
)
935 GtkTreeSelection
*sel
;
939 /* If there is a UE selected, update its counters in details window */
940 sel
= gtk_tree_view_get_selection(GTK_TREE_VIEW(hs
->ue_table
));
941 if (gtk_tree_selection_get_selected(sel
, &model
, &iter
)) {
944 /* Get the UE details */
945 gtk_tree_model_get(model
, &iter
, TABLE_COLUMN
, &ep
, -1);
947 set_filter_expression(ep
->stats
.ueid
, ep
->stats
.rnti
, UL_and_DL
,
948 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(hs
->show_mac_rach_cb
)),
949 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(hs
->show_mac_srs_cb
)),
950 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(hs
->show_dct_errors_cb
)),
951 gtk_entry_get_text(GTK_ENTRY(hs
->dct_error_substring_te
)),
958 /* What to do when a list item is selected/unselected */
959 static void mac_lte_select_cb(GtkTreeSelection
*sel
, gpointer data
)
961 mac_lte_stat_t
*hs
= (mac_lte_stat_t
*)data
;
966 if (gtk_tree_selection_get_selected(sel
, &model
, &iter
)) {
967 /* Show details of selected UE */
968 gtk_tree_model_get(model
, &iter
, TABLE_COLUMN
, &ep
, -1);
969 mac_lte_ue_details(ep
, hs
);
972 mac_lte_ue_details(NULL
, hs
);
976 /* When DCT errors check-box is toggled, enable substring controls accordingly */
977 static void mac_lte_dct_errors_cb(GtkTreeSelection
*sel _U_
, gpointer data
)
979 mac_lte_stat_t
*hs
= (mac_lte_stat_t
*)data
;
980 guint8 show_dct_errors
= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(hs
->show_dct_errors_cb
));
982 gtk_widget_set_sensitive(hs
->dct_error_substring_lb
, show_dct_errors
);
983 gtk_widget_set_sensitive(hs
->dct_error_substring_te
, show_dct_errors
);
987 /* Destroy the stats window */
988 static void win_destroy_cb(GtkWindow
*win _U_
, gpointer data
)
990 mac_lte_stat_t
*hs
= (mac_lte_stat_t
*)data
;
992 remove_tap_listener(hs
);
994 if (hs
->mac_lte_stat_dlg_w
!= NULL
) {
995 window_destroy(hs
->mac_lte_stat_dlg_w
);
996 hs
->mac_lte_stat_dlg_w
= NULL
;
998 mac_lte_stat_reset(hs
);
1004 /* Create a new MAC LTE stats dialog */
1005 static void gtk_mac_lte_stat_init(const char *opt_arg
, void *userdata _U_
)
1008 const char *filter
= NULL
;
1009 GString
*error_string
;
1010 GtkWidget
*ues_scrolled_window
;
1012 GtkWidget
*top_level_vbox
;
1014 GtkWidget
*system_row_hbox
;
1015 GtkWidget
*common_row_hbox
;
1017 GtkWidget
*selected_ue_hb
;
1019 GtkWidget
*mac_lte_stat_system_lb
;
1020 GtkWidget
*mac_lte_stat_common_channel_lb
;
1021 GtkWidget
*mac_lte_stat_selected_ue_lb
;
1022 GtkWidget
*selected_ue_vbox
[NUM_CHANNEL_COLUMNS
];
1023 GtkWidget
*selected_ue_column_titles
[5];
1025 GtkWidget
*mac_lte_stat_filters_lb
;
1026 GtkWidget
*filter_buttons_hb
;
1028 GtkWidget
*close_bt
;
1031 GtkListStore
*store
;
1033 GtkTreeView
*tree_view
;
1034 GtkCellRenderer
*renderer
;
1035 GtkTreeViewColumn
*column
;
1036 GtkTreeSelection
*sel
;
1037 gchar
*display_name
;
1041 /* Check for a filter string */
1042 if (strncmp(opt_arg
, "mac-lte,stat,", 13) == 0) {
1043 /* Skip those characters from filter to display */
1044 filter
= opt_arg
+ 13;
1053 hs
= (mac_lte_stat_t
*)g_malloc(sizeof(mac_lte_stat_t
));
1056 /* Copy filter (so can be used for window title at reset) */
1058 hs
->filter
= g_strdup(filter
);
1065 display_name
= cf_get_display_name(&cfile
);
1066 g_snprintf(title
, sizeof(title
), "Wireshark: LTE MAC Statistics: %s",
1068 g_free(display_name
);
1070 /* Create top-level window */
1071 hs
->mac_lte_stat_dlg_w
= window_new_with_geom(GTK_WINDOW_TOPLEVEL
, title
, "LTE MAC Statistics");
1074 gtk_window_set_default_size(GTK_WINDOW(hs
->mac_lte_stat_dlg_w
), 750, 300);
1076 /* Will stack widgets vertically inside dlg */
1077 top_level_vbox
= ws_gtk_box_new(GTK_ORIENTATION_VERTICAL
, 3, FALSE
); /* FALSE = not homogeneous */
1078 gtk_container_add(GTK_CONTAINER(hs
->mac_lte_stat_dlg_w
), top_level_vbox
);
1080 gtk_container_set_border_width(GTK_CONTAINER(top_level_vbox
), 6);
1081 gtk_widget_show(top_level_vbox
);
1084 /**********************************************/
1086 /**********************************************/
1087 mac_lte_stat_system_lb
= gtk_frame_new("System Data");
1089 /* Add max UEs/TTI counts in one row */
1090 system_row_hbox
= ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 0, FALSE
);
1091 gtk_container_add(GTK_CONTAINER(mac_lte_stat_system_lb
), system_row_hbox
);
1092 gtk_container_set_border_width(GTK_CONTAINER(system_row_hbox
), 5);
1094 gtk_box_pack_start(GTK_BOX(top_level_vbox
), mac_lte_stat_system_lb
, FALSE
, FALSE
, 0);
1096 /* Create labels (that will hold label and counter value) */
1097 hs
->ul_max_ues_per_tti
= gtk_label_new("Max UL UEs/TTI:");
1098 gtk_misc_set_alignment(GTK_MISC(hs
->ul_max_ues_per_tti
), 0.0f
, .5f
);
1099 gtk_box_pack_start(GTK_BOX(system_row_hbox
), hs
->ul_max_ues_per_tti
, TRUE
, TRUE
, 0);
1100 gtk_widget_show(hs
->ul_max_ues_per_tti
);
1102 hs
->dl_max_ues_per_tti
= gtk_label_new("Max DL UEs/TTI:");
1103 gtk_misc_set_alignment(GTK_MISC(hs
->dl_max_ues_per_tti
), 0.0f
, .5f
);
1104 gtk_box_pack_start(GTK_BOX(system_row_hbox
), hs
->dl_max_ues_per_tti
, TRUE
, TRUE
, 0);
1105 gtk_widget_show(hs
->dl_max_ues_per_tti
);
1108 /**********************************************/
1109 /* Common Channel data */
1110 /**********************************************/
1111 mac_lte_stat_common_channel_lb
= gtk_frame_new("Common Channel Data");
1113 /* Will add BCH and PCH counters into one row */
1114 common_row_hbox
= ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 0, FALSE
);
1115 gtk_container_add(GTK_CONTAINER(mac_lte_stat_common_channel_lb
), common_row_hbox
);
1116 gtk_container_set_border_width(GTK_CONTAINER(common_row_hbox
), 5);
1118 gtk_box_pack_start(GTK_BOX(top_level_vbox
), mac_lte_stat_common_channel_lb
, FALSE
, FALSE
, 0);
1120 /* Create labels (that will hold label and counter value) */
1121 hs
->common_mib_frames
= gtk_label_new("MIBs:");
1122 gtk_misc_set_alignment(GTK_MISC(hs
->common_mib_frames
), 0.0f
, .5f
);
1123 gtk_box_pack_start(GTK_BOX(common_row_hbox
), hs
->common_mib_frames
, TRUE
, TRUE
, 0);
1124 gtk_widget_show(hs
->common_mib_frames
);
1126 hs
->common_sib_frames
= gtk_label_new("SIB Frames:");
1127 gtk_misc_set_alignment(GTK_MISC(hs
->common_sib_frames
), 0.0f
, .5f
);
1128 gtk_box_pack_start(GTK_BOX(common_row_hbox
), hs
->common_sib_frames
, TRUE
, TRUE
, 0);
1129 gtk_widget_show(hs
->common_sib_frames
);
1131 hs
->common_sib_bytes
= gtk_label_new("SIB Bytes:");
1132 gtk_misc_set_alignment(GTK_MISC(hs
->common_sib_bytes
), 0.0f
, .5f
);
1133 gtk_box_pack_start(GTK_BOX(common_row_hbox
), hs
->common_sib_bytes
, TRUE
, TRUE
, 0);
1134 gtk_widget_show(hs
->common_sib_bytes
);
1136 hs
->common_pch_frames
= gtk_label_new("PCH Frames:");
1137 gtk_misc_set_alignment(GTK_MISC(hs
->common_pch_frames
), 0.0f
, .5f
);
1138 gtk_box_pack_start(GTK_BOX(common_row_hbox
), hs
->common_pch_frames
, TRUE
, TRUE
, 0);
1139 gtk_widget_show(hs
->common_pch_frames
);
1141 hs
->common_pch_bytes
= gtk_label_new("PCH Bytes:");
1142 gtk_misc_set_alignment(GTK_MISC(hs
->common_pch_bytes
), 0.0f
, .5f
);
1143 gtk_box_pack_start(GTK_BOX(common_row_hbox
), hs
->common_pch_bytes
, TRUE
, TRUE
, 0);
1144 gtk_widget_show(hs
->common_pch_bytes
);
1146 hs
->common_pch_paging_ids
= gtk_label_new("PCH Paging IDs:");
1147 gtk_misc_set_alignment(GTK_MISC(hs
->common_pch_paging_ids
), 0.0f
, .5f
);
1148 gtk_box_pack_start(GTK_BOX(common_row_hbox
), hs
->common_pch_paging_ids
, TRUE
, TRUE
, 0);
1149 gtk_widget_show(hs
->common_pch_paging_ids
);
1152 hs
->common_rar_frames
= gtk_label_new("RAR Frames:");
1153 gtk_misc_set_alignment(GTK_MISC(hs
->common_rar_frames
), 0.0f
, .5f
);
1154 gtk_box_pack_start(GTK_BOX(common_row_hbox
), hs
->common_rar_frames
, TRUE
, TRUE
, 0);
1155 gtk_widget_show(hs
->common_rar_frames
);
1157 hs
->common_rar_entries
= gtk_label_new("RAR Entries:");
1158 gtk_misc_set_alignment(GTK_MISC(hs
->common_rar_entries
), 0.0f
, .5f
);
1159 gtk_box_pack_start(GTK_BOX(common_row_hbox
), hs
->common_rar_entries
, TRUE
, TRUE
, 0);
1160 gtk_widget_show(hs
->common_rar_entries
);
1162 /**********************************************/
1163 /* UL/DL-SCH data */
1164 /**********************************************/
1166 hs
->mac_lte_stat_ues_lb
= gtk_frame_new("UL/DL-SCH Data (0 UEs)");
1167 ues_vb
= ws_gtk_box_new(GTK_ORIENTATION_VERTICAL
, 0, FALSE
);
1168 gtk_container_add(GTK_CONTAINER(hs
->mac_lte_stat_ues_lb
), ues_vb
);
1169 gtk_container_set_border_width(GTK_CONTAINER(ues_vb
), 5);
1171 ues_scrolled_window
= scrolled_window_new(NULL
, NULL
);
1172 gtk_box_pack_start(GTK_BOX(ues_vb
), ues_scrolled_window
, TRUE
, TRUE
, 0);
1173 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(ues_scrolled_window
),
1176 /* Create the table of UE data */
1177 store
= gtk_list_store_new(NUM_UE_COLUMNS
, G_TYPE_INT
, G_TYPE_STRING
, G_TYPE_INT
,
1178 G_TYPE_INT
, G_TYPE_INT
, G_TYPE_FLOAT
, G_TYPE_FLOAT
, G_TYPE_INT
, /* UL */
1179 G_TYPE_INT
, G_TYPE_INT
, G_TYPE_FLOAT
, G_TYPE_FLOAT
, G_TYPE_INT
,
1180 G_TYPE_INT
, G_TYPE_INT
, G_TYPE_INT
, G_TYPE_INT
, /* DL */
1182 hs
->ue_table
= GTK_TREE_VIEW(tree_view_new(GTK_TREE_MODEL(store
)));
1183 gtk_container_add(GTK_CONTAINER (ues_scrolled_window
), GTK_WIDGET(hs
->ue_table
));
1184 g_object_unref(G_OBJECT(store
));
1186 tree_view
= hs
->ue_table
;
1187 gtk_tree_view_set_headers_visible(tree_view
, TRUE
);
1188 gtk_tree_view_set_headers_clickable(tree_view
, TRUE
);
1190 /* Create the titles for each column of the per-UE table */
1191 for (i
= 0; i
< TABLE_COLUMN
; i
++) {
1192 if ((i
== UL_PADDING_PERCENT_COLUMN
) ||
1193 (i
== DL_PADDING_PERCENT_COLUMN
)) {
1194 /* Show % as progress bar */
1195 /* XXX: "progess" rendering doesn't seem to work for Gtk3 ?? */
1196 renderer
= gtk_cell_renderer_progress_new();
1197 column
= gtk_tree_view_column_new_with_attributes(ue_titles
[i
], renderer
,
1203 renderer
= gtk_cell_renderer_text_new();
1204 column
= gtk_tree_view_column_new_with_attributes(ue_titles
[i
], renderer
,
1207 gtk_tree_view_column_set_sort_column_id(column
, i
);
1210 /* Expand first column (RNTI, which is Key) */
1211 gtk_tree_view_column_set_expand(column
, TRUE
);
1213 /* For other columns, set all of the free space to be on the left */
1214 g_object_set(G_OBJECT(renderer
), "xalign", 1.0, NULL
);
1216 gtk_tree_view_column_set_sizing(column
, GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
1217 gtk_tree_view_column_set_resizable(column
, TRUE
);
1218 gtk_tree_view_append_column(tree_view
, column
);
1221 /* Set callback function for selecting a row in the UE table */
1222 sel
= gtk_tree_view_get_selection(GTK_TREE_VIEW(hs
->ue_table
));
1223 gtk_tree_selection_set_mode(sel
, GTK_SELECTION_SINGLE
);
1224 g_signal_connect(sel
, "changed", G_CALLBACK(mac_lte_select_cb
), hs
);
1226 gtk_box_pack_start(GTK_BOX(top_level_vbox
), hs
->mac_lte_stat_ues_lb
, TRUE
, TRUE
, 0);
1229 /**********************************************/
1230 /* Details of selected UE */
1231 /**********************************************/
1233 mac_lte_stat_selected_ue_lb
= gtk_frame_new("Selected UE details");
1235 selected_ue_hb
= ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 6, FALSE
);
1236 gtk_container_add(GTK_CONTAINER(mac_lte_stat_selected_ue_lb
), selected_ue_hb
);
1237 gtk_container_set_border_width(GTK_CONTAINER(selected_ue_hb
), 5);
1239 /********************************/
1240 /* First (row titles) column */
1241 selected_ue_vbox
[0] = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL
, 0, FALSE
);
1242 gtk_box_pack_start(GTK_BOX(selected_ue_hb
), selected_ue_vbox
[0], TRUE
, TRUE
, 0);
1244 selected_ue_column_titles
[0] = gtk_label_new("");
1245 gtk_misc_set_alignment(GTK_MISC(selected_ue_column_titles
[0]), 0.0f
, 0.0f
);
1246 gtk_box_pack_start(GTK_BOX(selected_ue_vbox
[0]), selected_ue_column_titles
[0], FALSE
, FALSE
, 0);
1248 for (n
=1; n
< 5; n
++) {
1249 selected_ue_column_titles
[n
] = gtk_label_new(selected_ue_row_names
[n
-1]);
1250 gtk_misc_set_alignment(GTK_MISC(selected_ue_column_titles
[n
]), 0.0f
, 0.0f
);
1251 gtk_box_pack_start(GTK_BOX(selected_ue_vbox
[0]), selected_ue_column_titles
[n
], FALSE
, FALSE
, 0);
1252 gtk_widget_show(selected_ue_column_titles
[n
]);
1256 /*************************/
1258 for (i
=CCCH_COLUMN
; i
< NUM_CHANNEL_COLUMNS
; i
++) {
1259 selected_ue_vbox
[i
] = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL
, 0, FALSE
);
1260 gtk_box_pack_start(GTK_BOX(selected_ue_hb
), selected_ue_vbox
[i
], TRUE
, TRUE
, 0);
1263 hs
->selected_ue_column_entry
[i
][0] = gtk_label_new(channel_titles
[i
-1]);
1264 gtk_misc_set_alignment(GTK_MISC(hs
->selected_ue_column_entry
[i
][0]), 0.5f
, 0.0f
);
1265 gtk_box_pack_start(GTK_BOX(selected_ue_vbox
[i
]), hs
->selected_ue_column_entry
[i
][0], FALSE
, FALSE
, 0);
1267 /* Counts for this channel */
1268 for (n
=1; n
< 5; n
++) {
1269 hs
->selected_ue_column_entry
[i
][n
] = gtk_label_new("0");
1270 gtk_misc_set_alignment(GTK_MISC(hs
->selected_ue_column_entry
[i
][n
]), 1.0f
, 0.0f
);
1271 gtk_box_pack_start(GTK_BOX(selected_ue_vbox
[i
]), hs
->selected_ue_column_entry
[i
][n
], FALSE
, FALSE
, 0);
1272 gtk_widget_show(hs
->selected_ue_column_entry
[i
][n
]);
1276 gtk_box_pack_start(GTK_BOX(top_level_vbox
), mac_lte_stat_selected_ue_lb
, FALSE
, FALSE
, 0);
1279 /**************************************/
1280 /* Filter on RNTI/UEId */
1281 /**************************************/
1282 mac_lte_stat_filters_lb
= gtk_frame_new("Filter on UE");
1284 /* Horizontal row of filter controls */
1285 filter_buttons_hb
= ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 6, FALSE
);
1286 gtk_container_add(GTK_CONTAINER(mac_lte_stat_filters_lb
), filter_buttons_hb
);
1287 gtk_container_set_border_width(GTK_CONTAINER(filter_buttons_hb
), 2);
1289 /* Add filters box to top-level window */
1290 gtk_box_pack_start(GTK_BOX(top_level_vbox
), mac_lte_stat_filters_lb
, FALSE
, FALSE
, 0);
1292 /* Filter buttons */
1295 hs
->ul_filter_bt
= gtk_button_new_with_label("Set UL display filter on selected this UE");
1296 gtk_box_pack_start(GTK_BOX(filter_buttons_hb
), hs
->ul_filter_bt
, FALSE
, FALSE
, 0);
1297 g_signal_connect(hs
->ul_filter_bt
, "clicked", G_CALLBACK(ul_filter_clicked
), hs
);
1298 gtk_widget_set_sensitive(hs
->ul_filter_bt
, FALSE
);
1299 gtk_widget_show(hs
->ul_filter_bt
);
1300 gtk_widget_set_tooltip_text(hs
->ul_filter_bt
,
1301 "Generate and set a filter showing only UL frames with selected RNTI and UEId");
1304 hs
->dl_filter_bt
= gtk_button_new_with_label("Set DL display filter on selected this UE");
1305 gtk_box_pack_start(GTK_BOX(filter_buttons_hb
), hs
->dl_filter_bt
, FALSE
, FALSE
, 0);
1306 g_signal_connect(hs
->dl_filter_bt
, "clicked", G_CALLBACK(dl_filter_clicked
), hs
);
1307 gtk_widget_set_sensitive(hs
->dl_filter_bt
, FALSE
);
1308 gtk_widget_show(hs
->dl_filter_bt
);
1309 gtk_widget_set_tooltip_text(hs
->dl_filter_bt
,
1310 "Generate and set a filter showing only DL frames with selected RNTI and UEId");
1313 hs
->uldl_filter_bt
= gtk_button_new_with_label("Set UL / DL display filter on selected this UE");
1314 gtk_box_pack_start(GTK_BOX(filter_buttons_hb
), hs
->uldl_filter_bt
, FALSE
, FALSE
, 0);
1315 g_signal_connect(hs
->uldl_filter_bt
, "clicked", G_CALLBACK(uldl_filter_clicked
), hs
);
1316 gtk_widget_set_sensitive(hs
->uldl_filter_bt
, FALSE
);
1317 gtk_widget_show(hs
->uldl_filter_bt
);
1318 gtk_widget_set_tooltip_text(hs
->uldl_filter_bt
,
1319 "Generate and set a filter showing only frames with selected RNTI and UEId");
1322 hs
->show_mac_rach_cb
= gtk_check_button_new_with_mnemonic("Show MAC RACH");
1323 gtk_widget_set_sensitive(hs
->show_mac_rach_cb
, FALSE
);
1324 gtk_box_pack_start(GTK_BOX(filter_buttons_hb
), hs
->show_mac_rach_cb
, TRUE
, TRUE
, 0);
1325 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(hs
->show_mac_rach_cb
), FALSE
);
1326 gtk_widget_set_tooltip_text(hs
->show_mac_rach_cb
, "When checked, generated filters will show "
1327 "MAC RACH attempts for the UE");
1330 hs
->show_mac_srs_cb
= gtk_check_button_new_with_mnemonic("Show MAC SRs");
1331 gtk_widget_set_sensitive(hs
->show_mac_srs_cb
, FALSE
);
1332 gtk_box_pack_start(GTK_BOX(filter_buttons_hb
), hs
->show_mac_srs_cb
, TRUE
, TRUE
, 0);
1333 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(hs
->show_mac_srs_cb
), FALSE
);
1334 gtk_widget_set_tooltip_text(hs
->show_mac_srs_cb
, "When checked, generated filters will show "
1335 "MAC SRs for the UE");
1338 /* Allow DCT errors to be shown... */
1339 hs
->show_dct_errors_cb
= gtk_check_button_new_with_mnemonic("Show DCT2000 error strings");
1340 gtk_box_pack_start(GTK_BOX(filter_buttons_hb
), hs
->show_dct_errors_cb
, TRUE
, TRUE
, 0);
1341 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(hs
->show_dct_errors_cb
), FALSE
);
1342 g_signal_connect(hs
->show_dct_errors_cb
, "toggled", G_CALLBACK(mac_lte_dct_errors_cb
), hs
);
1343 gtk_widget_set_tooltip_text(hs
->show_dct_errors_cb
, "When checked, generated filters will "
1344 "include DCT2000 error strings");
1345 /* Initially disabled */
1346 gtk_widget_set_sensitive(hs
->show_dct_errors_cb
, FALSE
);
1348 /* ... optionally limited by a substring */
1349 hs
->dct_error_substring_lb
= gtk_label_new("...containing");
1350 gtk_box_pack_start(GTK_BOX(filter_buttons_hb
), hs
->dct_error_substring_lb
, FALSE
, FALSE
, 0);
1351 gtk_widget_show(hs
->dct_error_substring_lb
);
1352 gtk_widget_set_sensitive(hs
->dct_error_substring_lb
, FALSE
);
1354 hs
->dct_error_substring_te
= gtk_entry_new();
1355 gtk_box_pack_start(GTK_BOX(filter_buttons_hb
), hs
->dct_error_substring_te
, FALSE
, FALSE
, 0);
1356 gtk_widget_show(hs
->dct_error_substring_te
);
1357 gtk_widget_set_sensitive(hs
->dct_error_substring_te
, FALSE
);
1358 gtk_widget_set_tooltip_text(hs
->dct_error_substring_te
,
1359 "If given, only match error strings containing this substring");
1362 /**********************************************/
1363 /* Register the tap listener */
1364 /**********************************************/
1366 error_string
= register_tap_listener("mac-lte", hs
,
1369 mac_lte_stat_packet
,
1372 simple_dialog(ESD_TYPE_ERROR
, ESD_BTN_OK
, "%s", error_string
->str
);
1373 g_string_free(error_string
, TRUE
);
1379 /************************************/
1381 /************************************/
1383 bbox
= dlg_button_row_new (GTK_STOCK_CLOSE
, GTK_STOCK_HELP
, NULL
);
1384 gtk_box_pack_end (GTK_BOX(top_level_vbox
), bbox
, FALSE
, FALSE
, 0);
1386 /* Add the close button */
1387 close_bt
= (GtkWidget
*)g_object_get_data(G_OBJECT(bbox
), GTK_STOCK_CLOSE
);
1388 window_set_cancel_button(hs
->mac_lte_stat_dlg_w
, close_bt
, window_cancel_button_cb
);
1390 help_bt
= (GtkWidget
*)g_object_get_data(G_OBJECT(bbox
), GTK_STOCK_HELP
);
1391 g_signal_connect(help_bt
, "clicked", G_CALLBACK(topic_cb
), (gpointer
)HELP_STATS_LTE_MAC_TRAFFIC_DIALOG
);
1394 g_signal_connect(hs
->mac_lte_stat_dlg_w
, "delete_event", G_CALLBACK(window_delete_event_cb
), NULL
);
1395 g_signal_connect(hs
->mac_lte_stat_dlg_w
, "destroy", G_CALLBACK(win_destroy_cb
), hs
);
1397 /* Show the window */
1398 gtk_widget_show_all(hs
->mac_lte_stat_dlg_w
);
1399 window_present(hs
->mac_lte_stat_dlg_w
);
1402 cf_retap_packets(&cfile
);
1403 gdk_window_raise(gtk_widget_get_window(hs
->mac_lte_stat_dlg_w
));
1407 static tap_param mac_lte_stat_params
[] = {
1408 { PARAM_FILTER
, "Filter", NULL
}
1411 static tap_param_dlg mac_lte_stat_dlg
= {
1414 gtk_mac_lte_stat_init
,
1416 G_N_ELEMENTS(mac_lte_stat_params
),
1421 /* Register this tap listener (need void on own so line register function found) */
1422 void register_tap_listener_mac_lte_stat(void)
1424 register_param_stat(&mac_lte_stat_dlg
, "_MAC", REGISTER_STAT_GROUP_TELEPHONY_LTE
);