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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
35 #ifdef HAVE_SYS_TYPES_H
36 #include <sys/types.h>
43 #include "gtk/gtkglobals.h"
45 #include <epan/packet.h>
46 #include <epan/packet_info.h>
48 #include <epan/dissectors/packet-mac-lte.h>
50 #include "../simple_dialog.h"
51 #include "../stat_menu.h"
53 #include "gtk/dlg_utils.h"
54 #include "gtk/gui_stat_menu.h"
55 #include "gtk/tap_param_dlg.h"
56 #include "gtk/gui_utils.h"
57 #include "gtk/help_dlg.h"
60 #include "gtk/old-gtk-compat.h"
62 /**********************************************/
63 /* Table column identifiers and title strings */
72 UL_PADDING_PERCENT_COLUMN,
73 UL_RETX_FRAMES_COLUMN,
78 DL_CRC_HIGH_CODE_RATE_COLUMN,
79 DL_CRC_PDSCH_LOST_COLUMN,
80 DL_RETX_FRAMES_COLUMN,
101 static const gchar *ue_titles[] = { "RNTI", "Type", "UEId",
102 "UL Frames", "UL Bytes", "UL MBit/sec", "UL Padding %", "UL ReTX",
103 "DL Frames", "DL Bytes", "DL MBit/sec", "DL CRC Failed", "DL CRC High Code Rate", "DL CRC PDSCH Lost", "DL ReTX"};
105 static const gchar *channel_titles[] = { "CCCH",
106 "LCID 1", "LCID 2", "LCID 3", "LCID 4", "LCID 5",
107 "LCID 6", "LCID 7", "LCID 8", "LCID 9", "LCID 10",
111 /* Stats for one UE */
112 typedef struct mac_lte_row_data {
113 /* Key for matching this row */
118 gboolean is_predefined_data;
121 guint32 UL_raw_bytes; /* all bytes */
122 guint32 UL_total_bytes; /* payload */
123 nstime_t UL_time_start;
124 nstime_t UL_time_stop;
125 guint32 UL_padding_bytes;
126 guint32 UL_CRC_errors;
127 guint32 UL_retx_frames;
130 guint32 DL_total_bytes;
131 nstime_t DL_time_start;
132 nstime_t DL_time_stop;
133 guint32 DL_CRC_failures;
134 guint32 DL_CRC_high_code_rate;
135 guint32 DL_CRC_PDSCH_lost;
136 guint32 DL_retx_frames;
138 guint32 UL_bytes_for_lcid[11];
139 guint32 UL_sdus_for_lcid[11];
140 guint32 DL_bytes_for_lcid[11];
141 guint32 DL_sdus_for_lcid[11];
145 /* One row/UE in the UE table */
146 typedef struct mac_lte_ep {
147 struct mac_lte_ep* next;
148 struct mac_lte_row_data stats;
154 /* Common channel stats */
155 typedef struct mac_lte_common_stats {
164 guint16 max_ul_ues_in_tti;
165 guint16 max_dl_ues_in_tti;
166 } mac_lte_common_stats;
169 static const char * selected_ue_row_names[] = {"UL SDUs", "UL Bytes", "DL SDUs", "DL Bytes"};
172 /* Used to keep track of whole MAC LTE statistics window */
173 typedef struct mac_lte_stat_t {
174 /* Stats window itself */
175 GtkWidget *mac_lte_stat_dlg_w;
180 GtkWidget *mac_lte_stat_ues_lb;
181 GtkWidget *ul_filter_bt;
182 GtkWidget *dl_filter_bt;
183 GtkWidget *uldl_filter_bt;
185 GtkWidget *show_dct_errors_cb;
186 GtkWidget *dct_error_substring_lb;
187 GtkWidget *dct_error_substring_te;
189 GtkWidget *ul_max_ues_per_tti;
190 GtkWidget *dl_max_ues_per_tti;
193 mac_lte_common_stats common_stats;
194 GtkWidget *common_bch_frames;
195 GtkWidget *common_bch_bytes;
196 GtkWidget *common_pch_frames;
197 GtkWidget *common_pch_bytes;
198 GtkWidget *common_rar_frames;
199 GtkWidget *common_rar_entries;
201 /* Keep track of unique rntis & ueids */
202 guint8 used_ueids[65535];
203 guint8 used_rntis[65535];
204 guint16 number_of_ueids;
205 guint16 number_of_rntis;
207 guint16 selected_rnti;
208 guint16 selected_ueid;
210 /* Labels in selected UE 'table' */
211 GtkWidget *selected_ue_column_entry[NUM_CHANNEL_COLUMNS][5];
213 GtkTreeView *ue_table;
214 mac_lte_ep_t *ep_list;
218 /* Reset the statistics window */
220 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;
229 if (mac_lte_stat->mac_lte_stat_dlg_w != NULL) {
230 g_snprintf(title, sizeof(title), "Wireshark: LTE MAC Traffic Statistics: %s (filter=\"%s\")",
231 cf_get_display_name(&cfile),
232 strlen(mac_lte_stat->filter) ? mac_lte_stat->filter : "none");
233 gtk_window_set_title(GTK_WINDOW(mac_lte_stat->mac_lte_stat_dlg_w), title);
236 g_snprintf(title, sizeof(title), "UL/DL-SCH data (0 entries)");
237 gtk_frame_set_label(GTK_FRAME(mac_lte_stat->mac_lte_stat_ues_lb), title);
239 /* Reset counts of unique ueids & rntis */
240 memset(mac_lte_stat->used_ueids, 0, 65535);
241 mac_lte_stat->number_of_ueids = 0;
242 memset(mac_lte_stat->used_rntis, 0, 65535);
243 mac_lte_stat->number_of_rntis = 0;
245 /* Zero common stats */
246 memset(&(mac_lte_stat->common_stats), 0, sizeof(mac_lte_common_stats));
248 /* Remove all entries from the UE list */
249 store = GTK_LIST_STORE(gtk_tree_view_get_model(mac_lte_stat->ue_table));
250 gtk_list_store_clear(store);
256 mac_lte_stat->ep_list = NULL;
258 /* Set all of the channel counters to 0 */
259 for (n=1; n <=4; n++) {
260 for (i=CCCH_COLUMN; i < NUM_CHANNEL_COLUMNS; i++) {
261 gtk_label_set_text(GTK_LABEL(mac_lte_stat->selected_ue_column_entry[i][n]), "0");
267 /* Allocate a mac_lte_ep_t struct to store info for new UE */
268 static mac_lte_ep_t* alloc_mac_lte_ep(struct mac_lte_tap_info *si, packet_info *pinfo _U_)
277 if (!(ep = g_malloc(sizeof(mac_lte_ep_t)))) {
281 /* Copy SI data into ep->stats */
282 ep->stats.rnti = si->rnti;
283 ep->stats.rnti_type = si->rntiType;
284 ep->stats.ueid = si->ueid;
286 /* Counts for new UE are all 0 */
287 ep->stats.UL_frames = 0;
288 ep->stats.DL_frames = 0;
289 ep->stats.UL_total_bytes = 0;
290 ep->stats.UL_raw_bytes = 0;
291 ep->stats.UL_padding_bytes = 0;
292 ep->stats.DL_total_bytes = 0;
293 ep->stats.UL_CRC_errors = 0;
294 ep->stats.DL_CRC_failures = 0;
295 ep->stats.DL_CRC_high_code_rate = 0;
296 ep->stats.DL_CRC_PDSCH_lost = 0;
297 ep->stats.UL_retx_frames = 0;
298 ep->stats.DL_retx_frames = 0;
300 for (n=0; n < 11; n++) {
301 ep->stats.UL_sdus_for_lcid[n] = 0;
302 ep->stats.UL_bytes_for_lcid[n] = 0;
304 ep->stats.DL_total_bytes = 0;
305 for (n=0; n < 11; n++) {
306 ep->stats.DL_sdus_for_lcid[n] = 0;
307 ep->stats.DL_bytes_for_lcid[n] = 0;
312 ep->iter_valid = FALSE;
318 /* Update counts of unique rntis & ueids */
319 static void update_ueid_rnti_counts(guint16 rnti, guint16 ueid, mac_lte_stat_t *hs)
321 if (!hs->used_ueids[ueid]) {
322 hs->used_ueids[ueid] = TRUE;
323 hs->number_of_ueids++;
325 if (!hs->used_rntis[rnti]) {
326 hs->used_rntis[rnti] = TRUE;
327 hs->number_of_rntis++;
332 /* Process stat struct for a MAC LTE frame */
334 mac_lte_stat_packet(void *phs, packet_info *pinfo, epan_dissect_t *edt _U_,
339 /* Get reference to stat window instance */
340 mac_lte_stat_t *hs = (mac_lte_stat_t *)phs;
341 mac_lte_ep_t *tmp = NULL, *te = NULL;
343 /* Cast tap info struct */
344 struct mac_lte_tap_info *si = (struct mac_lte_tap_info *)phi;
350 hs->common_stats.all_frames++;
352 /* For common channels, just update global counters */
353 switch (si->rntiType) {
355 hs->common_stats.pch_frames++;
356 hs->common_stats.pch_bytes += si->single_number_of_bytes;
360 hs->common_stats.bch_frames++;
361 hs->common_stats.bch_bytes += si->single_number_of_bytes;
364 hs->common_stats.rar_frames++;
365 hs->common_stats.rar_entries += si->number_of_rars;
369 /* Drop through for per-UE update */
377 /* Check max UEs/tti counter */
378 switch (si->direction) {
379 case DIRECTION_UPLINK:
380 hs->common_stats.max_ul_ues_in_tti =
381 MAX(hs->common_stats.max_ul_ues_in_tti, si->ueInTTI);
383 case DIRECTION_DOWNLINK:
384 hs->common_stats.max_dl_ues_in_tti =
385 MAX(hs->common_stats.max_dl_ues_in_tti, si->ueInTTI);
389 /* For per-UE data, must create a new row if none already existing */
391 /* Allocate new list */
392 hs->ep_list = alloc_mac_lte_ep(si, pinfo);
393 /* Make it the first/only entry */
396 /* Update counts of unique ueids & rntis */
397 update_ueid_rnti_counts(si->rnti, si->ueid, hs);
399 /* Look among existing rows for this RNTI */
400 for (tmp = hs->ep_list;(tmp != NULL); tmp = tmp->next) {
401 /* Match only by RNTI and UEId together */
402 if ((tmp->stats.rnti == si->rnti) &&
403 (tmp->stats.ueid == si->ueid)){
409 /* Not found among existing, so create a new one anyway */
411 if ((te = alloc_mac_lte_ep(si, pinfo))) {
412 /* Add new item to end of list */
413 mac_lte_ep_t *p = hs->ep_list;
420 /* Update counts of unique ueids & rntis */
421 update_ueid_rnti_counts(si->rnti, si->ueid, hs);
426 /* Really should have a row pointer by now */
431 /* Update entry with details from si */
432 te->stats.rnti = si->rnti;
433 te->stats.is_predefined_data = si->isPredefinedData;
436 if (si->direction == DIRECTION_UPLINK) {
438 te->stats.UL_retx_frames++;
442 if (si->crcStatusValid && (si->crcStatus != crc_success)) {
443 te->stats.UL_CRC_errors++;
447 /* Update time range */
448 if (te->stats.UL_frames == 0) {
449 te->stats.UL_time_start = si->time;
451 te->stats.UL_time_stop = si->time;
453 te->stats.UL_frames++;
455 te->stats.UL_raw_bytes += si->raw_length;
456 te->stats.UL_padding_bytes += si->padding_bytes;
458 if (si->isPredefinedData) {
459 te->stats.UL_total_bytes += si->single_number_of_bytes;
462 for (n=0; n < 11; n++) {
463 if (si->bytes_for_lcid[n]) {
464 te->stats.UL_sdus_for_lcid[n] += si->sdus_for_lcid[n];
466 te->stats.UL_bytes_for_lcid[n] += si->bytes_for_lcid[n];
467 te->stats.UL_total_bytes += si->bytes_for_lcid[n];
475 te->stats.DL_retx_frames++;
479 if (si->crcStatusValid && (si->crcStatus != crc_success)) {
480 switch (si->crcStatus) {
482 te->stats.DL_CRC_failures++;
484 case crc_high_code_rate:
485 te->stats.DL_CRC_high_code_rate++;
488 te->stats.DL_CRC_PDSCH_lost++;
491 /* Something went wrong! */
497 /* Update time range */
498 if (te->stats.DL_frames == 0) {
499 te->stats.DL_time_start = si->time;
501 te->stats.DL_time_stop = si->time;
503 te->stats.DL_frames++;
505 if (si->isPredefinedData) {
506 te->stats.DL_total_bytes += si->single_number_of_bytes;
509 for (n=0; n < 11; n++) {
510 if (si->bytes_for_lcid[n]) {
511 te->stats.DL_sdus_for_lcid[n] += si->sdus_for_lcid[n];
513 te->stats.DL_bytes_for_lcid[n] += si->bytes_for_lcid[n];
514 te->stats.DL_total_bytes += si->bytes_for_lcid[n];
523 /* Draw the UE details table according to the current UE selection */
525 mac_lte_ue_details(mac_lte_ep_t *mac_stat_ep, mac_lte_stat_t *hs)
529 guint8 show_dct_errors;
531 /**********************************/
532 /* Set data one row at a time */
535 for (n=0; n < PREDEFINED_COLUMN-1; n++) {
536 g_snprintf(buff, sizeof(buff), "%u",
537 (mac_stat_ep != NULL) ? mac_stat_ep->stats.UL_sdus_for_lcid[n] : 0);
538 gtk_label_set_text(GTK_LABEL(hs->selected_ue_column_entry[n+1][1]), buff);
542 if (mac_stat_ep != NULL) {
543 g_snprintf(buff, sizeof(buff), "%u",
544 mac_stat_ep->stats.is_predefined_data ? mac_stat_ep->stats.UL_frames : 0);
547 g_snprintf(buff, sizeof(buff), "%u", 0);
549 gtk_label_set_text(GTK_LABEL(hs->selected_ue_column_entry[PREDEFINED_COLUMN][1]), buff);
553 for (n=0; n < PREDEFINED_COLUMN-1; n++) {
554 g_snprintf(buff, sizeof(buff), "%u",
555 (mac_stat_ep != NULL) ? mac_stat_ep->stats.UL_bytes_for_lcid[n] : 0);
556 gtk_label_set_text(GTK_LABEL(hs->selected_ue_column_entry[n+1][2]), buff);
560 if (mac_stat_ep != NULL) {
561 g_snprintf(buff, sizeof(buff), "%u",
562 mac_stat_ep->stats.is_predefined_data ? mac_stat_ep->stats.UL_total_bytes : 0);
565 g_snprintf(buff, sizeof(buff), "%u", 0);
567 gtk_label_set_text(GTK_LABEL(hs->selected_ue_column_entry[PREDEFINED_COLUMN][2]), buff);
571 for (n=0; n < PREDEFINED_COLUMN-1; n++) {
572 g_snprintf(buff, sizeof(buff), "%u",
573 (mac_stat_ep != NULL) ? mac_stat_ep->stats.DL_sdus_for_lcid[n] : 0);
574 gtk_label_set_text(GTK_LABEL(hs->selected_ue_column_entry[n+1][3]), buff);
577 if (mac_stat_ep != NULL) {
578 g_snprintf(buff, sizeof(buff), "%u",
579 mac_stat_ep->stats.is_predefined_data ? mac_stat_ep->stats.DL_frames : 0);
582 g_snprintf(buff, sizeof(buff), "%u", 0);
584 gtk_label_set_text(GTK_LABEL(hs->selected_ue_column_entry[PREDEFINED_COLUMN][3]), buff);
588 for (n=0; n < PREDEFINED_COLUMN-1; n++) {
589 g_snprintf(buff, sizeof(buff), "%u",
590 (mac_stat_ep != NULL) ? mac_stat_ep->stats.DL_bytes_for_lcid[n] : 0);
591 gtk_label_set_text(GTK_LABEL(hs->selected_ue_column_entry[n+1][4]), buff);
594 if (mac_stat_ep != NULL) {
595 g_snprintf(buff, sizeof(buff), "%u",
596 mac_stat_ep->stats.is_predefined_data ? mac_stat_ep->stats.DL_total_bytes : 0);
599 g_snprintf(buff, sizeof(buff), "%u", 0);
601 gtk_label_set_text(GTK_LABEL(hs->selected_ue_column_entry[PREDEFINED_COLUMN][4]), buff);
603 /* Remember selected UE */
605 hs->selected_rnti = mac_stat_ep->stats.rnti;
606 hs->selected_ueid = mac_stat_ep->stats.ueid;
609 /* Enable/disable filter controls */
610 gtk_widget_set_sensitive(hs->ul_filter_bt, mac_stat_ep != NULL);
611 gtk_widget_set_sensitive(hs->dl_filter_bt, mac_stat_ep != NULL);
612 gtk_widget_set_sensitive(hs->uldl_filter_bt, mac_stat_ep != NULL);
613 gtk_widget_set_sensitive(hs->show_dct_errors_cb, mac_stat_ep != NULL);
615 /* Enabling substring control only if errors enabled */
616 show_dct_errors = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(hs->show_dct_errors_cb));
617 gtk_widget_set_sensitive(hs->dct_error_substring_lb, show_dct_errors && (mac_stat_ep != NULL));
618 gtk_widget_set_sensitive(hs->dct_error_substring_te, show_dct_errors && (mac_stat_ep != NULL));
622 /* Calculate and return a bandwidth figure, in Mbs */
623 static float calculate_bw(nstime_t *start_time, nstime_t *stop_time, guint32 bytes)
625 if (memcmp(start_time, stop_time, sizeof(nstime_t)) != 0) {
626 float elapsed_ms = (((float)stop_time->secs - (float)start_time->secs) * 1000) +
627 (((float)stop_time->nsecs - (float)start_time->nsecs) / 1000000);
628 return ((bytes * 8) / elapsed_ms) / 1000;
636 /* (Re)draw the whole dialog window */
638 mac_lte_stat_draw(void *phs)
641 guint16 number_of_ues = 0;
644 /* Look up the statistics window */
645 mac_lte_stat_t *hs = (mac_lte_stat_t *)phs;
646 mac_lte_ep_t* list = hs->ep_list, *tmp = 0;
648 GtkListStore *ues_store;
649 GtkTreeSelection *sel;
654 g_snprintf(buff, sizeof(buff), "Max UL UEs/TTI: %u", hs->common_stats.max_ul_ues_in_tti);
655 gtk_label_set_text(GTK_LABEL(hs->ul_max_ues_per_tti), buff);
656 g_snprintf(buff, sizeof(buff), "Max DL UEs/TTI: %u", hs->common_stats.max_dl_ues_in_tti);
657 gtk_label_set_text(GTK_LABEL(hs->dl_max_ues_per_tti), buff);
659 /* Common channel data */
660 g_snprintf(buff, sizeof(buff), "BCH Frames: %u", hs->common_stats.bch_frames);
661 gtk_label_set_text(GTK_LABEL(hs->common_bch_frames), buff);
662 g_snprintf(buff, sizeof(buff), "BCH Bytes: %u", hs->common_stats.bch_bytes);
663 gtk_label_set_text(GTK_LABEL(hs->common_bch_bytes), buff);
664 g_snprintf(buff, sizeof(buff), "PCH Frames: %u", hs->common_stats.pch_frames);
665 gtk_label_set_text(GTK_LABEL(hs->common_pch_frames), buff);
666 g_snprintf(buff, sizeof(buff), "PCH Bytes: %u", hs->common_stats.pch_bytes);
667 gtk_label_set_text(GTK_LABEL(hs->common_pch_bytes), buff);
668 g_snprintf(buff, sizeof(buff), "RAR Frames: %u", hs->common_stats.rar_frames);
669 gtk_label_set_text(GTK_LABEL(hs->common_rar_frames), buff);
670 g_snprintf(buff, sizeof(buff), "RAR Entries: %u", hs->common_stats.rar_entries);
671 gtk_label_set_text(GTK_LABEL(hs->common_rar_entries), buff);
674 /* Per-UE table entries */
675 ues_store = GTK_LIST_STORE(gtk_tree_view_get_model(hs->ue_table));
677 /* Set title that shows how many UEs currently in table */
678 for (tmp = list; (tmp!=NULL); tmp=tmp->next, number_of_ues++);
679 g_snprintf(title, sizeof(title), "UL/DL-SCH data (%u entries - %u unique RNTIs, %u unique UEIds)",
680 number_of_ues, hs->number_of_rntis, hs->number_of_ueids);
681 gtk_frame_set_label(GTK_FRAME(hs->mac_lte_stat_ues_lb), title);
683 /* Update title to include number of UEs and frames */
684 g_snprintf(title, sizeof(title), "Wireshark: LTE MAC Traffic Statistics: %s (%u UEs, %u frames) (filter=\"%s\")",
685 cf_get_display_name(&cfile),
687 hs->common_stats.all_frames,
688 strlen(hs->filter) ? hs->filter : "none");
689 gtk_window_set_title(GTK_WINDOW(hs->mac_lte_stat_dlg_w), title);
692 for (tmp = list; tmp; tmp=tmp->next) {
694 /* Calculate bandwidth */
695 float UL_bw = calculate_bw(&tmp->stats.UL_time_start,
696 &tmp->stats.UL_time_stop,
697 tmp->stats.UL_total_bytes);
698 float DL_bw = calculate_bw(&tmp->stats.DL_time_start,
699 &tmp->stats.DL_time_stop,
700 tmp->stats.DL_total_bytes);
702 if (tmp->iter_valid != TRUE) {
703 /* Add to list control if not drawn this UE before */
704 gtk_list_store_append(ues_store, &tmp->iter);
705 tmp->iter_valid = TRUE;
708 /* Set each column for this row */
709 gtk_list_store_set(ues_store, &tmp->iter,
710 RNTI_COLUMN, tmp->stats.rnti,
712 (tmp->stats.rnti_type == C_RNTI) ? "C-RNTI" : "SPS-RNTI",
713 UEID_COLUMN, tmp->stats.ueid,
714 UL_FRAMES_COLUMN, tmp->stats.UL_frames,
715 UL_BYTES_COLUMN, tmp->stats.UL_total_bytes,
717 UL_PADDING_PERCENT_COLUMN,
718 tmp->stats.UL_total_bytes ?
719 (((float)tmp->stats.UL_padding_bytes / (float)tmp->stats.UL_raw_bytes) * 100.0) :
721 UL_RETX_FRAMES_COLUMN, tmp->stats.UL_retx_frames,
722 DL_FRAMES_COLUMN, tmp->stats.DL_frames,
723 DL_BYTES_COLUMN, tmp->stats.DL_total_bytes,
725 DL_CRC_FAILED_COLUMN, tmp->stats.DL_CRC_failures,
726 DL_CRC_HIGH_CODE_RATE_COLUMN, tmp->stats.DL_CRC_high_code_rate,
727 DL_CRC_PDSCH_LOST_COLUMN, tmp->stats.DL_CRC_PDSCH_lost,
728 DL_RETX_FRAMES_COLUMN, tmp->stats.DL_retx_frames,
734 if (hs->selected_rnti != 0) {
735 GtkTreeIter *ue_iter = NULL;
736 mac_lte_ep_t *ep = hs->ep_list;
738 if ((ep->stats.ueid == hs->selected_ueid) &&
739 (ep->stats.rnti == hs->selected_rnti)) {
745 if (ue_iter != NULL) {
747 gtk_tree_selection_select_iter(gtk_tree_view_get_selection(hs->ue_table),
752 /* If there is a UE selected, update its counters in details window */
753 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(hs->ue_table));
754 if (gtk_tree_selection_get_selected(sel, &model, &iter)) {
757 gtk_tree_model_get(model, &iter, TABLE_COLUMN, &ep, -1);
758 mac_lte_ue_details(ep, hs);
763 /* Compose and set appropriate display filter */
764 typedef enum Direction_t {UL_Only, DL_Only, UL_and_DL} Direction_t;
765 static void set_filter_expression(guint16 ueid,
767 Direction_t direction,
769 const gchar *DCTErrorSubstring,
772 #define MAX_FILTER_LEN 256
773 static char buffer[MAX_FILTER_LEN];
776 /* Create the filter expression */
780 if (strlen(DCTErrorSubstring) > 0) {
781 offset += g_snprintf(buffer+offset, MAX_FILTER_LEN-offset,
782 "(dct2000.error-comment and (dct2000.comment contains \"%s\")) or (",
786 offset += g_snprintf(buffer+offset, MAX_FILTER_LEN-offset,
787 "dct2000.error-comment or (");
791 /* Filter expression */
792 if (strlen(hs->filter)) {
793 offset += g_snprintf(buffer+offset, MAX_FILTER_LEN-offset, "%s and ", hs->filter);
799 offset += g_snprintf(buffer+offset, MAX_FILTER_LEN-offset, "(mac-lte.direction == 0) and ");
802 offset += g_snprintf(buffer+offset, MAX_FILTER_LEN-offset, "(mac-lte.direction == 1) and ");
809 offset += g_snprintf(buffer+offset, MAX_FILTER_LEN-offset,
810 "mac-lte.rnti == %u and mac-lte.ueid == %u",
813 /* Close parenthesis */
815 offset += g_snprintf(buffer+offset, MAX_FILTER_LEN-offset,
819 /* Set its value to our new string */
820 gtk_entry_set_text(GTK_ENTRY(main_display_filter_widget), buffer);
823 main_filter_packets(&cfile, buffer, TRUE);
826 /* Respond to UL filter button being clicked by building and using filter */
827 static void ul_filter_clicked(GtkWindow *win _U_, mac_lte_stat_t* hs)
829 GtkTreeSelection *sel;
833 /* If there is a UE selected, update its counters in details window */
834 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(hs->ue_table));
835 if (gtk_tree_selection_get_selected(sel, &model, &iter)) {
838 /* Get the UE details */
839 gtk_tree_model_get(model, &iter, TABLE_COLUMN, &ep, -1);
841 set_filter_expression(ep->stats.ueid, ep->stats.rnti, UL_Only,
842 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(hs->show_dct_errors_cb)),
843 gtk_entry_get_text(GTK_ENTRY(hs->dct_error_substring_te)),
848 /* Respond to DL filter button being clicked by building and using filter */
849 static void dl_filter_clicked(GtkWindow *win _U_, mac_lte_stat_t* hs)
851 GtkTreeSelection *sel;
855 /* If there is a UE selected, update its counters in details window */
856 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(hs->ue_table));
857 if (gtk_tree_selection_get_selected(sel, &model, &iter)) {
860 /* Get the UE details */
861 gtk_tree_model_get(model, &iter, TABLE_COLUMN, &ep, -1);
863 set_filter_expression(ep->stats.ueid, ep->stats.rnti, DL_Only,
864 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(hs->show_dct_errors_cb)),
865 gtk_entry_get_text(GTK_ENTRY(hs->dct_error_substring_te)),
871 /* Respond to UL/DL filter button being clicked by building and using filter */
872 static void uldl_filter_clicked(GtkWindow *win _U_, mac_lte_stat_t* hs)
874 GtkTreeSelection *sel;
878 /* If there is a UE selected, update its counters in details window */
879 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(hs->ue_table));
880 if (gtk_tree_selection_get_selected(sel, &model, &iter)) {
883 /* Get the UE details */
884 gtk_tree_model_get(model, &iter, TABLE_COLUMN, &ep, -1);
886 set_filter_expression(ep->stats.ueid, ep->stats.rnti, UL_and_DL,
887 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(hs->show_dct_errors_cb)),
888 gtk_entry_get_text(GTK_ENTRY(hs->dct_error_substring_te)),
895 /* What to do when a list item is selected/unselected */
896 static void mac_lte_select_cb(GtkTreeSelection *sel, gpointer data)
898 mac_lte_stat_t *hs = (mac_lte_stat_t *)data;
903 if (gtk_tree_selection_get_selected(sel, &model, &iter)) {
904 /* Show details of selected UE */
905 gtk_tree_model_get(model, &iter, TABLE_COLUMN, &ep, -1);
906 mac_lte_ue_details(ep, hs);
909 mac_lte_ue_details(NULL, hs);
913 /* When DCT errors check-box is toggled, enable substring controls accordingly */
914 static void mac_lte_dct_errors_cb(GtkTreeSelection *sel _U_, gpointer data)
916 mac_lte_stat_t *hs = (mac_lte_stat_t*)data;
917 guint8 show_dct_errors = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(hs->show_dct_errors_cb));
919 gtk_widget_set_sensitive(hs->dct_error_substring_lb, show_dct_errors);
920 gtk_widget_set_sensitive(hs->dct_error_substring_te, show_dct_errors);
924 /* Destroy the stats window */
925 static void win_destroy_cb(GtkWindow *win _U_, gpointer data)
927 mac_lte_stat_t *hs = (mac_lte_stat_t *)data;
929 protect_thread_critical_region();
930 remove_tap_listener(hs);
931 unprotect_thread_critical_region();
933 if (hs->mac_lte_stat_dlg_w != NULL) {
934 window_destroy(hs->mac_lte_stat_dlg_w);
935 hs->mac_lte_stat_dlg_w = NULL;
937 mac_lte_stat_reset(hs);
943 /* Create a new MAC LTE stats dialog */
944 static void gtk_mac_lte_stat_init(const char *optarg, void *userdata _U_)
947 const char *filter = NULL;
948 GString *error_string;
949 GtkWidget *ues_scrolled_window;
951 GtkWidget *top_level_vbox;
953 GtkWidget *system_row_hbox;
954 GtkWidget *common_row_hbox;
956 GtkWidget *selected_ue_hb;
958 GtkWidget *mac_lte_stat_system_lb;
959 GtkWidget *mac_lte_stat_common_channel_lb;
960 GtkWidget *mac_lte_stat_selected_ue_lb;
961 GtkWidget *selected_ue_vbox[NUM_CHANNEL_COLUMNS];
962 GtkWidget *selected_ue_column_titles[5];
964 GtkWidget *mac_lte_stat_filters_lb;
965 GtkWidget *filter_buttons_hb;
972 GtkTreeView *tree_view;
973 GtkCellRenderer *renderer;
974 GtkTreeViewColumn *column;
975 GtkTreeSelection *sel;
979 /* Check for a filter string */
980 if (strncmp(optarg, "mac-lte,stat,", 13) == 0) {
981 /* Skip those characters from filter to display */
982 filter = optarg + 13;
991 hs = g_malloc(sizeof(mac_lte_stat_t));
994 /* Copy filter (so can be used for window title at reset) */
996 hs->filter = g_strdup(filter);
1003 g_snprintf(title, sizeof(title), "Wireshark: LTE MAC Statistics: %s",
1004 cf_get_display_name(&cfile));
1006 /* Create top-level window */
1007 hs->mac_lte_stat_dlg_w = window_new_with_geom(GTK_WINDOW_TOPLEVEL, title, "LTE MAC Statistics");
1010 gtk_window_set_default_size(GTK_WINDOW(hs->mac_lte_stat_dlg_w), 750, 300);
1012 /* Will stack widgets vertically inside dlg */
1013 top_level_vbox = gtk_vbox_new(FALSE, 3); /* FALSE = not homogeneous */
1014 gtk_container_add(GTK_CONTAINER(hs->mac_lte_stat_dlg_w), top_level_vbox);
1016 gtk_container_set_border_width(GTK_CONTAINER(top_level_vbox), 6);
1017 gtk_widget_show(top_level_vbox);
1020 /**********************************************/
1022 /**********************************************/
1023 mac_lte_stat_system_lb = gtk_frame_new("System Data");
1025 /* Add max UEs/TTI counts in one row */
1026 system_row_hbox = gtk_hbox_new(FALSE, 0);
1027 gtk_container_add(GTK_CONTAINER(mac_lte_stat_system_lb), system_row_hbox);
1028 gtk_container_set_border_width(GTK_CONTAINER(system_row_hbox), 5);
1030 gtk_box_pack_start(GTK_BOX(top_level_vbox), mac_lte_stat_system_lb, FALSE, FALSE, 0);
1032 /* Create labels (that will hold label and counter value) */
1033 hs->ul_max_ues_per_tti = gtk_label_new("Max UL UEs/TTI:");
1034 gtk_misc_set_alignment(GTK_MISC(hs->ul_max_ues_per_tti), 0.0f, .5f);
1035 gtk_container_add(GTK_CONTAINER(system_row_hbox), hs->ul_max_ues_per_tti);
1036 gtk_widget_show(hs->ul_max_ues_per_tti);
1038 hs->dl_max_ues_per_tti = gtk_label_new("Max DL UEs/TTI:");
1039 gtk_misc_set_alignment(GTK_MISC(hs->dl_max_ues_per_tti), 0.0f, .5f);
1040 gtk_container_add(GTK_CONTAINER(system_row_hbox), hs->dl_max_ues_per_tti);
1041 gtk_widget_show(hs->dl_max_ues_per_tti);
1044 /**********************************************/
1045 /* Common Channel data */
1046 /**********************************************/
1047 mac_lte_stat_common_channel_lb = gtk_frame_new("Common Channel Data");
1049 /* Will add BCH and PCH counters into one row */
1050 common_row_hbox = gtk_hbox_new(FALSE, 0);
1051 gtk_container_add(GTK_CONTAINER(mac_lte_stat_common_channel_lb), common_row_hbox);
1052 gtk_container_set_border_width(GTK_CONTAINER(common_row_hbox), 5);
1054 gtk_box_pack_start(GTK_BOX(top_level_vbox), mac_lte_stat_common_channel_lb, FALSE, FALSE, 0);
1056 /* Create labels (that will hold label and counter value) */
1057 hs->common_bch_frames = gtk_label_new("BCH Frames:");
1058 gtk_misc_set_alignment(GTK_MISC(hs->common_bch_frames), 0.0f, .5f);
1059 gtk_container_add(GTK_CONTAINER(common_row_hbox), hs->common_bch_frames);
1060 gtk_widget_show(hs->common_bch_frames);
1062 hs->common_bch_bytes = gtk_label_new("BCH Bytes:");
1063 gtk_misc_set_alignment(GTK_MISC(hs->common_bch_bytes), 0.0f, .5f);
1064 gtk_container_add(GTK_CONTAINER(common_row_hbox), hs->common_bch_bytes);
1065 gtk_widget_show(hs->common_bch_bytes);
1067 hs->common_pch_frames = gtk_label_new("PCH Frames:");
1068 gtk_misc_set_alignment(GTK_MISC(hs->common_pch_frames), 0.0f, .5f);
1069 gtk_container_add(GTK_CONTAINER(common_row_hbox), hs->common_pch_frames);
1070 gtk_widget_show(hs->common_pch_frames);
1072 hs->common_pch_bytes = gtk_label_new("PCH Bytes:");
1073 gtk_misc_set_alignment(GTK_MISC(hs->common_pch_bytes), 0.0f, .5f);
1074 gtk_container_add(GTK_CONTAINER(common_row_hbox), hs->common_pch_bytes);
1075 gtk_widget_show(hs->common_pch_bytes);
1077 hs->common_rar_frames = gtk_label_new("RAR Frames:");
1078 gtk_misc_set_alignment(GTK_MISC(hs->common_rar_frames), 0.0f, .5f);
1079 gtk_container_add(GTK_CONTAINER(common_row_hbox), hs->common_rar_frames);
1080 gtk_widget_show(hs->common_rar_frames);
1082 hs->common_rar_entries = gtk_label_new("RAR Entries:");
1083 gtk_misc_set_alignment(GTK_MISC(hs->common_rar_entries), 0.0f, .5f);
1084 gtk_container_add(GTK_CONTAINER(common_row_hbox), hs->common_rar_entries);
1085 gtk_widget_show(hs->common_rar_entries);
1087 /**********************************************/
1088 /* UL/DL-SCH data */
1089 /**********************************************/
1091 hs->mac_lte_stat_ues_lb = gtk_frame_new("UL/DL-SCH Data (0 UEs)");
1092 ues_vb = gtk_vbox_new(FALSE, 0);
1093 gtk_container_add(GTK_CONTAINER(hs->mac_lte_stat_ues_lb), ues_vb);
1094 gtk_container_set_border_width(GTK_CONTAINER(ues_vb), 5);
1096 ues_scrolled_window = scrolled_window_new(NULL, NULL);
1097 gtk_box_pack_start(GTK_BOX(ues_vb), ues_scrolled_window, TRUE, TRUE, 0);
1098 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(ues_scrolled_window),
1101 /* Create the table of UE data */
1102 store = gtk_list_store_new(NUM_UE_COLUMNS, G_TYPE_INT, G_TYPE_STRING, G_TYPE_INT,
1103 G_TYPE_INT, G_TYPE_INT, G_TYPE_FLOAT, G_TYPE_FLOAT, G_TYPE_INT, /* UL */
1104 G_TYPE_INT, G_TYPE_INT, G_TYPE_FLOAT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, /* DL */
1106 hs->ue_table = GTK_TREE_VIEW(tree_view_new(GTK_TREE_MODEL(store)));
1107 gtk_container_add(GTK_CONTAINER (ues_scrolled_window), GTK_WIDGET(hs->ue_table));
1108 g_object_unref(G_OBJECT(store));
1110 tree_view = hs->ue_table;
1111 gtk_tree_view_set_headers_visible(tree_view, TRUE);
1112 gtk_tree_view_set_headers_clickable(tree_view, TRUE);
1114 /* Create the titles for each column of the per-UE table */
1115 for (i = 0; i < TABLE_COLUMN; i++) {
1116 renderer = gtk_cell_renderer_text_new();
1117 column = gtk_tree_view_column_new_with_attributes(ue_titles[i], renderer,
1119 gtk_tree_view_column_set_sort_column_id(column, i);
1122 /* Expand first column (RNTI, which is Key) */
1123 gtk_tree_view_column_set_expand(column, TRUE);
1125 /* For other columns, set all of the free space to be on the left */
1126 g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);
1128 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
1129 gtk_tree_view_column_set_resizable(column, TRUE);
1130 gtk_tree_view_append_column(tree_view, column);
1133 /* Set callback function for selecting a row in the UE table */
1134 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(hs->ue_table));
1135 gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
1136 g_signal_connect(sel, "changed", G_CALLBACK(mac_lte_select_cb), hs);
1138 gtk_box_pack_start(GTK_BOX(top_level_vbox), hs->mac_lte_stat_ues_lb, TRUE, TRUE, 0);
1141 /**********************************************/
1142 /* Details of selected UE */
1143 /**********************************************/
1145 mac_lte_stat_selected_ue_lb = gtk_frame_new("Selected UE details");
1147 selected_ue_hb = gtk_hbox_new(FALSE, 6);
1148 gtk_container_add(GTK_CONTAINER(mac_lte_stat_selected_ue_lb), selected_ue_hb);
1149 gtk_container_set_border_width(GTK_CONTAINER(selected_ue_hb), 5);
1151 /********************************/
1152 /* First (row titles) column */
1153 selected_ue_vbox[0] = gtk_vbox_new(FALSE, 0);
1154 gtk_container_add(GTK_CONTAINER(selected_ue_hb), selected_ue_vbox[0]);
1156 selected_ue_column_titles[0] = gtk_label_new("");
1157 gtk_misc_set_alignment(GTK_MISC(selected_ue_column_titles[0]), 0.0f, 0.0f);
1158 gtk_container_add(GTK_CONTAINER(selected_ue_vbox[0]), selected_ue_column_titles[0]);
1160 for (n=1; n < 5; n++) {
1161 selected_ue_column_titles[n] = gtk_label_new(selected_ue_row_names[n-1]);
1162 gtk_misc_set_alignment(GTK_MISC(selected_ue_column_titles[n]), 0.0f, 0.0f);
1163 gtk_container_add(GTK_CONTAINER(selected_ue_vbox[0]), selected_ue_column_titles[n]);
1164 gtk_widget_show(selected_ue_column_titles[n]);
1168 /*************************/
1170 for (i=CCCH_COLUMN; i < NUM_CHANNEL_COLUMNS; i++) {
1171 selected_ue_vbox[i] = gtk_vbox_new(FALSE, 0);
1172 gtk_container_add(GTK_CONTAINER(selected_ue_hb), selected_ue_vbox[i]);
1175 hs->selected_ue_column_entry[i][0] = gtk_label_new(channel_titles[i-1]);
1176 gtk_misc_set_alignment(GTK_MISC(hs->selected_ue_column_entry[i][0]), 0.5f, 0.0f);
1177 gtk_container_add(GTK_CONTAINER(selected_ue_vbox[i]), hs->selected_ue_column_entry[i][0]);
1179 /* Counts for this channel */
1180 for (n=1; n < 5; n++) {
1181 hs->selected_ue_column_entry[i][n] = gtk_label_new("0");
1182 gtk_misc_set_alignment(GTK_MISC(hs->selected_ue_column_entry[i][n]), 1.0f, 0.0f);
1183 gtk_container_add(GTK_CONTAINER(selected_ue_vbox[i]), hs->selected_ue_column_entry[i][n]);
1184 gtk_widget_show(hs->selected_ue_column_entry[i][n]);
1188 gtk_box_pack_start(GTK_BOX(top_level_vbox), mac_lte_stat_selected_ue_lb, FALSE, FALSE, 0);
1191 /**************************************/
1192 /* Filter on RNTI/UEId */
1193 /**************************************/
1194 mac_lte_stat_filters_lb = gtk_frame_new("Filter on UE");
1196 /* Horizontal row of filter controls */
1197 filter_buttons_hb = gtk_hbox_new(FALSE, 6);
1198 gtk_container_add(GTK_CONTAINER(mac_lte_stat_filters_lb), filter_buttons_hb);
1199 gtk_container_set_border_width(GTK_CONTAINER(filter_buttons_hb), 2);
1201 /* Add filters box to top-level window */
1202 gtk_box_pack_start(GTK_BOX(top_level_vbox), mac_lte_stat_filters_lb, FALSE, FALSE, 0);
1204 /* Filter buttons */
1207 hs->ul_filter_bt = gtk_button_new_with_label("Set UL display filter on selected this RNTI / UEId");
1208 gtk_box_pack_start(GTK_BOX(filter_buttons_hb), hs->ul_filter_bt, FALSE, FALSE, 0);
1209 g_signal_connect(hs->ul_filter_bt, "clicked", G_CALLBACK(ul_filter_clicked), hs);
1210 gtk_widget_set_sensitive(hs->ul_filter_bt, FALSE);
1211 gtk_widget_show(hs->ul_filter_bt);
1212 gtk_widget_set_tooltip_text(hs->ul_filter_bt,
1213 "Generate and set a filter showing only UL frames with selected RNTI and UEId");
1216 hs->dl_filter_bt = gtk_button_new_with_label("Set DL display filter on selected this RNTI / UEId");
1217 gtk_box_pack_start(GTK_BOX(filter_buttons_hb), hs->dl_filter_bt, FALSE, FALSE, 0);
1218 g_signal_connect(hs->dl_filter_bt, "clicked", G_CALLBACK(dl_filter_clicked), hs);
1219 gtk_widget_set_sensitive(hs->dl_filter_bt, FALSE);
1220 gtk_widget_show(hs->dl_filter_bt);
1221 gtk_widget_set_tooltip_text(hs->dl_filter_bt,
1222 "Generate and set a filter showing only DL frames with selected RNTI and UEId");
1225 hs->uldl_filter_bt = gtk_button_new_with_label("Set UL / DL display filter on selected this RNTI / UEId");
1226 gtk_box_pack_start(GTK_BOX(filter_buttons_hb), hs->uldl_filter_bt, FALSE, FALSE, 0);
1227 g_signal_connect(hs->uldl_filter_bt, "clicked", G_CALLBACK(uldl_filter_clicked), hs);
1228 gtk_widget_set_sensitive(hs->uldl_filter_bt, FALSE);
1229 gtk_widget_show(hs->uldl_filter_bt);
1230 gtk_widget_set_tooltip_text(hs->uldl_filter_bt,
1231 "Generate and set a filter showing only frames with selected RNTI and UEId");
1234 /* Allow DCT errors to be shown... */
1235 hs->show_dct_errors_cb = gtk_check_button_new_with_mnemonic("Show DCT2000 error strings");
1236 gtk_container_add(GTK_CONTAINER(filter_buttons_hb), hs->show_dct_errors_cb);
1237 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(hs->show_dct_errors_cb), FALSE);
1238 g_signal_connect(hs->show_dct_errors_cb, "toggled", G_CALLBACK(mac_lte_dct_errors_cb), hs);
1239 gtk_widget_set_tooltip_text(hs->show_dct_errors_cb, "When checked, generated filters will "
1240 "include DCT2000 error strings");
1241 /* Initially disabled */
1242 gtk_widget_set_sensitive(hs->show_dct_errors_cb, FALSE);
1244 /* ... optionally limited by a substring */
1245 hs->dct_error_substring_lb = gtk_label_new("...containing");
1246 gtk_box_pack_start(GTK_BOX(filter_buttons_hb), hs->dct_error_substring_lb, FALSE, FALSE, 0);
1247 gtk_widget_show(hs->dct_error_substring_lb);
1248 gtk_widget_set_sensitive(hs->dct_error_substring_lb, FALSE);
1250 hs->dct_error_substring_te = gtk_entry_new();
1251 gtk_box_pack_start(GTK_BOX(filter_buttons_hb), hs->dct_error_substring_te, FALSE, FALSE, 0);
1252 gtk_widget_show(hs->dct_error_substring_te);
1253 gtk_widget_set_sensitive(hs->dct_error_substring_te, FALSE);
1254 gtk_widget_set_tooltip_text(hs->dct_error_substring_te,
1255 "If given, only match error strings containing this substring");
1258 /**********************************************/
1259 /* Register the tap listener */
1260 /**********************************************/
1262 error_string = register_tap_listener("mac-lte", hs,
1265 mac_lte_stat_packet,
1268 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", error_string->str);
1269 g_string_free(error_string, TRUE);
1275 /************************************/
1277 /************************************/
1279 bbox = dlg_button_row_new (GTK_STOCK_CLOSE, GTK_STOCK_HELP, NULL);
1280 gtk_box_pack_end (GTK_BOX(top_level_vbox), bbox, FALSE, FALSE, 0);
1282 /* Add the close button */
1283 close_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CLOSE);
1284 window_set_cancel_button(hs->mac_lte_stat_dlg_w, close_bt, window_cancel_button_cb);
1286 help_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
1287 g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_STATS_LTE_MAC_TRAFFIC_DIALOG);
1290 g_signal_connect(hs->mac_lte_stat_dlg_w, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
1291 g_signal_connect(hs->mac_lte_stat_dlg_w, "destroy", G_CALLBACK(win_destroy_cb), hs);
1293 /* Show the window */
1294 gtk_widget_show_all(hs->mac_lte_stat_dlg_w);
1295 window_present(hs->mac_lte_stat_dlg_w);
1298 cf_retap_packets(&cfile);
1299 gdk_window_raise(gtk_widget_get_window(hs->mac_lte_stat_dlg_w));
1303 static tap_param mac_lte_stat_params[] = {
1304 { PARAM_FILTER, "Filter", NULL }
1307 static tap_param_dlg mac_lte_stat_dlg = {
1310 gtk_mac_lte_stat_init,
1312 G_N_ELEMENTS(mac_lte_stat_params),
1317 /* Register this tap listener (need void on own so line register function found) */
1319 register_tap_listener_mac_lte_stat(void)
1321 register_dfilter_stat(&mac_lte_stat_dlg, "_LTE/_MAC", REGISTER_STAT_GROUP_TELEPHONY);
1324 #ifdef MAIN_MENU_USE_UIMANAGER
1325 void mac_lte_stat_cb(GtkAction *action, gpointer user_data _U_)
1327 tap_param_dlg_cb(action, &mac_lte_stat_dlg);