1 /* Routines for LTE MAC disassembly
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.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 #include <epan/packet.h>
29 #include <epan/expert.h>
30 #include <epan/prefs.h>
34 #include "packet-mac-lte.h"
35 #include "packet-rlc-lte.h"
39 * 3GPP TS 36.321 Evolved Universal Terrestrial Radio Access (E-UTRA)
40 * Medium Access Control (MAC) protocol specification (Release 8)
46 - add a preference so that padding can be verified against an expected pattern?
49 /* Initialize the protocol and registered fields. */
50 int proto_mac_lte = -1;
52 static int mac_lte_tap = -1;
54 /* Decoding context */
55 static int hf_mac_lte_context = -1;
56 static int hf_mac_lte_context_radio_type = -1;
57 static int hf_mac_lte_context_direction = -1;
58 static int hf_mac_lte_context_rnti = -1;
59 static int hf_mac_lte_context_rnti_type = -1;
60 static int hf_mac_lte_context_ueid = -1;
61 static int hf_mac_lte_context_subframe_number = -1;
62 static int hf_mac_lte_context_grant_subframe_number = -1;
63 static int hf_mac_lte_context_predefined_frame = -1;
64 static int hf_mac_lte_context_length = -1;
65 static int hf_mac_lte_context_ul_grant_size = -1;
66 static int hf_mac_lte_context_bch_transport_channel = -1;
67 static int hf_mac_lte_context_retx_count = -1;
68 static int hf_mac_lte_context_crc_status = -1;
69 static int hf_mac_lte_context_rapid = -1;
70 static int hf_mac_lte_context_rach_attempt_number = -1;
72 /* Extra PHY context */
73 static int hf_mac_lte_context_phy_ul = -1;
74 static int hf_mac_lte_context_phy_ul_modulation_type = -1;
75 static int hf_mac_lte_context_phy_ul_tbs_index = -1;
76 static int hf_mac_lte_context_phy_ul_resource_block_length = -1;
77 static int hf_mac_lte_context_phy_ul_resource_block_start = -1;
79 static int hf_mac_lte_context_phy_dl = -1;
80 static int hf_mac_lte_context_phy_dl_dci_format = -1;
81 static int hf_mac_lte_context_phy_dl_resource_allocation_type = -1;
82 static int hf_mac_lte_context_phy_dl_aggregation_level = -1;
83 static int hf_mac_lte_context_phy_dl_mcs_index = -1;
84 static int hf_mac_lte_context_phy_dl_redundancy_version_index = -1;
85 static int hf_mac_lte_context_phy_dl_retx = -1;
86 static int hf_mac_lte_context_phy_dl_resource_block_length = -1;
87 static int hf_mac_lte_context_phy_dl_crc_status = -1;
90 /* Out-of-band events */
91 static int hf_mac_lte_oob_send_preamble = -1;
92 static int hf_mac_lte_oob_send_sr = -1;
93 static int hf_mac_lte_oob_sr_failure = -1;
95 /* MAC SCH header fields */
96 static int hf_mac_lte_ulsch = -1;
97 static int hf_mac_lte_ulsch_header = -1;
98 static int hf_mac_lte_dlsch = -1;
99 static int hf_mac_lte_dlsch_header = -1;
100 static int hf_mac_lte_sch_subheader = -1;
102 static int hf_mac_lte_sch_reserved = -1;
103 static int hf_mac_lte_dlsch_lcid = -1;
104 static int hf_mac_lte_ulsch_lcid = -1;
105 static int hf_mac_lte_sch_extended = -1;
106 static int hf_mac_lte_sch_format = -1;
107 static int hf_mac_lte_sch_length = -1;
109 static int hf_mac_lte_sch_header_only = -1;
112 static int hf_mac_lte_sch_sdu = -1;
113 static int hf_mac_lte_bch_pdu = -1;
114 static int hf_mac_lte_pch_pdu = -1;
115 static int hf_mac_lte_predefined_pdu = -1;
116 static int hf_mac_lte_raw_pdu = -1;
117 static int hf_mac_lte_padding_data = -1;
118 static int hf_mac_lte_padding_length = -1;
122 static int hf_mac_lte_rar = -1;
123 static int hf_mac_lte_rar_headers = -1;
124 static int hf_mac_lte_rar_header = -1;
125 static int hf_mac_lte_rar_extension = -1;
126 static int hf_mac_lte_rar_t = -1;
127 static int hf_mac_lte_rar_bi = -1;
128 static int hf_mac_lte_rar_rapid = -1;
129 static int hf_mac_lte_rar_reserved = -1;
130 static int hf_mac_lte_rar_body = -1;
131 static int hf_mac_lte_rar_reserved2 = -1;
132 static int hf_mac_lte_rar_ta = -1;
133 static int hf_mac_lte_rar_ul_grant = -1;
134 static int hf_mac_lte_rar_ul_grant_hopping = -1;
135 static int hf_mac_lte_rar_ul_grant_fsrba = -1;
136 static int hf_mac_lte_rar_ul_grant_tmcs = -1;
137 static int hf_mac_lte_rar_ul_grant_tcsp = -1;
138 static int hf_mac_lte_rar_ul_grant_ul_delay = -1;
139 static int hf_mac_lte_rar_ul_grant_cqi_request = -1;
140 static int hf_mac_lte_rar_temporary_crnti = -1;
142 /* Common channel control values */
143 static int hf_mac_lte_control_bsr = -1;
144 static int hf_mac_lte_control_bsr_lcg_id = -1;
145 static int hf_mac_lte_control_short_bsr_buffer_size = -1;
146 static int hf_mac_lte_control_long_bsr_buffer_size_0 = -1;
147 static int hf_mac_lte_control_long_bsr_buffer_size_1 = -1;
148 static int hf_mac_lte_control_long_bsr_buffer_size_2 = -1;
149 static int hf_mac_lte_control_long_bsr_buffer_size_3 = -1;
150 static int hf_mac_lte_control_crnti = -1;
151 static int hf_mac_lte_control_timing_advance = -1;
152 static int hf_mac_lte_control_timing_advance_reserved = -1;
153 static int hf_mac_lte_control_ue_contention_resolution = -1;
154 static int hf_mac_lte_control_ue_contention_resolution_identity = -1;
155 static int hf_mac_lte_control_ue_contention_resolution_msg3 = -1;
156 static int hf_mac_lte_control_ue_contention_resolution_msg3_matched = -1;
157 static int hf_mac_lte_control_ue_contention_resolution_time_since_msg3 = -1;
158 static int hf_mac_lte_control_power_headroom = -1;
159 static int hf_mac_lte_control_power_headroom_reserved = -1;
160 static int hf_mac_lte_control_power_headroom_level = -1;
161 static int hf_mac_lte_control_padding = -1;
163 static int hf_mac_lte_suspected_dl_retx_original_frame = -1;
165 static int hf_mac_lte_ul_harq_resend_original_frame = -1;
167 static int hf_mac_lte_grant_answering_sr = -1;
168 static int hf_mac_lte_failure_answering_sr = -1;
169 static int hf_mac_lte_sr_leading_to_failure = -1;
170 static int hf_mac_lte_sr_leading_to_grant = -1;
171 static int hf_mac_lte_sr_invalid_event = -1;
172 static int hf_mac_lte_sr_time_since_request = -1;
173 static int hf_mac_lte_sr_time_until_answer = -1;
177 static int ett_mac_lte = -1;
178 static int ett_mac_lte_context = -1;
179 static int ett_mac_lte_phy_context = -1;
180 static int ett_mac_lte_ulsch_header = -1;
181 static int ett_mac_lte_dlsch_header = -1;
182 static int ett_mac_lte_sch_subheader = -1;
183 static int ett_mac_lte_rar_headers = -1;
184 static int ett_mac_lte_rar_header = -1;
185 static int ett_mac_lte_rar_body = -1;
186 static int ett_mac_lte_rar_ul_grant = -1;
187 static int ett_mac_lte_bsr = -1;
188 static int ett_mac_lte_bch = -1;
189 static int ett_mac_lte_pch = -1;
190 static int ett_mac_lte_contention_resolution = -1;
191 static int ett_mac_lte_power_headroom = -1;
192 static int ett_mac_lte_oob = -1;
195 /* Constants and value strings */
197 static const value_string radio_type_vals[] =
205 static const value_string direction_vals[] =
207 { DIRECTION_UPLINK, "Uplink"},
208 { DIRECTION_DOWNLINK, "Downlink"},
213 static const value_string rnti_type_vals[] =
215 { NO_RNTI, "NO-RNTI"},
217 { RA_RNTI, "RA-RNTI"},
219 { SI_RNTI, "SI-RNTI"},
220 { SPS_RNTI, "SPS-RNTI"},
224 static const value_string bch_transport_channel_vals[] =
226 { SI_RNTI, "DL-SCH"},
231 static const value_string crc_status_vals[] =
239 static const value_string dci_format_vals[] =
253 static const value_string aggregation_level_vals[] =
262 static const value_string modulation_type_vals[] =
271 #define UE_CONTENTION_RESOLUTION_IDENTITY_LCID 0x1c
272 #define TIMING_ADVANCE_LCID 0x1d
273 #define DRX_COMMAND_LCID 0x1e
274 #define PADDING_LCID 0x1f
276 static const value_string dlsch_lcid_vals[] =
289 { UE_CONTENTION_RESOLUTION_IDENTITY_LCID, "UE Contention Resolution Identity"},
290 { TIMING_ADVANCE_LCID , "Timing Advance"},
291 { DRX_COMMAND_LCID , "DRX Command"},
292 { PADDING_LCID , "Padding" },
296 #define POWER_HEADROOM_REPORT_LCID 0x1a
297 #define CRNTI_LCID 0x1b
298 #define TRUNCATED_BSR_LCID 0x1c
299 #define SHORT_BSR_LCID 0x1d
300 #define LONG_BSR_LCID 0x1e
302 static const value_string ulsch_lcid_vals[] =
315 { POWER_HEADROOM_REPORT_LCID, "Power Headroom Report"},
316 { CRNTI_LCID, "C-RNTI"},
317 { TRUNCATED_BSR_LCID, "Truncated BSR"},
318 { SHORT_BSR_LCID, "Short BSR"},
319 { LONG_BSR_LCID, "Long BSR"},
320 { PADDING_LCID, "Padding" },
325 static const value_string format_vals[] =
327 { 0, "Data length is < 128 bytes"},
328 { 1, "Data length is >= 128 bytes"},
333 static const value_string rar_type_vals[] =
335 { 0, "Backoff Indicator present"},
336 { 1, "RAPID present"},
341 static const value_string rar_bi_vals[] =
360 static const value_string buffer_size_vals[] =
363 { 1, "0 < BS <= 10"},
364 { 2, "10 < BS <= 12"},
365 { 3, "12 < BS <= 14"},
366 { 4, "14 < BS <= 17"},
367 { 5, "17 < BS <= 19"},
368 { 6, "19 < BS <= 22"},
369 { 7, "22 < BS <= 26"},
370 { 8, "26 < BS <= 31"},
371 { 9, "31 < BS <= 36"},
372 { 10, "36 < BS <= 42"},
373 { 11, "42 < BS <= 49"},
374 { 12, "49 < BS <= 57"},
375 { 13, "47 < BS <= 67"},
376 { 14, "67 < BS <= 78"},
377 { 15, "78 < BS <= 91"},
378 { 16, "91 < BS <= 107"},
379 { 17, "107 < BS <= 125"},
380 { 18, "125 < BS <= 146"},
381 { 19, "146 < BS <= 171"},
382 { 20, "171 < BS <= 200"},
383 { 21, "200 < BS <= 234"},
384 { 22, "234 < BS <= 274"},
385 { 23, "274 < BS <= 321"},
386 { 24, "321 < BS <= 376"},
387 { 25, "376 < BS <= 440"},
388 { 26, "440 < BS <= 515"},
389 { 27, "515 < BS <= 603"},
390 { 28, "603 < BS <= 706"},
391 { 29, "706 < BS <= 826"},
392 { 30, "826 < BS <= 967"},
393 { 31, "967 < BS <= 1132"},
394 { 32, "1132 < BS <= 1326"},
395 { 33, "1326 < BS <= 1552"},
396 { 34, "1552 < BS <= 1817"},
397 { 35, "1817 < BS <= 2127"},
398 { 36, "2127 < BS <= 2490"},
399 { 37, "2490 < BS <= 2915"},
400 { 38, "2915 < BS <= 3413"},
401 { 39, "3413 < BS <= 3995"},
402 { 40, "3995 < BS <= 4677"},
403 { 41, "4677 < BS <= 5476"},
404 { 42, "5476 < BS <= 6411"},
405 { 43, "6411 < BS <= 7505"},
406 { 44, "7505 < BS <= 8787"},
407 { 45, "8787 < BS <= 10276"},
408 { 46, "10287 < BS <= 12043"},
409 { 47, "12043 < BS <= 14099"},
410 { 48, "14099 < BS <= 16507"},
411 { 49, "16507 < BS <= 19325"},
412 { 50, "19325 < BS <= 22624"},
413 { 51, "22624 < BS <= 26487"},
414 { 52, "26487 < BS <= 31009"},
415 { 53, "31009 < BS <= 36304"},
416 { 54, "36304 < BS <= 42502"},
417 { 55, "42502 < BS <= 49759"},
418 { 56, "49759 < BS <= 58255"},
419 { 57, "58255 < BS <= 68201"},
420 { 58, "68201 < BS <= 79846"},
421 { 59, "79846 < BS <= 93479"},
422 { 60, "93479 < BS <= 109439"},
423 { 61, "109439 < BS <= 128125"},
424 { 62, "128125 < BS <= 150000"},
425 { 63, "BS > 150000"},
429 static const value_string power_headroom_size_vals[] =
431 { 0, "-23 <= PH < -22"},
432 { 1, "-22 <= PH < -21"},
433 { 2, "-21 <= PH < -20"},
434 { 3, "-20 <= PH < -19"},
435 { 4, "-19 <= PH < -18"},
436 { 5, "-18 <= PH < -17"},
437 { 6, "-17 <= PH < -16"},
438 { 7, "-16 <= PH < -15"},
439 { 8, "-15 <= PH < -14"},
440 { 9, "-14 <= PH < -13"},
441 { 10, "-13 <= PH < -12"},
442 { 11, "-12 <= PH < -11"},
443 { 12, "-11 <= PH < -10"},
444 { 13, "-10 <= PH < -9"},
445 { 14, "-9 <= PH < -8"},
446 { 15, "-8 <= PH < -7"},
447 { 16, "-7 <= PH < -6"},
448 { 17, "-6 <= PH < -5"},
449 { 18, "-5 <= PH < -4"},
450 { 19, "-4 <= PH < -3"},
451 { 20, "-3 <= PH < -2"},
452 { 21, "-2 <= PH < -1"},
453 { 22, "-1 <= PH < 0"},
454 { 23, "0 <= PH < 1"},
455 { 24, "1 <= PH < 2"},
456 { 25, "2 <= PH < 3"},
457 { 26, "3 <= PH < 4"},
458 { 27, "4 <= PH < 5"},
459 { 28, "5 <= PH < 6"},
460 { 29, "6 <= PH < 7"},
461 { 30, "7 <= PH < 8"},
462 { 31, "8 <= PH < 9"},
463 { 32, "9 <= PH < 10"},
464 { 33, "10 <= PH < 11"},
465 { 34, "11 <= PH < 12"},
466 { 35, "12 <= PH < 13"},
467 { 36, "13 <= PH < 14"},
468 { 37, "14 <= PH < 15"},
469 { 38, "15 <= PH < 16"},
470 { 39, "16 <= PH < 17"},
471 { 40, "17 <= PH < 18"},
472 { 41, "18 <= PH < 19"},
473 { 42, "19 <= PH < 20"},
474 { 43, "20 <= PH < 21"},
475 { 44, "21 <= PH < 22"},
476 { 45, "22 <= PH < 23"},
477 { 46, "23 <= PH < 24"},
478 { 47, "24 <= PH < 25"},
479 { 48, "25 <= PH < 26"},
480 { 49, "26 <= PH < 27"},
481 { 50, "27 <= PH < 28"},
482 { 51, "28 <= PH < 29"},
483 { 52, "29 <= PH < 30"},
484 { 53, "30 <= PH < 31"},
485 { 54, "31 <= PH < 32"},
486 { 55, "32 <= PH < 33"},
487 { 56, "33 <= PH < 34"},
488 { 57, "34 <= PH < 35"},
489 { 58, "34 <= PH < 36"},
490 { 59, "36 <= PH < 37"},
491 { 60, "37 <= PH < 38"},
492 { 61, "38 <= PH < 39"},
493 { 62, "39 <= PH < 40"},
498 static const value_string header_only_vals[] =
500 { 0, "MAC PDU Headers and body present"},
501 { 1, "MAC PDU Headers only"},
505 static const value_string predefined_frame_vals[] =
507 { 0, "Real MAC PDU present - will dissect"},
508 { 1, "Predefined frame present - will not dissect"},
513 /**************************************************************************/
514 /* Preferences state */
515 /**************************************************************************/
517 /* If this PDU has been NACK'd (by HARQ) more than a certain number of times,
518 we trigger an expert warning. */
519 static gint global_mac_lte_retx_counter_trigger = 3;
521 /* By default try to decode transparent data (BCH, PCH and CCCH) data using LTE RRC dissector */
522 static gboolean global_mac_lte_attempt_rrc_decode = TRUE;
524 /* Whether should attempt to dissect frames failing CRC check */
525 static gboolean global_mac_lte_dissect_crc_failures = FALSE;
527 /* Whether should attempt to decode lcid 1&2 SDUs as srb1/2 (i.e. AM RLC) */
528 static gboolean global_mac_lte_attempt_srb_decode = TRUE;
530 /* Whether should attempt to track UL HARQ resends */
531 static gboolean global_mac_lte_attempt_ul_harq_resend_track = TRUE;
533 /* Threshold for warning in expert info about high BSR values */
534 static gint global_mac_lte_bsr_warn_threshold = 50; /* default is 19325 -> 22624 */
536 /* Whether or not to track SRs and related frames */
537 static gboolean global_mac_lte_track_sr = TRUE;
539 /* Which layer info to show in the info column */
541 ShowPHYLayer, ShowMACLayer, ShowRLCLayer
544 static gint global_mac_lte_layer_to_show = (gint)ShowRLCLayer;
545 static guint8 s_number_of_rlc_pdus_shown = 0;
548 /***********************************************************************/
549 /* How to dissect lcid 3-10 (presume drb logical channels) */
551 static const value_string drb_lcid_vals[] = {
563 typedef enum rlc_channel_type_t {
569 } rlc_channel_type_t;
571 static const value_string rlc_channel_type_vals[] = {
573 { rlcUM5 , "UM, SN Len=5"},
574 { rlcUM10, "UM, SN Len=10"},
581 typedef struct drb_mapping_t {
584 rlc_channel_type_t channel_type;
585 } lcid_drb_mapping_t;
588 static lcid_drb_mapping_t *lcid_drb_mappings = NULL;
589 static guint num_lcid_drb_mappings = 0;
591 UAT_VS_DEF(lcid_drb_mappings, lcid, lcid_drb_mapping_t, 3, "LCID 3")
592 UAT_DEC_CB_DEF(lcid_drb_mappings, drbid, lcid_drb_mapping_t)
593 UAT_VS_DEF(lcid_drb_mappings, channel_type, lcid_drb_mapping_t, 2, "AM")
596 static uat_t* lcid_drb_mappings_uat;
598 extern int proto_rlc_lte;
600 /***************************************************************/
604 /***************************************************************/
605 /* Keeping track of Msg3 bodies so they can be compared with */
606 /* Contention Resolution bodies. */
608 typedef struct Msg3Data {
615 /* This table stores (RNTI -> Msg3Data*). Will be populated when
616 Msg3 frames are first read. */
617 static GHashTable *mac_lte_msg3_hash = NULL;
619 /* Hash table functions for mac_lte_msg3_hash. Hash is just the (RNTI) key */
620 static gint mac_lte_rnti_hash_equal(gconstpointer v, gconstpointer v2)
625 static guint mac_lte_rnti_hash_func(gconstpointer v)
627 return GPOINTER_TO_UINT(v);
632 typedef enum ContentionResolutionStatus {
636 } ContentionResolutionStatus;
638 typedef struct ContentionResolutionResult {
639 ContentionResolutionStatus status;
642 } ContentionResolutionResult;
645 /* This table stores (CRFrameNum -> CRResult). It is assigned during the first
646 pass and used thereafter */
647 static GHashTable *mac_lte_cr_result_hash = NULL;
649 /* Hash table functions for mac_lte_cr_result_hash. Hash is just the (framenum) key */
650 static gint mac_lte_framenum_hash_equal(gconstpointer v, gconstpointer v2)
655 static guint mac_lte_framenum_hash_func(gconstpointer v)
657 return GPOINTER_TO_UINT(v);
660 /**************************************************************************/
664 /****************************************************************/
665 /* Keeping track of last DL frames per C-RNTI so can guess when */
666 /* there has been a HARQ retransmission */
668 /* Could be bigger, but more than enough to flag suspected resends */
669 #define MAX_EXPECTED_PDU_LENGTH 2048
671 typedef struct LastFrameData {
674 guint subframeNumber;
675 nstime_t received_time;
677 guint8 data[MAX_EXPECTED_PDU_LENGTH];
680 typedef struct LastFrameDataAllSubframes {
681 LastFrameData subframe[10];
682 } LastFrameDataAllSubframes;
685 /* This table stores (RNTI -> LastFrameDataAllSubframes*). Will be populated when
686 DL frames are first read. */
687 static GHashTable *mac_lte_dl_harq_hash = NULL;
689 typedef struct DLHARQResult {
690 guint previousFrameNum;
694 /* This table stores (FrameNumber -> DLHARQResult). It is assigned during the first
695 pass and used thereafter */
696 static GHashTable *mac_lte_dl_harq_result_hash = NULL;
698 /**************************************************************************/
701 /*****************************************************************/
702 /* Keeping track of last UL frames per C-RNTI so can verify when */
703 /* told that a frame is a retx */
705 /* This table stores (RNTI -> LastFrameDataAllSubframes*). Will be populated when
706 UL frames are first read. */
707 static GHashTable *mac_lte_ul_harq_hash = NULL;
709 typedef struct ULHARQResult {
710 guint previousFrameNum;
714 /* This table stores (CRFrameNum -> ULHARQResult). It is assigned during the first
715 pass and used thereafter */
716 static GHashTable *mac_lte_ul_harq_result_hash = NULL;
718 /**************************************************************************/
721 /**************************************************************************/
722 /* Tracking of Scheduling Requests (SRs). */
724 /* - last grant before SR */
725 /* - SR failures following request */
726 /* - grant following SR */
728 typedef enum SREvent {
734 static const value_string sr_event_vals[] =
736 { SR_Grant, "Grant"},
737 { SR_Request, "SR Request"},
738 { SR_Failure, "SR Failure"},
743 typedef enum SRStatus {
749 static const value_string sr_status_vals[] =
751 { None, "Receiving grants"},
752 { SR_Outstanding, "SR Request outstanding"},
753 { SR_Failed, "SR has Failed"},
758 typedef struct SRState {
760 guint32 lastSRFramenum;
761 guint32 lastGrantFramenum;
762 nstime_t requestTime;
766 /* This table keeps track of the SR state for each UE.
768 static GHashTable *mac_lte_ue_sr_state = NULL;
771 typedef enum SRResultType {
780 typedef struct SRResult {
783 guint32 timeDifference;
785 /* These 2 are only used with InvalidSREvent */
790 /* Entries in this table are created during the first pass
791 It maps (SRFrameNum -> SRResult) */
792 static GHashTable *mac_lte_sr_request_hash = NULL;
795 /**************************************************************************/
799 /* Forward declarations */
800 void proto_reg_handoff_mac_lte(void);
801 void dissect_mac_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
804 /* Heuristic dissection */
805 static gboolean global_mac_lte_heur = FALSE;
807 /* Heuristic dissector looks for supported framing protocol (see wiki page) */
808 static gboolean dissect_mac_lte_heur(tvbuff_t *tvb, packet_info *pinfo,
812 struct mac_lte_info *p_mac_lte_info;
815 gboolean infoAlreadySet = FALSE;
817 /* This is a heuristic dissector, which means we get all the UDP
818 * traffic not sent to a known dissector and not claimed by
819 * a heuristic dissector called before us!
822 if (!global_mac_lte_heur) {
826 /* If redissecting, use previous info struct (if available) */
827 p_mac_lte_info = p_get_proto_data(pinfo->fd, proto_mac_lte);
828 if (p_mac_lte_info == NULL) {
829 /* Allocate new info struct for this frame */
830 p_mac_lte_info = se_alloc0(sizeof(struct mac_lte_info));
831 infoAlreadySet = FALSE;
834 infoAlreadySet = TRUE;
837 /* Do this again on re-dissection to re-discover offset of actual PDU */
839 /* Needs to be at least as long as:
840 - the signature string
843 - at least one byte of MAC PDU payload */
844 if ((size_t)tvb_length_remaining(tvb, offset) < (strlen(MAC_LTE_START_STRING)+3+2)) {
848 /* OK, compare with signature string */
849 if (tvb_strneql(tvb, offset, MAC_LTE_START_STRING, (gint)strlen(MAC_LTE_START_STRING)) != 0) {
852 offset += (gint)strlen(MAC_LTE_START_STRING);
854 /* Read fixed fields */
855 p_mac_lte_info->radioType = tvb_get_guint8(tvb, offset++);
856 p_mac_lte_info->direction = tvb_get_guint8(tvb, offset++);
858 /* TODO: add this info to framing protocol */
859 if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
860 p_mac_lte_info->detailed_phy_info.ul_info.present = FALSE;
863 p_mac_lte_info->detailed_phy_info.dl_info.present = FALSE;
866 p_mac_lte_info->rntiType = tvb_get_guint8(tvb, offset++);
868 /* Read optional fields */
869 while (tag != MAC_LTE_PAYLOAD_TAG) {
870 /* Process next tag */
871 tag = tvb_get_guint8(tvb, offset++);
873 case MAC_LTE_RNTI_TAG:
874 p_mac_lte_info->rnti = tvb_get_ntohs(tvb, offset);
877 case MAC_LTE_UEID_TAG:
878 p_mac_lte_info->ueid = tvb_get_ntohs(tvb, offset);
881 case MAC_LTE_SUBFRAME_TAG:
882 p_mac_lte_info->subframeNumber = tvb_get_ntohs(tvb, offset);
885 case MAC_LTE_PREDFINED_DATA_TAG:
886 p_mac_lte_info->isPredefinedData = tvb_get_guint8(tvb, offset);
889 case MAC_LTE_RETX_TAG:
890 p_mac_lte_info->reTxCount = tvb_get_guint8(tvb, offset);
893 case MAC_LTE_CRC_STATUS_TAG:
894 p_mac_lte_info->crcStatusValid = TRUE;
895 p_mac_lte_info->detailed_phy_info.dl_info.crc_status = tvb_get_guint8(tvb, offset);
899 case MAC_LTE_PAYLOAD_TAG:
900 /* Have reached data, so set payload length and get out of loop */
901 p_mac_lte_info->length= tvb_length_remaining(tvb, offset);
905 /* It must be a recognised tag */
910 if (!infoAlreadySet) {
911 /* Store info in packet */
912 p_add_proto_data(pinfo->fd, proto_mac_lte, p_mac_lte_info);
915 /**************************************/
916 /* OK, now dissect as MAC LTE */
918 /* Create tvb that starts at actual MAC PDU */
919 mac_tvb = tvb_new_subset(tvb, offset, -1, tvb_reported_length(tvb)-offset);
920 dissect_mac_lte(mac_tvb, pinfo, tree);
925 /* Write the given formatted text to:
926 - the info column (if pinfo != NULL)
927 - 1 or 2 other labels (optional)
929 static void write_pdu_label_and_info(proto_item *ti1, proto_item *ti2,
930 packet_info *pinfo, const char *format, ...)
932 #define MAX_INFO_BUFFER 256
933 static char info_buffer[MAX_INFO_BUFFER];
937 va_start(ap, format);
938 g_vsnprintf(info_buffer, MAX_INFO_BUFFER, format, ap);
941 /* Add to indicated places */
943 col_append_str(pinfo->cinfo, COL_INFO, info_buffer);
946 proto_item_append_text(ti1, "%s", info_buffer);
949 proto_item_append_text(ti2, "%s", info_buffer);
953 /* Show extra PHY parameters (if present) */
954 static void show_extra_phy_parameters(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree,
955 struct mac_lte_info *p_mac_lte_info)
958 proto_tree *phy_tree;
961 if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
962 if (p_mac_lte_info->detailed_phy_info.ul_info.present) {
965 phy_ti = proto_tree_add_string_format(tree, hf_mac_lte_context_phy_ul,
966 tvb, 0, 0, "", "UL PHY Context");
967 phy_tree = proto_item_add_subtree(phy_ti, ett_mac_lte_phy_context);
968 PROTO_ITEM_SET_GENERATED(phy_ti);
971 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_modulation_type,
973 p_mac_lte_info->detailed_phy_info.ul_info.modulation_type);
974 PROTO_ITEM_SET_GENERATED(ti);
976 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_tbs_index,
978 p_mac_lte_info->detailed_phy_info.ul_info.tbs_index);
979 PROTO_ITEM_SET_GENERATED(ti);
981 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_resource_block_length,
983 p_mac_lte_info->detailed_phy_info.ul_info.resource_block_length);
984 PROTO_ITEM_SET_GENERATED(ti);
986 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_resource_block_start,
988 p_mac_lte_info->detailed_phy_info.ul_info.resource_block_start);
989 PROTO_ITEM_SET_GENERATED(ti);
991 proto_item_append_text(phy_ti, " (");
993 write_pdu_label_and_info(phy_ti, NULL,
994 (global_mac_lte_layer_to_show == ShowPHYLayer) ? pinfo : NULL,
995 "%s Tbs_Index=%u RB_len=%u RB_start=%u",
996 val_to_str_const(p_mac_lte_info->detailed_phy_info.ul_info.modulation_type,
997 modulation_type_vals, "Unknown"),
998 p_mac_lte_info->detailed_phy_info.ul_info.tbs_index,
999 p_mac_lte_info->detailed_phy_info.ul_info.resource_block_length,
1000 p_mac_lte_info->detailed_phy_info.ul_info.resource_block_start);
1002 proto_item_append_text(phy_ti, ")");
1004 /* Don't want columns to be replaced now */
1005 if (global_mac_lte_layer_to_show == ShowPHYLayer) {
1006 col_set_writable(pinfo->cinfo, FALSE);
1011 if (p_mac_lte_info->detailed_phy_info.dl_info.present) {
1014 phy_ti = proto_tree_add_string_format(tree, hf_mac_lte_context_phy_dl,
1015 tvb, 0, 0, "", "DL PHY Context");
1016 phy_tree = proto_item_add_subtree(phy_ti, ett_mac_lte_phy_context);
1017 PROTO_ITEM_SET_GENERATED(phy_ti);
1020 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_dci_format,
1022 p_mac_lte_info->detailed_phy_info.dl_info.dci_format);
1023 PROTO_ITEM_SET_GENERATED(ti);
1025 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_resource_allocation_type,
1027 p_mac_lte_info->detailed_phy_info.dl_info.resource_allocation_type);
1028 PROTO_ITEM_SET_GENERATED(ti);
1030 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_aggregation_level,
1032 p_mac_lte_info->detailed_phy_info.dl_info.aggregation_level);
1033 PROTO_ITEM_SET_GENERATED(ti);
1035 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_mcs_index,
1037 p_mac_lte_info->detailed_phy_info.dl_info.mcs_index);
1038 PROTO_ITEM_SET_GENERATED(ti);
1040 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_redundancy_version_index,
1042 p_mac_lte_info->detailed_phy_info.dl_info.redundancy_version_index);
1043 PROTO_ITEM_SET_GENERATED(ti);
1045 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_resource_block_length,
1047 p_mac_lte_info->detailed_phy_info.dl_info.resource_block_length);
1048 PROTO_ITEM_SET_GENERATED(ti);
1050 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_crc_status,
1052 p_mac_lte_info->detailed_phy_info.dl_info.crc_status);
1053 PROTO_ITEM_SET_GENERATED(ti);
1055 proto_item_append_text(phy_ti, " (");
1057 write_pdu_label_and_info(phy_ti, NULL,
1058 (global_mac_lte_layer_to_show == ShowPHYLayer) ? pinfo : NULL,
1059 "DCI_Format=%s Res_Alloc=%u Aggr_Level=%s MCS=%u RV=%u "
1060 "Res_Block_len=%u CRC_status=%s",
1061 val_to_str_const(p_mac_lte_info->detailed_phy_info.dl_info.dci_format,
1062 dci_format_vals, "Unknown"),
1063 p_mac_lte_info->detailed_phy_info.dl_info.resource_allocation_type,
1064 val_to_str_const(p_mac_lte_info->detailed_phy_info.dl_info.aggregation_level,
1065 aggregation_level_vals, "Unknown"),
1066 p_mac_lte_info->detailed_phy_info.dl_info.mcs_index,
1067 p_mac_lte_info->detailed_phy_info.dl_info.redundancy_version_index,
1068 p_mac_lte_info->detailed_phy_info.dl_info.resource_block_length,
1069 val_to_str_const(p_mac_lte_info->detailed_phy_info.dl_info.crc_status,
1070 crc_status_vals, "Unknown"));
1071 proto_item_append_text(phy_ti, ")");
1073 /* Don't want columns to be replaced now */
1074 if (global_mac_lte_layer_to_show == ShowPHYLayer) {
1075 col_set_writable(pinfo->cinfo, FALSE);
1082 /* Dissect a single Random Access Reponse body */
1083 static gint dissect_rar_entry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1085 gint offset, guint8 rapid)
1088 guint start_body_offset = offset;
1090 proto_item *rar_body_ti;
1091 proto_tree *rar_body_tree;
1092 proto_tree *ul_grant_tree;
1093 proto_item *ul_grant_ti;
1094 guint16 timing_advance;
1098 /* Create tree for this Body */
1099 rar_body_ti = proto_tree_add_item(tree,
1100 hf_mac_lte_rar_body,
1101 tvb, offset, 0, FALSE);
1102 rar_body_tree = proto_item_add_subtree(rar_body_ti, ett_mac_lte_rar_body);
1104 /* Dissect an RAR entry */
1106 /* Check reserved bit */
1107 reserved = (tvb_get_guint8(tvb, offset) & 0x80) >> 7;
1108 ti = proto_tree_add_item(rar_body_tree, hf_mac_lte_rar_reserved2, tvb, offset, 1, FALSE);
1109 if (reserved != 0) {
1110 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
1111 "RAR body Reserved bit not zero (found 0x%x)", reserved);
1114 /* Timing Advance */
1115 timing_advance = (tvb_get_ntohs(tvb, offset) & 0x7ff0) >> 4;
1116 ti = proto_tree_add_item(rar_body_tree, hf_mac_lte_rar_ta, tvb, offset, 2, FALSE);
1117 if (timing_advance != 0) {
1118 expert_add_info_format(pinfo, ti, PI_SEQUENCE, (timing_advance <= 31) ? PI_NOTE : PI_WARN,
1119 "RAR Timing advance not zero (%u)", timing_advance);
1124 ul_grant = (tvb_get_ntohl(tvb, offset) & 0x0fffff00) >> 8;
1125 ul_grant_ti = proto_tree_add_item(rar_body_tree, hf_mac_lte_rar_ul_grant, tvb, offset, 3, FALSE);
1127 /* Break these 20 bits down as described in 36.213, section 6.2 */
1128 /* Create subtree for UL grant break-down */
1129 ul_grant_tree = proto_item_add_subtree(ul_grant_ti, ett_mac_lte_rar_ul_grant);
1131 /* Hopping flag (1 bit) */
1132 proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_hopping,
1133 tvb, offset, 1, FALSE);
1135 /* Fixed sized resource block assignment (10 bits) */
1136 proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_fsrba,
1137 tvb, offset, 2, FALSE);
1139 /* Truncated Modulation and coding scheme (4 bits) */
1140 proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_tmcs,
1141 tvb, offset+1, 2, FALSE);
1143 /* TPC command for scheduled PUSCH (3 bits) */
1144 proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_tcsp,
1145 tvb, offset+2, 1, FALSE);
1147 /* UL delay (1 bit) */
1148 proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_ul_delay,
1149 tvb, offset+2, 1, FALSE);
1151 /* CQI request (1 bit) */
1152 proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_cqi_request,
1153 tvb, offset+2, 1, FALSE);
1157 /* Temporary C-RNTI */
1158 temp_crnti = tvb_get_ntohs(tvb, offset);
1159 proto_tree_add_item(rar_body_tree, hf_mac_lte_rar_temporary_crnti, tvb, offset, 2, FALSE);
1162 write_pdu_label_and_info(pdu_ti, rar_body_ti, pinfo,
1163 "(RAPID=%u: TA=%u, UL-Grant=%u, Temp C-RNTI=%u) ",
1164 rapid, timing_advance, ul_grant, temp_crnti);
1166 proto_item_set_len(rar_body_ti, offset-start_body_offset);
1172 /* Dissect Random Access Reponse (RAR) PDU */
1173 static void dissect_rar(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *pdu_ti,
1174 gint offset, mac_lte_info *p_mac_lte_info, mac_lte_tap_info *tap_info)
1176 gint number_of_rars = 0; /* No of RAR bodies expected following headers */
1178 gboolean backoff_indicator_seen = FALSE;
1179 guint8 backoff_indicator = 0;
1182 proto_tree *rar_headers_tree;
1184 proto_item *rar_headers_ti;
1185 int start_headers_offset = offset;
1187 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
1188 "RAR (RA-RNTI=%u, SF=%u) ",
1189 p_mac_lte_info->rnti, p_mac_lte_info->subframeNumber);
1191 /* Create hidden 'virtual root' so can filter on mac-lte.rar */
1192 ti = proto_tree_add_item(tree, hf_mac_lte_rar, tvb, offset, -1, FALSE);
1193 PROTO_ITEM_SET_HIDDEN(ti);
1195 /* Create headers tree */
1196 rar_headers_ti = proto_tree_add_item(tree,
1197 hf_mac_lte_rar_headers,
1198 tvb, offset, 0, FALSE);
1199 rar_headers_tree = proto_item_add_subtree(rar_headers_ti, ett_mac_lte_rar_headers);
1202 /***************************/
1203 /* Read the header entries */
1205 int start_header_offset = offset;
1206 proto_tree *rar_header_tree;
1207 proto_item *rar_header_ti;
1209 guint8 first_byte = tvb_get_guint8(tvb, offset);
1211 /* Create tree for this header */
1212 rar_header_ti = proto_tree_add_item(rar_headers_tree,
1213 hf_mac_lte_rar_header,
1214 tvb, offset, 0, FALSE);
1215 rar_header_tree = proto_item_add_subtree(rar_header_ti, ett_mac_lte_rar_header);
1218 extension = (first_byte & 0x80) >> 7;
1219 proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_extension, tvb, offset, 1, FALSE);
1222 type_value = (first_byte & 0x40) >> 6;
1223 proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_t, tvb, offset, 1, FALSE);
1225 if (type_value == 0) {
1226 /* Backoff Indicator (BI) case */
1232 /* 2 Reserved bits */
1233 reserved = (tvb_get_guint8(tvb, offset) & 0x30) >> 4;
1234 tii = proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_reserved, tvb, offset, 1, FALSE);
1235 if (reserved != 0) {
1236 expert_add_info_format(pinfo, tii, PI_MALFORMED, PI_ERROR,
1237 "RAR header Reserved bits not zero (found 0x%x)", reserved);
1240 /* Backoff Indicator */
1241 backoff_indicator = tvb_get_guint8(tvb, offset) & 0x0f;
1242 bi_ti = proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_bi, tvb, offset, 1, FALSE);
1244 /* As of March 2009 spec, it must be first, and may only appear once */
1245 if (backoff_indicator_seen) {
1246 expert_add_info_format(pinfo, bi_ti, PI_MALFORMED, PI_ERROR,
1247 "MAC RAR PDU has > 1 Backoff Indicator subheader present");
1249 backoff_indicator_seen = TRUE;
1251 write_pdu_label_and_info(pdu_ti, rar_header_ti, pinfo,
1252 "(Backoff Indicator=%sms)",
1253 val_to_str_const(backoff_indicator, rar_bi_vals, "Illegal-value "));
1255 /* If present, it must be the first subheader */
1256 if (number_of_rars > 0) {
1257 expert_add_info_format(pinfo, bi_ti, PI_MALFORMED, PI_WARN,
1258 "Backoff Indicator must appear as first subheader");
1264 /* TODO: complain if the same RAPID appears twice in same frame? */
1265 rapids[number_of_rars] = tvb_get_guint8(tvb, offset) & 0x3f;
1266 proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_rapid, tvb, offset, 1, FALSE);
1268 proto_item_append_text(rar_header_ti, "(RAPID=%u)", rapids[number_of_rars]);
1275 /* Finalise length of header tree selection */
1276 proto_item_set_len(rar_header_ti, offset - start_header_offset);
1278 } while (extension);
1280 /* Append summary to headers root */
1281 proto_item_append_text(rar_headers_ti, " (%u RARs", number_of_rars);
1282 if (backoff_indicator_seen) {
1283 proto_item_append_text(rar_headers_ti, ", BI=%sms)",
1284 val_to_str_const(backoff_indicator, rar_bi_vals, "Illegal-value "));
1287 proto_item_append_text(rar_headers_ti, ")");
1290 /* Set length for headers root */
1291 proto_item_set_len(rar_headers_ti, offset-start_headers_offset);
1294 /***************************/
1295 /* Read any indicated RARs */
1296 for (n=0; n < number_of_rars; n++) {
1297 offset = dissect_rar_entry(tvb, pinfo, tree, pdu_ti, offset, rapids[n]);
1300 /* Update TAP info */
1301 tap_info->number_of_rars += number_of_rars;
1303 /* Warn if we don't seem to have reached the end of the frame yet */
1304 if (tvb_length_remaining(tvb, offset) != 0) {
1305 expert_add_info_format(pinfo, pdu_ti, PI_MALFORMED, PI_ERROR,
1306 "%u bytes remaining after RAR PDU dissected",
1307 tvb_length_remaining(tvb, offset));
1312 /* Dissect BCH PDU */
1313 static void dissect_bch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1315 int offset, mac_lte_info *p_mac_lte_info)
1319 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
1320 "BCH PDU (%u bytes, on %s transport) ",
1321 tvb_length_remaining(tvb, offset),
1322 val_to_str_const(p_mac_lte_info->rntiType,
1323 bch_transport_channel_vals,
1326 /* Show which transport layer it came in on (inferred from RNTI type) */
1327 ti = proto_tree_add_uint(tree, hf_mac_lte_context_bch_transport_channel,
1328 tvb, offset, 0, p_mac_lte_info->rntiType);
1329 PROTO_ITEM_SET_GENERATED(ti);
1331 /****************************************/
1332 /* Whole frame is BCH data */
1335 ti = proto_tree_add_item(tree, hf_mac_lte_bch_pdu,
1336 tvb, offset, -1, FALSE);
1338 if (global_mac_lte_attempt_rrc_decode) {
1339 /* Attempt to decode payload using LTE RRC dissector */
1340 tvbuff_t *rrc_tvb = tvb_new_subset(tvb, offset, -1, tvb_length_remaining(tvb, offset));
1342 /* Get appropriate dissector handle */
1343 dissector_handle_t protocol_handle = 0;
1344 if (p_mac_lte_info->rntiType == SI_RNTI) {
1345 protocol_handle = find_dissector("lte-rrc.bcch.dl.sch");
1348 protocol_handle = find_dissector("lte-rrc.bcch.bch");
1351 /* Hide raw view of bytes */
1352 PROTO_ITEM_SET_HIDDEN(ti);
1354 /* Call it (catch exceptions so that stats will be updated) */
1355 /* TODO: couldn't avoid warnings for 'ti' by using volatile
1358 call_dissector_only(protocol_handle, rrc_tvb, pinfo, tree);
1365 /* Check that this *is* downlink! */
1366 if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
1367 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
1368 "BCH data should not be received in Uplink!");
1373 /* Dissect PCH PDU */
1374 static void dissect_pch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1375 proto_item *pdu_ti, int offset, guint8 direction)
1379 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
1380 "PCH PDU (%u bytes) ",
1381 tvb_length_remaining(tvb, offset));
1383 /****************************************/
1384 /* Whole frame is PCH data */
1386 /* Always show as raw data */
1387 ti = proto_tree_add_item(tree, hf_mac_lte_pch_pdu,
1388 tvb, offset, -1, FALSE);
1390 if (global_mac_lte_attempt_rrc_decode) {
1392 /* Attempt to decode payload using LTE RRC dissector */
1393 tvbuff_t *rrc_tvb = tvb_new_subset(tvb, offset, -1, tvb_length_remaining(tvb, offset));
1395 /* Get appropriate dissector handle */
1396 dissector_handle_t protocol_handle = find_dissector("lte-rrc.pcch");
1398 /* Hide raw view of bytes */
1399 PROTO_ITEM_SET_HIDDEN(ti);
1401 /* Call it (catch exceptions so that stats will be updated) */
1403 call_dissector_only(protocol_handle, rrc_tvb, pinfo, tree);
1410 /* Check that this *is* downlink! */
1411 if (direction == DIRECTION_UPLINK) {
1412 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
1413 "PCH data should not be received in Uplink!");
1418 /* Does this header entry correspond to a fixed-sized control element? */
1419 static int is_fixed_sized_control_element(guint8 lcid, guint8 direction)
1421 if (direction == DIRECTION_UPLINK) {
1424 case POWER_HEADROOM_REPORT_LCID:
1426 case TRUNCATED_BSR_LCID:
1427 case SHORT_BSR_LCID:
1436 /* Assume Downlink */
1438 case UE_CONTENTION_RESOLUTION_IDENTITY_LCID:
1439 case TIMING_ADVANCE_LCID:
1440 case DRX_COMMAND_LCID:
1450 /* Is this a BSR report header? */
1451 static int is_bsr_lcid(guint8 lcid)
1453 return ((lcid == TRUNCATED_BSR_LCID) ||
1454 (lcid == SHORT_BSR_LCID) ||
1455 (lcid == LONG_BSR_LCID));
1459 /* Helper function to call RLC dissector for SDUs (where channel params are known) */
1460 static void call_rlc_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1462 int offset, guint16 data_length,
1463 guint8 mode, guint8 direction, guint16 ueid,
1464 guint16 channelType, guint16 channelId,
1465 guint8 UMSequenceNumberLength)
1467 tvbuff_t *srb_tvb = tvb_new_subset(tvb, offset, data_length, data_length);
1468 struct rlc_lte_info *p_rlc_lte_info;
1470 /* Get RLC dissector handle */
1471 volatile dissector_handle_t protocol_handle = find_dissector("rlc-lte");
1473 /* Resuse or create RLC info */
1474 p_rlc_lte_info = p_get_proto_data(pinfo->fd, proto_rlc_lte);
1475 if (p_rlc_lte_info == NULL) {
1476 p_rlc_lte_info = se_alloc0(sizeof(struct rlc_lte_info));
1479 /* Fill in struct details for srb channels */
1480 p_rlc_lte_info->rlcMode = mode;
1481 p_rlc_lte_info->direction = direction;
1482 p_rlc_lte_info->priority = 0; /* ?? */
1483 p_rlc_lte_info->ueid = ueid;
1484 p_rlc_lte_info->channelType = channelType;
1485 p_rlc_lte_info->channelId = channelId;
1486 p_rlc_lte_info->pduLength = data_length;
1487 p_rlc_lte_info->UMSequenceNumberLength = UMSequenceNumberLength;
1489 /* Store info in packet */
1490 p_add_proto_data(pinfo->fd, proto_rlc_lte, p_rlc_lte_info);
1492 if (global_mac_lte_layer_to_show != ShowRLCLayer) {
1493 /* Don't want these columns replaced */
1494 col_set_writable(pinfo->cinfo, FALSE);
1497 /* Clear info column before first RLC PDU */
1498 if (s_number_of_rlc_pdus_shown == 0) {
1499 col_clear(pinfo->cinfo, COL_INFO);
1502 /* Add a separator and protect column contents here */
1503 write_pdu_label_and_info(pdu_ti, NULL, pinfo, " || ");
1504 col_set_fence(pinfo->cinfo, COL_INFO);
1507 s_number_of_rlc_pdus_shown++;
1509 /* Call it (catch exceptions so that stats will be updated) */
1511 call_dissector_only(protocol_handle, srb_tvb, pinfo, tree);
1517 col_set_writable(pinfo->cinfo, TRUE);
1521 /* Track DL frames, and look for likely cases of likely HARQ retx. Return TRUE if found */
1522 static int DetectIfDLHARQResend(packet_info *pinfo, tvbuff_t *tvb, volatile int offset,
1523 proto_tree *tree, mac_lte_info *p_mac_lte_info)
1525 DLHARQResult *result = NULL;
1526 proto_item *result_ti;
1528 /* TDD may not work... */
1530 if (!pinfo->fd->flags.visited) {
1531 /* First time, so set result and update DL harq table */
1532 LastFrameData *lastData = NULL;
1533 LastFrameData *thisData = NULL;
1535 /* Look up entry for this UE/RNTI */
1536 LastFrameDataAllSubframes *ueData =
1537 g_hash_table_lookup(mac_lte_dl_harq_hash, GUINT_TO_POINTER((guint)p_mac_lte_info->rnti));
1538 if (ueData != NULL) {
1540 /* Looking for a frame sent 8 or 9 subframes previously.
1541 TODO: have seen retx >=10 SFs later... */
1542 gboolean found_match = FALSE;
1545 for (SFs_ago=8; (SFs_ago <= 9) && !found_match; SFs_ago++) {
1546 /* Check 8 SFs ago */
1547 lastData = &(ueData->subframe[(p_mac_lte_info->subframeNumber+(10-SFs_ago)) % 10]);
1548 if (lastData->inUse) {
1549 /* Compare time, sf, data to see if this looks like a retx */
1550 if ((tvb_length_remaining(tvb, offset) == lastData->length) &&
1551 (memcmp(lastData->data,
1552 tvb_get_ptr(tvb, offset, lastData->length),
1553 MIN(lastData->length, MAX_EXPECTED_PDU_LENGTH)) == 0)) {
1555 /* Work out gap between frames */
1556 gint seconds_between_packets = (gint)
1557 (pinfo->fd->abs_ts.secs - lastData->received_time.secs);
1558 gint nseconds_between_packets =
1559 pinfo->fd->abs_ts.nsecs - lastData->received_time.nsecs;
1561 /* Round difference to nearest millisecond */
1562 gint total_gap = (seconds_between_packets*1000) +
1563 ((nseconds_between_packets+500000) / 1000000);
1565 /* Should be equal to number of subframes - allow some leeway */
1566 if ((total_gap >= (SFs_ago-1)) && (total_gap <= (SFs_ago+1))) {
1569 /* Resend detected!!! Store result */
1570 result = se_alloc(sizeof(DLHARQResult));
1571 result->previousFrameNum = lastData->framenum;
1572 g_hash_table_insert(mac_lte_dl_harq_result_hash, GUINT_TO_POINTER(pinfo->fd->num), result);
1578 /* Even if we didn't find a previous frame, if we know its a retx, setup result */
1579 if ((result == NULL) && (p_mac_lte_info->dl_retx == dl_retx_yes)) {
1580 result = se_alloc(sizeof(DLHARQResult));
1581 result->previousFrameNum = 0;
1582 g_hash_table_insert(mac_lte_dl_harq_result_hash, GUINT_TO_POINTER(pinfo->fd->num), result);
1587 /* Allocate entry in table for this UE/RNTI */
1588 ueData = se_alloc0(sizeof(LastFrameDataAllSubframes));
1589 g_hash_table_insert(mac_lte_dl_harq_hash, GUINT_TO_POINTER((guint)p_mac_lte_info->rnti), ueData);
1592 /* Store this frame's details in table */
1593 thisData = &(ueData->subframe[p_mac_lte_info->subframeNumber]);
1594 thisData->inUse = TRUE;
1595 thisData->length = tvb_length_remaining(tvb, offset);
1596 memcpy(thisData->data,
1597 tvb_get_ptr(tvb, offset, MIN(thisData->length, MAX_EXPECTED_PDU_LENGTH)),
1598 MIN(thisData->length, MAX_EXPECTED_PDU_LENGTH));
1599 thisData->subframeNumber = p_mac_lte_info->subframeNumber;
1600 thisData->framenum = pinfo->fd->num;
1601 thisData->received_time = pinfo->fd->abs_ts;
1604 /* Not first time, so just set whats already stored in result */
1605 result = g_hash_table_lookup(mac_lte_dl_harq_result_hash, GUINT_TO_POINTER(pinfo->fd->num));
1609 /************************************************************/
1610 /* Show result, with link back to original frame (if known) */
1611 result_ti = proto_tree_add_boolean(tree, hf_mac_lte_context_phy_dl_retx,
1612 tvb, 0, 0, (result != NULL));
1613 if (result != NULL) {
1614 proto_item *original_ti;
1615 expert_add_info_format(pinfo, result_ti, PI_SEQUENCE, PI_WARN,
1616 "%sDL HARQ resend (UE=%u)",
1617 (p_mac_lte_info->dl_retx == dl_retx_unknown) ? "Suspected " : "",
1618 p_mac_lte_info->ueid);
1619 if (result->previousFrameNum != 0) {
1620 original_ti = proto_tree_add_uint(tree, hf_mac_lte_suspected_dl_retx_original_frame,
1621 tvb, 0, 0, result->previousFrameNum);
1622 PROTO_ITEM_SET_GENERATED(original_ti);
1626 /* Don't show negatives */
1627 PROTO_ITEM_SET_HIDDEN(result_ti);
1629 PROTO_ITEM_SET_GENERATED(result_ti);
1631 /* Return TRUE if resend was detected */
1632 return (result != NULL);
1636 /* Return TRUE if the given packet is thought to be a retx */
1637 int is_mac_lte_frame_retx(packet_info *pinfo, guint8 direction)
1639 if (direction == DIRECTION_UPLINK) {
1640 /* For UL, retx count is stored in per-packet struct */
1641 struct mac_lte_info *p_mac_lte_info = p_get_proto_data(pinfo->fd, proto_mac_lte);
1642 return ((p_mac_lte_info != NULL) && (p_mac_lte_info->reTxCount > 0));
1645 /* For DL, must consult result table */
1646 return (g_hash_table_lookup(mac_lte_dl_harq_result_hash, GUINT_TO_POINTER(pinfo->fd->num)) != NULL);
1651 /* Track UL frames, so that when a retx is indicated, we can search for
1652 the original tx. We will either find it, and provide a link back to it,
1653 or flag that we couldn't find as an expert error */
1654 static void TrackReportedULHARQResend(packet_info *pinfo, tvbuff_t *tvb, volatile int offset,
1655 proto_tree *tree, mac_lte_info *p_mac_lte_info,
1656 proto_item *retx_ti)
1658 ULHARQResult *result = NULL;
1660 /* FDD only for now! */
1661 if (p_mac_lte_info->radioType != FDD_RADIO) {
1665 if (!pinfo->fd->flags.visited) {
1666 /* First time, so set result and update UL harq table */
1667 LastFrameData *lastData = NULL;
1668 LastFrameData *thisData = NULL;
1670 /* Look up entry for this UE/RNTI */
1671 LastFrameDataAllSubframes *ueData =
1672 g_hash_table_lookup(mac_lte_ul_harq_hash, GUINT_TO_POINTER((guint)p_mac_lte_info->rnti));
1673 if (ueData != NULL) {
1675 if (p_mac_lte_info->reTxCount >= 1) {
1676 /* Looking for a frame sent 8 subframes previously */
1677 lastData = &(ueData->subframe[(p_mac_lte_info->subframeNumber+2) % 10]);
1678 if (lastData->inUse) {
1679 /* Compare time, sf, data to see if this looks like a retx */
1680 if ((tvb_length_remaining(tvb, offset) == lastData->length) &&
1681 (memcmp(lastData->data,
1682 tvb_get_ptr(tvb, offset, lastData->length),
1683 MIN(lastData->length, MAX_EXPECTED_PDU_LENGTH)) == 0)) {
1685 /* Work out gap between frames */
1686 gint seconds_between_packets = (gint)
1687 (pinfo->fd->abs_ts.secs - lastData->received_time.secs);
1688 gint nseconds_between_packets =
1689 pinfo->fd->abs_ts.nsecs - lastData->received_time.nsecs;
1691 /* Round to nearest ms */
1692 gint total_gap = (seconds_between_packets*1000) +
1693 ((nseconds_between_packets+500000) / 1000000);
1695 /* Should be 8 ms apart - allow some leeway */
1696 if ((total_gap >= 7) && (total_gap <= 9)) {
1697 /* Original detected!!! Store result */
1698 result = se_alloc(sizeof(ULHARQResult));
1699 result->previousFrameNum = lastData->framenum;
1700 g_hash_table_insert(mac_lte_ul_harq_result_hash, GUINT_TO_POINTER(pinfo->fd->num), result);
1707 /* Allocate entry in table for this UE/RNTI */
1708 ueData = se_alloc0(sizeof(LastFrameDataAllSubframes));
1709 g_hash_table_insert(mac_lte_ul_harq_hash, GUINT_TO_POINTER((guint)p_mac_lte_info->rnti), ueData);
1712 /* Store this frame's details in table */
1713 thisData = &(ueData->subframe[p_mac_lte_info->subframeNumber]);
1714 thisData->inUse = TRUE;
1715 thisData->length = tvb_length_remaining(tvb, offset);
1716 memcpy(thisData->data,
1717 tvb_get_ptr(tvb, offset, MIN(thisData->length, MAX_EXPECTED_PDU_LENGTH)),
1718 MIN(thisData->length, MAX_EXPECTED_PDU_LENGTH));
1719 thisData->subframeNumber = p_mac_lte_info->subframeNumber;
1720 thisData->framenum = pinfo->fd->num;
1721 thisData->received_time = pinfo->fd->abs_ts;
1724 /* Not first time, so just set whats already stored in result */
1725 result = g_hash_table_lookup(mac_lte_ul_harq_result_hash, GUINT_TO_POINTER(pinfo->fd->num));
1728 if (retx_ti != NULL) {
1729 if (result != NULL) {
1730 proto_item *original_ti;
1732 original_ti = proto_tree_add_uint(tree, hf_mac_lte_ul_harq_resend_original_frame,
1733 tvb, 0, 0, result->previousFrameNum);
1734 PROTO_ITEM_SET_GENERATED(original_ti);
1737 expert_add_info_format(pinfo, retx_ti, PI_SEQUENCE, PI_ERROR,
1738 "Original Tx of UL frame not found (UE %u) !!", p_mac_lte_info->ueid);
1744 /* Look up SRResult associated with a given frame. Will create one if necessary
1745 if can_create is set */
1746 static SRResult *GetSRResult(guint32 frameNum, gboolean can_create)
1749 result = g_hash_table_lookup(mac_lte_sr_request_hash, GUINT_TO_POINTER(frameNum));
1751 if ((result == NULL) && can_create) {
1752 result = se_alloc0(sizeof(SRResult));
1753 g_hash_table_insert(mac_lte_sr_request_hash, GUINT_TO_POINTER((guint)frameNum), result);
1759 /* Keep track of SR requests, failures and related grants, in order to show them
1760 as generated fields in these frames */
1761 static void TrackSRInfo(SREvent event, packet_info *pinfo, proto_tree *tree _U_,
1762 tvbuff_t *tvb _U_, guint16 rnti, proto_item *event_ti)
1764 SRResult *result = NULL;
1765 SRResult *resultForSRFrame = NULL;
1768 /* Create state for this RNTI if necessary */
1769 SRState *state = g_hash_table_lookup(mac_lte_ue_sr_state, GUINT_TO_POINTER((guint)rnti));
1770 if (state == NULL) {
1771 /* Allocate status for this RNTI */
1772 state = se_alloc(sizeof(SRState));
1773 state->status = None;
1774 g_hash_table_insert(mac_lte_ue_sr_state, GUINT_TO_POINTER((guint)rnti), state);
1777 /* First time through - update state with new info */
1778 if (!pinfo->fd->flags.visited) {
1779 guint32 timeSinceRequest;
1781 /* Store time of request */
1782 if (event == SR_Request) {
1783 state->requestTime = pinfo->fd->abs_ts;
1786 switch (state->status) {
1790 /* Got another grant - fine */
1793 state->lastGrantFramenum = pinfo->fd->num;
1797 /* Sent an SR - fine */
1800 state->status = SR_Outstanding;
1801 state->lastSRFramenum = pinfo->fd->num;
1805 /* This is an error, since we hadn't send an SR... */
1806 result = GetSRResult(pinfo->fd->num, TRUE);
1807 result->type = InvalidSREvent;
1808 result->status = None;
1809 result->event = SR_Failure;
1814 case SR_Outstanding:
1815 timeSinceRequest = (guint32)(((pinfo->fd->abs_ts.secs - state->requestTime.secs) * 1000) +
1816 ((pinfo->fd->abs_ts.nsecs - state->requestTime.nsecs) / 1000000));
1820 /* Got grant we were waiting for, so state goes to None */
1823 state->status = None;
1825 /* Set result info */
1826 result = GetSRResult(pinfo->fd->num, TRUE);
1827 result->type = GrantAnsweringSR;
1828 result->frameNum = state->lastSRFramenum;
1829 result->timeDifference = timeSinceRequest;
1831 /* Also set forward link for SR */
1832 resultForSRFrame = GetSRResult(state->lastSRFramenum, TRUE);
1833 resultForSRFrame->type = SRLeadingToGrant;
1834 resultForSRFrame->frameNum = pinfo->fd->num;
1835 resultForSRFrame->timeDifference = timeSinceRequest;
1839 /* Another request when already have one pending */
1840 result = GetSRResult(pinfo->fd->num, TRUE);
1841 result->type = InvalidSREvent;
1842 result->status = SR_Outstanding;
1843 result->event = SR_Grant;
1847 /* We sent an SR but it failed */
1850 state->status = SR_Failed;
1852 /* Set result info for failure frame */
1853 result = GetSRResult(pinfo->fd->num, TRUE);
1854 result->type = FailureAnsweringSR;
1855 result->frameNum = state->lastSRFramenum;
1856 result->timeDifference = timeSinceRequest;
1858 /* Also set forward link for SR */
1859 resultForSRFrame = GetSRResult(state->lastSRFramenum, TRUE);
1860 resultForSRFrame->type = SRLeadingToFailure;
1861 resultForSRFrame->frameNum = pinfo->fd->num;
1862 resultForSRFrame->timeDifference = timeSinceRequest;
1870 /* Got a grant, presumably after a subsequent RACH - fine */
1873 state->status = None;
1877 /* Tried another SR after a failure, and presumbly no
1878 successful subsequent RACH */
1879 result = GetSRResult(pinfo->fd->num, TRUE);
1880 result->type = InvalidSREvent;
1881 result->status = SR_Failed;
1882 result->event = SR_Request;
1886 /* 2 failures in a row.... */
1887 result = GetSRResult(pinfo->fd->num, TRUE);
1888 result->type = InvalidSREvent;
1889 result->status = SR_Failed;
1890 result->event = SR_Failure;
1897 /* Get stored result for this frame */
1898 result = GetSRResult(pinfo->fd->num, FALSE);
1899 if (result == NULL) {
1900 /* For an SR frame, there should always be either a PDCCH grant or indication
1901 that the SR has failed */
1902 if (event == SR_Request) {
1903 expert_add_info_format(pinfo, event_ti, PI_SEQUENCE, PI_ERROR,
1904 "SR results in neither a grant or a failure indication");
1910 /* Show result info */
1911 switch (result->type) {
1912 case GrantAnsweringSR:
1913 ti = proto_tree_add_uint(tree, hf_mac_lte_grant_answering_sr,
1914 tvb, 0, 0, result->frameNum);
1915 PROTO_ITEM_SET_GENERATED(ti);
1916 ti = proto_tree_add_uint(tree, hf_mac_lte_sr_time_since_request,
1917 tvb, 0, 0, result->timeDifference);
1918 PROTO_ITEM_SET_GENERATED(ti);
1921 case FailureAnsweringSR:
1922 ti = proto_tree_add_uint(tree, hf_mac_lte_failure_answering_sr,
1923 tvb, 0, 0, result->frameNum);
1924 PROTO_ITEM_SET_GENERATED(ti);
1925 ti = proto_tree_add_uint(tree, hf_mac_lte_sr_time_since_request,
1926 tvb, 0, 0, result->timeDifference);
1927 PROTO_ITEM_SET_GENERATED(ti);
1930 case SRLeadingToGrant:
1931 ti = proto_tree_add_uint(tree, hf_mac_lte_sr_leading_to_grant,
1932 tvb, 0, 0, result->frameNum);
1933 PROTO_ITEM_SET_GENERATED(ti);
1934 ti = proto_tree_add_uint(tree, hf_mac_lte_sr_time_until_answer,
1935 tvb, 0, 0, result->timeDifference);
1936 PROTO_ITEM_SET_GENERATED(ti);
1940 case SRLeadingToFailure:
1941 ti = proto_tree_add_uint(tree, hf_mac_lte_sr_leading_to_failure,
1942 tvb, 0, 0, result->frameNum);
1943 PROTO_ITEM_SET_GENERATED(ti);
1944 ti = proto_tree_add_uint(tree, hf_mac_lte_sr_time_until_answer,
1945 tvb, 0, 0, result->timeDifference);
1946 PROTO_ITEM_SET_GENERATED(ti);
1949 case InvalidSREvent:
1950 ti = proto_tree_add_none_format(tree, hf_mac_lte_sr_invalid_event,
1951 tvb, 0, 0, "Invalid SR event - state=(%s), event=(%s)",
1952 val_to_str_const(result->status, sr_status_vals, "Unknown"),
1953 val_to_str_const(result->event, sr_event_vals, "Unknown"));
1954 PROTO_ITEM_SET_GENERATED(ti);
1955 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_ERROR,
1956 "Invalid SR event - state=(%s), event=(%s)",
1957 val_to_str_const(result->status, sr_status_vals, "Unknown"),
1958 val_to_str_const(result->event, sr_event_vals, "Unknown"));
1968 #define MAX_HEADERS_IN_PDU 1024
1970 /* UL-SCH and DL-SCH formats have much in common, so handle them in a common
1972 static void dissect_ulsch_or_dlsch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1974 volatile int offset, guint8 direction,
1975 mac_lte_info *p_mac_lte_info, mac_lte_tap_info *tap_info,
1976 proto_item *retx_ti,
1977 proto_tree *context_tree)
1981 proto_item *truncated_ti;
1982 proto_item *padding_length_ti;
1983 proto_item *hidden_root_ti;
1985 /* Keep track of LCIDs and lengths as we dissect the header */
1986 volatile guint8 number_of_headers = 0;
1987 guint8 lcids[MAX_HEADERS_IN_PDU];
1988 gint16 pdu_lengths[MAX_HEADERS_IN_PDU];
1990 proto_item *pdu_header_ti;
1991 proto_tree *pdu_header_tree;
1993 gboolean have_seen_data_header = FALSE;
1994 gboolean have_seen_bsr = FALSE;
1995 gboolean expecting_body_data = FALSE;
1996 volatile guint32 is_truncated = FALSE;
1998 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
1999 "%s: (SF=%u) UEId=%u ",
2000 (direction == DIRECTION_UPLINK) ? "UL-SCH" : "DL-SCH",
2001 p_mac_lte_info->subframeNumber,
2002 p_mac_lte_info->ueid);
2004 tap_info->raw_length = p_mac_lte_info->length;
2006 /* For downlink frames, can try to work out if this looks like a HARQ resend */
2007 if (direction == DIRECTION_DOWNLINK) {
2008 /* Result will be added to context tree */
2009 int detected = DetectIfDLHARQResend(pinfo, tvb, offset, context_tree, p_mac_lte_info);
2010 if (p_mac_lte_info->dl_retx == dl_retx_unknown) {
2011 tap_info->isPHYRetx = detected;
2014 tap_info->isPHYRetx = p_mac_lte_info->dl_retx;
2019 /* For uplink frames, if this is logged as a resend, look for original tx */
2020 if ((direction == DIRECTION_UPLINK) && global_mac_lte_attempt_ul_harq_resend_track) {
2021 TrackReportedULHARQResend(pinfo, tvb, offset, tree, p_mac_lte_info, retx_ti);
2024 /* For uplink grants, update SR status */
2025 if ((direction == DIRECTION_UPLINK) && global_mac_lte_track_sr) {
2026 TrackSRInfo(SR_Grant, pinfo, tree, tvb, p_mac_lte_info->rnti, NULL);
2029 /* Add hidden item to filter on */
2030 hidden_root_ti = proto_tree_add_string_format(tree,
2031 (direction == DIRECTION_UPLINK) ?
2037 PROTO_ITEM_SET_HIDDEN(hidden_root_ti);
2039 /* Add PDU block header subtree */
2040 pdu_header_ti = proto_tree_add_string_format(tree,
2041 (direction == DIRECTION_UPLINK) ?
2042 hf_mac_lte_ulsch_header :
2043 hf_mac_lte_dlsch_header,
2047 pdu_header_tree = proto_item_add_subtree(pdu_header_ti,
2048 (direction == DIRECTION_UPLINK) ?
2049 ett_mac_lte_ulsch_header :
2050 ett_mac_lte_dlsch_header);
2053 /************************************************************************/
2054 /* Dissect each sub-header. */
2058 proto_item *pdu_subheader_ti;
2059 proto_tree *pdu_subheader_tree;
2060 proto_item *lcid_ti;
2062 gint offset_start_subheader = offset;
2063 guint8 first_byte = tvb_get_guint8(tvb, offset);
2065 /* Add PDU block header subtree */
2066 pdu_subheader_ti = proto_tree_add_string_format(pdu_header_tree,
2067 hf_mac_lte_sch_subheader,
2071 pdu_subheader_tree = proto_item_add_subtree(pdu_subheader_ti,
2072 ett_mac_lte_sch_subheader);
2074 /* Check 1st 2 reserved bits */
2075 reserved = (first_byte & 0xc0) >> 6;
2076 ti = proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_sch_reserved,
2077 tvb, offset, 1, FALSE);
2078 if (reserved != 0) {
2079 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
2080 "%cL-SCH header Reserved bits not zero",
2081 (p_mac_lte_info->direction == DIRECTION_UPLINK) ? 'U' : 'D');
2085 extension = (first_byte & 0x20) >> 5;
2086 proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_sch_extended,
2087 tvb, offset, 1, FALSE);
2089 /* LCID. Has different meaning depending upon direction. */
2090 lcids[number_of_headers] = first_byte & 0x1f;
2091 if (direction == DIRECTION_UPLINK) {
2092 lcid_ti = proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_ulsch_lcid,
2093 tvb, offset, 1, FALSE);
2094 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
2096 val_to_str_const(lcids[number_of_headers],
2097 ulsch_lcid_vals, "(Unknown LCID)"));
2100 lcid_ti = proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_dlsch_lcid,
2101 tvb, offset, 1, FALSE);
2102 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
2104 val_to_str_const(lcids[number_of_headers],
2105 dlsch_lcid_vals, "(Unknown LCID)"));
2109 /* Remember if we've seen a data subheader */
2110 if (lcids[number_of_headers] <= 10) {
2111 have_seen_data_header = TRUE;
2112 expecting_body_data = TRUE;
2115 /* Show an expert item if a contol subheader (except Padding) appears
2116 *after* a data PDU */
2117 if (have_seen_data_header &&
2118 (lcids[number_of_headers] > 10) && (lcids[number_of_headers] != PADDING_LCID)) {
2119 expert_add_info_format(pinfo, lcid_ti, PI_MALFORMED, PI_ERROR,
2120 "%cL-SCH Control subheaders should not appear after data subheaders",
2121 (p_mac_lte_info->direction == DIRECTION_UPLINK) ? 'U' : 'D');
2124 /* Show an expert item if we're seeing more then one BSR in a frame */
2125 if ((direction == DIRECTION_UPLINK) && is_bsr_lcid(lcids[number_of_headers])) {
2126 if (have_seen_bsr) {
2127 expert_add_info_format(pinfo, lcid_ti, PI_MALFORMED, PI_ERROR,
2128 "There shouldn't be > 1 BSR in a frame");
2130 have_seen_bsr = TRUE;
2134 /********************************************************************/
2135 /* Length field follows if not the last header or for a fixed-sized
2138 if (is_fixed_sized_control_element(lcids[number_of_headers], direction)) {
2139 pdu_lengths[number_of_headers] = 0;
2142 pdu_lengths[number_of_headers] = -1;
2146 if (!is_fixed_sized_control_element(lcids[number_of_headers], direction) &&
2147 (lcids[number_of_headers] != PADDING_LCID)) {
2151 /* F(ormat) bit tells us how long the length field is */
2152 format = (tvb_get_guint8(tvb, offset) & 0x80) >> 7;
2153 proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_sch_format,
2154 tvb, offset, 1, FALSE);
2156 /* Now read length field itself */
2158 /* >= 128 - use 15 bits */
2159 proto_tree_add_bits_ret_val(pdu_subheader_tree, hf_mac_lte_sch_length,
2160 tvb, offset*8 + 1, 15, &length, FALSE);
2165 /* Less than 128 - only 7 bits */
2166 proto_tree_add_bits_ret_val(pdu_subheader_tree, hf_mac_lte_sch_length,
2167 tvb, offset*8 + 1, 7, &length, FALSE);
2170 pdu_lengths[number_of_headers] = (gint16)length;
2173 pdu_lengths[number_of_headers] = 0;
2178 /* Close off description in info column */
2179 switch (pdu_lengths[number_of_headers]) {
2181 write_pdu_label_and_info(pdu_ti, NULL, pinfo, ") ");
2184 write_pdu_label_and_info(pdu_ti, NULL, pinfo, ":remainder) ");
2187 write_pdu_label_and_info(pdu_ti, NULL, pinfo, ":%u bytes) ",
2188 pdu_lengths[number_of_headers]);
2192 /* Append summary to subheader root */
2193 proto_item_append_text(pdu_subheader_ti, " (lcid=%s",
2194 val_to_str_const(lcids[number_of_headers],
2195 (direction == DIRECTION_UPLINK) ?
2200 switch (pdu_lengths[number_of_headers]) {
2202 proto_item_append_text(pdu_subheader_ti, ", length is remainder)");
2205 proto_item_append_text(pdu_subheader_ti, ")");
2208 proto_item_append_text(pdu_subheader_ti, ", length=%u)",
2209 pdu_lengths[number_of_headers]);
2214 /* Flag unknown lcid values in expert info */
2215 if (match_strval(lcids[number_of_headers],
2216 (direction == DIRECTION_UPLINK) ? ulsch_lcid_vals : dlsch_lcid_vals) == NULL) {
2217 expert_add_info_format(pinfo, pdu_subheader_ti, PI_MALFORMED, PI_ERROR,
2218 "%cL-SCH: Unexpected LCID received (%u)",
2219 (p_mac_lte_info->direction == DIRECTION_UPLINK) ? 'U' : 'D',
2220 lcids[number_of_headers]);
2223 /* Set length of this subheader */
2224 proto_item_set_len(pdu_subheader_ti, offset- offset_start_subheader);
2226 number_of_headers++;
2227 } while (extension);
2229 /* Append summary to overall PDU header root */
2230 proto_item_append_text(pdu_header_ti, " (%u subheaders)",
2233 /* And set its length to offset */
2234 proto_item_set_len(pdu_header_ti, offset);
2239 /************************************************************************/
2240 /* Dissect SDUs / control elements / padding. */
2241 /************************************************************************/
2243 /* Dissect control element bodies first */
2245 for (n=0; n < number_of_headers; n++) {
2246 /* Get out of loop once see any data SDU subheaders */
2247 if (lcids[n] <= 10) {
2251 /* Process what should be a valid control PDU type */
2252 if (direction == DIRECTION_DOWNLINK) {
2254 /****************************/
2255 /* DL-SCH Control PDUs */
2257 case UE_CONTENTION_RESOLUTION_IDENTITY_LCID:
2260 proto_tree *cr_tree;
2262 ContentionResolutionResult *crResult;
2264 /* Create CR root */
2265 cr_ti = proto_tree_add_string_format(tree,
2266 hf_mac_lte_control_ue_contention_resolution,
2269 "Contention Resolution");
2270 cr_tree = proto_item_add_subtree(cr_ti, ett_mac_lte_contention_resolution);
2273 proto_tree_add_item(cr_tree, hf_mac_lte_control_ue_contention_resolution_identity,
2274 tvb, offset, 6, FALSE);
2276 /* Get pointer to result struct for this frame */
2277 crResult = g_hash_table_lookup(mac_lte_cr_result_hash, GUINT_TO_POINTER(pinfo->fd->num));
2278 if (crResult == NULL) {
2280 /* Need to set result by looking for and comparing with Msg3 */
2282 guint msg3Key = p_mac_lte_info->rnti;
2284 /* Allocate result and add it to the table */
2285 crResult = se_alloc(sizeof(ContentionResolutionResult));
2286 g_hash_table_insert(mac_lte_cr_result_hash, GUINT_TO_POINTER(pinfo->fd->num), crResult);
2289 msg3Data = g_hash_table_lookup(mac_lte_msg3_hash, GUINT_TO_POINTER(msg3Key));
2291 /* Compare CCCH bytes */
2292 if (msg3Data != NULL) {
2293 crResult->msSinceMsg3 = (guint32)(((pinfo->fd->abs_ts.secs - msg3Data->msg3Time.secs) * 1000) +
2294 ((pinfo->fd->abs_ts.nsecs - msg3Data->msg3Time.nsecs) / 1000000));
2295 crResult->msg3FrameNum = msg3Data->framenum;
2297 /* Compare the 6 bytes */
2298 if (memcmp(&msg3Data->data, tvb_get_ptr(tvb, offset, 6), 6) == 0) {
2299 crResult->status = Msg3Match;
2302 crResult->status = Msg3NoMatch;
2306 crResult->status = NoMsg3;
2310 /* Now show CR result in tree */
2311 switch (crResult->status) {
2313 proto_item_append_text(cr_ti, " (no corresponding Msg3 found!)");
2317 ti = proto_tree_add_uint(cr_tree, hf_mac_lte_control_ue_contention_resolution_msg3,
2318 tvb, 0, 0, crResult->msg3FrameNum);
2319 PROTO_ITEM_SET_GENERATED(ti);
2320 ti = proto_tree_add_uint(cr_tree, hf_mac_lte_control_ue_contention_resolution_time_since_msg3,
2321 tvb, 0, 0, crResult->msSinceMsg3);
2322 PROTO_ITEM_SET_GENERATED(ti);
2324 ti = proto_tree_add_boolean(cr_tree, hf_mac_lte_control_ue_contention_resolution_msg3_matched,
2326 PROTO_ITEM_SET_GENERATED(ti);
2327 proto_item_append_text(cr_ti, " (matches Msg3 from frame %u, %ums ago)",
2328 crResult->msg3FrameNum, crResult->msSinceMsg3);
2332 ti = proto_tree_add_uint(cr_tree, hf_mac_lte_control_ue_contention_resolution_msg3,
2333 tvb, 0, 0, crResult->msg3FrameNum);
2334 PROTO_ITEM_SET_GENERATED(ti);
2335 ti = proto_tree_add_uint(cr_tree, hf_mac_lte_control_ue_contention_resolution_time_since_msg3,
2336 tvb, 0, 0, crResult->msSinceMsg3);
2337 PROTO_ITEM_SET_GENERATED(ti);
2339 ti = proto_tree_add_boolean(cr_tree, hf_mac_lte_control_ue_contention_resolution_msg3_matched,
2341 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
2342 "CR body in Msg4 doesn't match Msg3 CCCH in frame %u",
2343 crResult->msg3FrameNum);
2344 PROTO_ITEM_SET_GENERATED(ti);
2345 proto_item_append_text(cr_ti, " (doesn't match Msg3 from frame %u, %u ago)",
2346 crResult->msg3FrameNum, crResult->msSinceMsg3);
2353 case TIMING_ADVANCE_LCID:
2356 proto_item *reserved_ti;
2360 /* Check 2 reserved bits */
2361 reserved = (tvb_get_guint8(tvb, offset) & 0xc0) >> 6;
2362 reserved_ti = proto_tree_add_item(tree, hf_mac_lte_control_timing_advance_reserved, tvb, offset, 1, FALSE);
2363 if (reserved != 0) {
2364 expert_add_info_format(pinfo, reserved_ti, PI_MALFORMED, PI_ERROR,
2365 "Timing Advance Reserved bits not zero (found 0x%x)", reserved);
2369 ta_value = tvb_get_guint8(tvb, offset) & 0x3f;
2370 ta_ti = proto_tree_add_item(tree, hf_mac_lte_control_timing_advance,
2371 tvb, offset, 1, FALSE);
2373 if (ta_value == 31) {
2374 expert_add_info_format(pinfo, ta_ti, PI_SEQUENCE,
2376 "Timing Advance control element received (no correction needed)");
2379 expert_add_info_format(pinfo, ta_ti, PI_SEQUENCE,
2381 "Timing Advance control element received (%u) %s correction needed",
2383 (ta_value < 31) ? "-ve" : "+ve");
2388 case DRX_COMMAND_LCID:
2392 /* No payload (in this position) */
2393 tap_info->padding_bytes++;
2402 /**********************************/
2403 /* UL-SCH Control PDUs */
2405 case POWER_HEADROOM_REPORT_LCID:
2408 proto_tree *phr_tree;
2413 /* Create PHR root */
2414 phr_ti = proto_tree_add_string_format(tree,
2415 hf_mac_lte_control_power_headroom,
2419 phr_tree = proto_item_add_subtree(phr_ti, ett_mac_lte_power_headroom);
2421 /* Check 2 Reserved bits */
2422 reserved = (tvb_get_guint8(tvb, offset) & 0xc0) >> 6;
2423 ti = proto_tree_add_item(phr_tree, hf_mac_lte_control_power_headroom_reserved,
2424 tvb, offset, 1, FALSE);
2425 if (reserved != 0) {
2426 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
2427 "Power Headroom Reserved bits not zero (found 0x%x)", reserved);
2431 level = tvb_get_guint8(tvb, offset) & 0x3f;
2432 proto_tree_add_item(phr_tree, hf_mac_lte_control_power_headroom_level,
2433 tvb, offset, 1, FALSE);
2435 /* Show value in root label */
2436 proto_item_append_text(phr_ti, " (%s)",
2437 val_to_str_const(level, power_headroom_size_vals, "Unknown"));
2444 proto_tree_add_item(tree, hf_mac_lte_control_crnti,
2445 tvb, offset, 2, FALSE);
2448 case TRUNCATED_BSR_LCID:
2449 case SHORT_BSR_LCID:
2451 proto_tree *bsr_tree;
2453 proto_item *buffer_size_ti;
2457 bsr_ti = proto_tree_add_string_format(tree,
2458 hf_mac_lte_control_bsr,
2462 bsr_tree = proto_item_add_subtree(bsr_ti, ett_mac_lte_bsr);
2465 lcgid = (tvb_get_guint8(tvb, offset) & 0xc0) >> 6;
2466 proto_tree_add_item(bsr_tree, hf_mac_lte_control_bsr_lcg_id,
2467 tvb, offset, 1, FALSE);
2469 buffer_size = tvb_get_guint8(tvb, offset) & 0x3f;
2470 buffer_size_ti = proto_tree_add_item(bsr_tree, hf_mac_lte_control_short_bsr_buffer_size,
2471 tvb, offset, 1, FALSE);
2473 if (buffer_size >= global_mac_lte_bsr_warn_threshold) {
2474 expert_add_info_format(pinfo, buffer_size_ti, PI_SEQUENCE, PI_WARN,
2475 "UE %u - BSR for LCG %u exceeds threshold: %u (%s)",
2476 p_mac_lte_info->ueid,
2478 buffer_size, val_to_str_const(buffer_size, buffer_size_vals, "Unknown"));
2482 proto_item_append_text(bsr_ti, " (lcgid=%u %s)",
2484 val_to_str_const(buffer_size, buffer_size_vals, "Unknown"));
2489 proto_tree *bsr_tree;
2491 proto_item *buffer_size_ti;
2492 guint8 buffer_size[4];
2493 bsr_ti = proto_tree_add_string_format(tree,
2494 hf_mac_lte_control_bsr,
2498 bsr_tree = proto_item_add_subtree(bsr_ti, ett_mac_lte_bsr);
2501 buffer_size_ti = proto_tree_add_item(bsr_tree, hf_mac_lte_control_long_bsr_buffer_size_0,
2502 tvb, offset, 1, FALSE);
2503 buffer_size[0] = (tvb_get_guint8(tvb, offset) & 0xfc) >> 2;
2504 if (buffer_size[0] >= global_mac_lte_bsr_warn_threshold) {
2505 expert_add_info_format(pinfo, buffer_size_ti, PI_SEQUENCE, PI_WARN,
2506 "UE %u - BSR for LCG 0 exceeds threshold: %u (%s)",
2507 p_mac_lte_info->ueid,
2508 buffer_size[0], val_to_str_const(buffer_size[0], buffer_size_vals, "Unknown"));
2512 buffer_size_ti = proto_tree_add_item(bsr_tree, hf_mac_lte_control_long_bsr_buffer_size_1,
2513 tvb, offset, 2, FALSE);
2514 buffer_size[1] = ((tvb_get_guint8(tvb, offset) & 0x03) << 4) | ((tvb_get_guint8(tvb, offset+1) & 0xf0) >> 4);
2516 if (buffer_size[1] >= global_mac_lte_bsr_warn_threshold) {
2517 expert_add_info_format(pinfo, buffer_size_ti, PI_SEQUENCE, PI_WARN,
2518 "UE %u - BSR for LCG 1 exceeds threshold: %u (%s)",
2519 p_mac_lte_info->ueid,
2520 buffer_size[1], val_to_str_const(buffer_size[1], buffer_size_vals, "Unknown"));
2524 buffer_size_ti = proto_tree_add_item(bsr_tree, hf_mac_lte_control_long_bsr_buffer_size_2,
2525 tvb, offset, 2, FALSE);
2527 buffer_size[2] = ((tvb_get_guint8(tvb, offset) & 0x0f) << 2) | ((tvb_get_guint8(tvb, offset+1) & 0xc0) >> 6);
2529 if (buffer_size[2] >= global_mac_lte_bsr_warn_threshold) {
2530 expert_add_info_format(pinfo, buffer_size_ti, PI_SEQUENCE, PI_WARN,
2531 "UE %u - BSR for LCG 2 exceeds threshold: %u (%s)",
2532 p_mac_lte_info->ueid,
2533 buffer_size[2], val_to_str_const(buffer_size[2], buffer_size_vals, "Unknown"));
2537 buffer_size_ti = proto_tree_add_item(bsr_tree, hf_mac_lte_control_long_bsr_buffer_size_3,
2538 tvb, offset, 1, FALSE);
2539 buffer_size[3] = tvb_get_guint8(tvb, offset) & 0x3f;
2541 if (buffer_size[3] >= global_mac_lte_bsr_warn_threshold) {
2542 expert_add_info_format(pinfo, buffer_size_ti, PI_SEQUENCE, PI_WARN,
2543 "UE %u - BSR for LCG 3 exceeds threshold: %u (%s)",
2544 p_mac_lte_info->ueid,
2545 buffer_size[3], val_to_str_const(buffer_size[3], buffer_size_vals, "Unknown"));
2548 /* Append summary to parent */
2549 proto_item_append_text(bsr_ti, " 0:(%s) 1:(%s) 2:(%s) 3:(%s)",
2550 val_to_str_const(buffer_size[0], buffer_size_vals, "Unknown"),
2551 val_to_str_const(buffer_size[1], buffer_size_vals, "Unknown"),
2552 val_to_str_const(buffer_size[2], buffer_size_vals, "Unknown"),
2553 val_to_str_const(buffer_size[3], buffer_size_vals, "Unknown"));
2557 /* No payload, in this position */
2558 tap_info->padding_bytes++;
2568 /* There might not be any data, if only headers (plus control data) were logged */
2569 is_truncated = ((tvb_length_remaining(tvb, offset) == 0) && expecting_body_data);
2570 truncated_ti = proto_tree_add_uint(tree, hf_mac_lte_sch_header_only, tvb, 0, 0,
2573 PROTO_ITEM_SET_GENERATED(truncated_ti);
2574 expert_add_info_format(pinfo, truncated_ti, PI_SEQUENCE, PI_NOTE,
2575 "MAC PDU SDUs have been omitted");
2579 PROTO_ITEM_SET_HIDDEN(truncated_ti);
2583 /* Now process remaining bodies, which should all be data */
2584 for (; n < number_of_headers; n++) {
2586 /* Data SDUs treated identically for Uplink or downlink channels */
2588 const guint8 *pdu_data;
2589 volatile guint16 data_length;
2593 /* Break out if meet padding */
2594 if (lcids[n] == PADDING_LCID) {
2598 /* Work out length */
2599 data_length = (pdu_lengths[n] == -1) ?
2600 tvb_length_remaining(tvb, offset) :
2603 /* Dissect SDU as raw bytes */
2604 sdu_ti = proto_tree_add_bytes_format(tree, hf_mac_lte_sch_sdu, tvb, offset, pdu_lengths[n],
2605 tvb_get_ptr(tvb, offset, pdu_lengths[n]),
2606 "SDU (%s, length=%u bytes): ",
2607 val_to_str_const(lcids[n],
2608 (direction == DIRECTION_UPLINK) ?
2613 /* Show bytes too. There must be a nicer way of doing this! */
2614 pdu_data = tvb_get_ptr(tvb, offset, pdu_lengths[n]);
2615 for (i=0; i < data_length; i++) {
2616 g_snprintf(buff+(i*2), 3, "%02x", pdu_data[i]);
2618 g_snprintf(buff+(i*2), 4, "...");
2622 proto_item_append_text(sdu_ti, "%s", buff);
2625 /* Look for Msg3 data so that it may be compared with later
2626 Contention Resolution body */
2627 if ((lcids[n] == 0) && (direction == DIRECTION_UPLINK) && (data_length == 6)) {
2628 if (!pinfo->fd->flags.visited) {
2629 guint key = p_mac_lte_info->rnti;
2630 Msg3Data *data = g_hash_table_lookup(mac_lte_msg3_hash, GUINT_TO_POINTER(key));
2632 /* Look for previous entry for this UE */
2634 /* Allocate space for data and add to table */
2635 data = se_alloc(sizeof(Msg3Data));
2636 g_hash_table_insert(mac_lte_msg3_hash, GUINT_TO_POINTER(key), data);
2639 /* Fill in data details */
2640 data->framenum = pinfo->fd->num;
2641 memcpy(&data->data, tvb_get_ptr(tvb, offset, data_length), data_length);
2642 data->msg3Time = pinfo->fd->abs_ts;
2646 /* CCCH frames can be dissected directly by LTE RRC... */
2647 if ((lcids[n] == 0) && global_mac_lte_attempt_rrc_decode) {
2648 tvbuff_t *rrc_tvb = tvb_new_subset(tvb, offset, data_length, data_length);
2650 /* Get appropriate dissector handle */
2651 volatile dissector_handle_t protocol_handle = 0;
2652 if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
2653 protocol_handle = find_dissector("lte_rrc.ul_ccch");
2656 protocol_handle = find_dissector("lte_rrc.dl_ccch");
2659 /* Hide raw view of bytes */
2660 PROTO_ITEM_SET_HIDDEN(sdu_ti);
2662 /* Call it (catch exceptions so that stats will be updated) */
2664 call_dissector_only(protocol_handle, rrc_tvb, pinfo, tree);
2671 /* LCID 1 and 2 can be assumed to be srb1&2, so can dissect as RLC AM */
2672 if ((lcids[n] == 1) || (lcids[n] == 2)) {
2673 if (global_mac_lte_attempt_srb_decode) {
2674 /* Call RLC dissector */
2675 call_rlc_dissector(tvb, pinfo, tree, pdu_ti, offset, data_length,
2676 RLC_AM_MODE, direction, p_mac_lte_info->ueid,
2677 CHANNEL_TYPE_SRB, lcids[n], 0);
2679 /* Hide raw view of bytes */
2680 PROTO_ITEM_SET_HIDDEN(sdu_ti);
2684 else if ((lcids[n] >= 2) && (lcids[n] <= 10)) {
2686 /* Look for mapping for this LCID to drb channel set by UAT table */
2687 rlc_channel_type_t rlc_channel_type = rlcRaw;
2688 guint8 UM_seqnum_length = 0;
2692 for (m=0; m < num_lcid_drb_mappings; m++) {
2693 if (lcids[n] == lcid_drb_mappings[m].lcid) {
2695 rlc_channel_type = lcid_drb_mappings[m].channel_type;
2697 /* Set UM_seqnum_length */
2698 switch (lcid_drb_mappings[m].channel_type) {
2700 UM_seqnum_length = 5;
2703 UM_seqnum_length = 10;
2710 drb_id = lcid_drb_mappings[m].drbid;
2715 /* Dissect according to channel type */
2716 switch (rlc_channel_type) {
2718 call_rlc_dissector(tvb, pinfo, tree, pdu_ti, offset, data_length,
2719 RLC_UM_MODE, direction, p_mac_lte_info->ueid,
2720 CHANNEL_TYPE_DRB, (guint16)drb_id, UM_seqnum_length);
2723 call_rlc_dissector(tvb, pinfo, tree, pdu_ti, offset, data_length,
2724 RLC_UM_MODE, direction, p_mac_lte_info->ueid,
2725 CHANNEL_TYPE_DRB, (guint16)drb_id, UM_seqnum_length);
2728 call_rlc_dissector(tvb, pinfo, tree, pdu_ti, offset, data_length,
2729 RLC_AM_MODE, direction, p_mac_lte_info->ueid,
2730 CHANNEL_TYPE_DRB, (guint16)drb_id, 0);
2733 call_rlc_dissector(tvb, pinfo, tree, pdu_ti, offset, data_length,
2734 RLC_TM_MODE, direction, p_mac_lte_info->ueid,
2735 CHANNEL_TYPE_DRB, (guint16)drb_id, 0);
2738 /* Nothing to do! */
2742 if (rlc_channel_type != rlcRaw) {
2743 /* Hide raw view of bytes */
2744 PROTO_ITEM_SET_HIDDEN(sdu_ti);
2749 offset += data_length;
2751 /* Update tap byte count for this channel */
2752 tap_info->bytes_for_lcid[lcids[n]] += data_length;
2753 tap_info->sdus_for_lcid[lcids[n]]++;
2756 /* Now padding, if present, extends to the end of the PDU */
2757 if (lcids[number_of_headers-1] == PADDING_LCID) {
2758 if (tvb_length_remaining(tvb, offset) > 0) {
2759 proto_tree_add_item(tree, hf_mac_lte_padding_data,
2760 tvb, offset, -1, FALSE);
2762 padding_length_ti = proto_tree_add_int(tree, hf_mac_lte_padding_length,
2764 p_mac_lte_info->length - offset);
2765 PROTO_ITEM_SET_GENERATED(padding_length_ti);
2767 /* Update padding bytes in stats */
2768 tap_info->padding_bytes += (p_mac_lte_info->length - offset);
2770 /* Make sure the PDU isn't bigger than reported! */
2771 if (offset > p_mac_lte_info->length) {
2772 expert_add_info_format(pinfo, padding_length_ti, PI_MALFORMED, PI_ERROR,
2773 "MAC PDU is longer than reported length (reported=%u, actual=%u)",
2774 p_mac_lte_info->length, offset);
2778 /* There is no padding at the end of the frame */
2779 if (!is_truncated && (offset < p_mac_lte_info->length)) {
2780 /* There is a problem if we haven't used all of the PDU */
2781 expert_add_info_format(pinfo, pdu_ti, PI_MALFORMED, PI_ERROR,
2782 "PDU for UE %u is shorter than reported length (reported=%u, actual=%u)",
2783 p_mac_lte_info->ueid, p_mac_lte_info->length, offset);
2786 if (!is_truncated && (offset > p_mac_lte_info->length)) {
2787 /* There is a problem if the PDU is longer than rpeported */
2788 expert_add_info_format(pinfo, pdu_ti, PI_MALFORMED, PI_ERROR,
2789 "PDU for UE %u is longer than reported length (reported=%u, actual=%u)",
2790 p_mac_lte_info->ueid, p_mac_lte_info->length, offset);
2797 /*****************************/
2798 /* Main dissection function. */
2799 void dissect_mac_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2801 proto_tree *mac_lte_tree;
2803 proto_tree *context_tree;
2804 proto_item *context_ti;
2805 proto_item *retx_ti = NULL;
2808 struct mac_lte_info *p_mac_lte_info = NULL;
2811 static mac_lte_tap_info tap_info;
2812 memset(&tap_info, 0, sizeof(mac_lte_tap_info));
2814 /* Set protocol name */
2815 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MAC-LTE");
2817 /* Create protocol tree. */
2818 pdu_ti = proto_tree_add_item(tree, proto_mac_lte, tvb, offset, -1, FALSE);
2819 proto_item_append_text(pdu_ti, " ");
2820 mac_lte_tree = proto_item_add_subtree(pdu_ti, ett_mac_lte);
2823 /* Look for packet info! */
2824 p_mac_lte_info = p_get_proto_data(pinfo->fd, proto_mac_lte);
2826 /* Can't dissect anything without it... */
2827 if (p_mac_lte_info == NULL) {
2829 proto_tree_add_text(mac_lte_tree, tvb, offset, -1,
2830 "Can't dissect LTE MAC frame because no per-frame info was attached!");
2831 PROTO_ITEM_SET_GENERATED(tii);
2835 /* Clear info column */
2836 col_clear(pinfo->cinfo, COL_INFO);
2839 /*****************************************/
2840 /* Show context information */
2842 /* Create context root */
2843 context_ti = proto_tree_add_string_format(mac_lte_tree, hf_mac_lte_context,
2844 tvb, offset, 0, "", "Context");
2845 context_tree = proto_item_add_subtree(context_ti, ett_mac_lte_context);
2846 PROTO_ITEM_SET_GENERATED(context_ti);
2848 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_radio_type,
2849 tvb, 0, 0, p_mac_lte_info->radioType);
2850 PROTO_ITEM_SET_GENERATED(ti);
2852 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_direction,
2853 tvb, 0, 0, p_mac_lte_info->direction);
2854 PROTO_ITEM_SET_GENERATED(ti);
2856 if (p_mac_lte_info->ueid != 0) {
2857 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_ueid,
2858 tvb, 0, 0, p_mac_lte_info->ueid);
2859 PROTO_ITEM_SET_GENERATED(ti);
2862 /* There are several out-of-band MAC events that may be indicated in the context info. */
2863 /* Handle them here */
2864 if (p_mac_lte_info->length == 0) {
2865 proto_item *preamble_ti;
2866 proto_tree *preamble_tree;
2868 switch (p_mac_lte_info->oob_event) {
2869 case ltemac_send_preamble:
2870 preamble_ti = proto_tree_add_item(mac_lte_tree, hf_mac_lte_oob_send_preamble,
2872 preamble_tree = proto_item_add_subtree(preamble_ti, ett_mac_lte_oob);
2873 PROTO_ITEM_SET_GENERATED(ti);
2875 ti = proto_tree_add_uint(preamble_tree, hf_mac_lte_context_rapid,
2876 tvb, 0, 0, p_mac_lte_info->rapid);
2877 PROTO_ITEM_SET_GENERATED(ti);
2879 ti = proto_tree_add_uint(preamble_tree, hf_mac_lte_context_rach_attempt_number,
2880 tvb, 0, 0, p_mac_lte_info->rach_attempt_number);
2881 PROTO_ITEM_SET_GENERATED(ti);
2884 write_pdu_label_and_info(pdu_ti, preamble_ti, pinfo,
2885 "RACH Preamble sent for UE %u (RAPID=%u, attempt=%u)",
2886 p_mac_lte_info->ueid, p_mac_lte_info->rapid, p_mac_lte_info->rach_attempt_number);
2888 /* Add expert info (a note, unless attempt > 1) */
2889 expert_add_info_format(pinfo, ti, PI_SEQUENCE,
2890 (p_mac_lte_info->rach_attempt_number > 1) ? PI_WARN : PI_NOTE,
2891 "RACH Preamble sent for UE %u (RAPID=%u, attempt=%u)",
2892 p_mac_lte_info->ueid, p_mac_lte_info->rapid,
2893 p_mac_lte_info->rach_attempt_number);
2895 case ltemac_send_sr:
2896 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_rnti,
2897 tvb, 0, 0, p_mac_lte_info->rnti);
2898 PROTO_ITEM_SET_GENERATED(ti);
2900 ti = proto_tree_add_item(mac_lte_tree, hf_mac_lte_oob_send_sr,
2902 PROTO_ITEM_SET_GENERATED(ti);
2905 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
2906 "Scheduling Request sent for UE %u (C-RNTI=%u)",
2907 p_mac_lte_info->ueid, p_mac_lte_info->rnti);
2909 /* Add expert info (an note) */
2910 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_NOTE,
2911 "Scheduling Request send for UE %u (RNTI %u)",
2912 p_mac_lte_info->ueid, p_mac_lte_info->rnti);
2914 /* Update SR status */
2915 if (global_mac_lte_track_sr) {
2916 TrackSRInfo(SR_Request, pinfo, mac_lte_tree, tvb, p_mac_lte_info->rnti, ti);
2919 case ltemac_sr_failure:
2920 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_rnti,
2921 tvb, 0, 0, p_mac_lte_info->rnti);
2922 PROTO_ITEM_SET_GENERATED(ti);
2924 ti = proto_tree_add_item(mac_lte_tree, hf_mac_lte_oob_sr_failure,
2926 PROTO_ITEM_SET_GENERATED(ti);
2929 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
2930 "Scheduling Request FAILED for UE %u (C-RNTI=%u)",
2931 p_mac_lte_info->ueid,
2932 p_mac_lte_info->rnti);
2934 /* Add expert info (an error) */
2935 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_ERROR,
2936 "Scheduling Request failed for UE %u (RNTI %u)",
2937 p_mac_lte_info->ueid,
2938 p_mac_lte_info->rnti);
2940 /* Update SR status */
2941 if (global_mac_lte_track_sr) {
2942 TrackSRInfo(SR_Failure, pinfo, mac_lte_tree, tvb, p_mac_lte_info->rnti, ti);
2948 /* Our work here is done */
2953 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_subframe_number,
2954 tvb, 0, 0, p_mac_lte_info->subframeNumber);
2955 PROTO_ITEM_SET_GENERATED(ti);
2956 if (p_mac_lte_info->subframeNumber > 9) {
2957 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
2958 "Subframe number was out of range - using max (9) instead");
2959 p_mac_lte_info->subframeNumber = 9;
2962 if (p_mac_lte_info->rntiType != NO_RNTI) {
2963 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_rnti,
2964 tvb, 0, 0, p_mac_lte_info->rnti);
2965 PROTO_ITEM_SET_GENERATED(ti);
2968 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_rnti_type,
2969 tvb, 0, 0, p_mac_lte_info->rntiType);
2970 PROTO_ITEM_SET_GENERATED(ti);
2972 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_predefined_frame,
2973 tvb, 0, 0, p_mac_lte_info->isPredefinedData);
2974 if (p_mac_lte_info->isPredefinedData) {
2975 PROTO_ITEM_SET_GENERATED(ti);
2978 PROTO_ITEM_SET_HIDDEN(ti);
2981 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_length,
2982 tvb, 0, 0, p_mac_lte_info->length);
2983 PROTO_ITEM_SET_GENERATED(ti);
2984 /* Infer uplink grant size */
2985 if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
2986 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_ul_grant_size,
2987 tvb, 0, 0, p_mac_lte_info->length);
2988 PROTO_ITEM_SET_GENERATED(ti);
2991 /* Retx count goes in top-level tree to make it more visible */
2992 if (p_mac_lte_info->reTxCount) {
2993 retx_ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_context_retx_count,
2994 tvb, 0, 0, p_mac_lte_info->reTxCount);
2995 PROTO_ITEM_SET_GENERATED(retx_ti);
2997 if (p_mac_lte_info->reTxCount >= global_mac_lte_retx_counter_trigger) {
2998 expert_add_info_format(pinfo, retx_ti, PI_SEQUENCE, PI_ERROR,
2999 "UE %u: UL MAC frame ReTX no. %u",
3000 p_mac_lte_info->ueid, p_mac_lte_info->reTxCount);
3004 if (p_mac_lte_info->crcStatusValid) {
3005 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_crc_status,
3006 tvb, 0, 0, p_mac_lte_info->detailed_phy_info.dl_info.crc_status);
3007 PROTO_ITEM_SET_GENERATED(ti);
3008 if (p_mac_lte_info->detailed_phy_info.dl_info.crc_status != TRUE) {
3009 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
3010 "%s Frame has CRC error",
3011 (p_mac_lte_info->direction == DIRECTION_UPLINK) ? "UL" : "DL");
3012 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
3013 "%s: <CRC FAILURE> UEId=%u %s=%u ",
3014 (p_mac_lte_info->direction == DIRECTION_UPLINK) ? "UL" : "DL",
3015 p_mac_lte_info->ueid,
3016 val_to_str_const(p_mac_lte_info->rntiType, rnti_type_vals,
3017 "Unknown RNTI type"),
3018 p_mac_lte_info->rnti);
3022 /* May also have extra Physical layer attributes set for this frame */
3023 show_extra_phy_parameters(pinfo, tvb, mac_lte_tree, p_mac_lte_info);
3025 /* Set context-info parts of tap struct */
3026 tap_info.rnti = p_mac_lte_info->rnti;
3027 tap_info.ueid = p_mac_lte_info->ueid;
3028 tap_info.rntiType = p_mac_lte_info->rntiType;
3029 tap_info.isPredefinedData = p_mac_lte_info->isPredefinedData;
3030 tap_info.isPHYRetx = (p_mac_lte_info->reTxCount >= 1);
3031 tap_info.crcStatusValid = p_mac_lte_info->crcStatusValid;
3032 tap_info.crcStatus = p_mac_lte_info->detailed_phy_info.dl_info.crc_status;
3033 tap_info.direction = p_mac_lte_info->direction;
3035 /* Also set total number of bytes (won't be used for UL/DL-SCH) */
3036 tap_info.single_number_of_bytes = tvb_length_remaining(tvb, offset);
3038 /* If we know its predefined data, don't try to decode any further */
3039 if (p_mac_lte_info->isPredefinedData) {
3040 proto_tree_add_item(mac_lte_tree, hf_mac_lte_predefined_pdu, tvb, offset, -1, FALSE);
3041 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
3042 "Predefined data (%u bytes)",
3043 tvb_length_remaining(tvb, offset));
3045 /* Queue tap info */
3046 if (!pinfo->in_error_pkt) {
3047 tap_queue_packet(mac_lte_tap, pinfo, &tap_info);
3053 /* IF CRC status failed, just do decode as raw bytes */
3054 if (!global_mac_lte_dissect_crc_failures &&
3055 (p_mac_lte_info->crcStatusValid && !p_mac_lte_info->detailed_phy_info.dl_info.crc_status)) {
3057 proto_tree_add_item(mac_lte_tree, hf_mac_lte_raw_pdu, tvb, offset, -1, FALSE);
3058 write_pdu_label_and_info(pdu_ti, NULL, pinfo, "Raw data (%u bytes)", tvb_length_remaining(tvb, offset));
3061 TODO: unfortunately DL retx detection won't get done if we return here... */
3062 if (!pinfo->in_error_pkt) {
3063 tap_queue_packet(mac_lte_tap, pinfo, &tap_info);
3069 /* Reset this counter */
3070 s_number_of_rlc_pdus_shown = 0;
3072 /* Dissect the MAC PDU itself. Format depends upon RNTI type. */
3073 switch (p_mac_lte_info->rntiType) {
3077 dissect_pch(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info->direction);
3082 dissect_rar(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info, &tap_info);
3087 /* Can be UL-SCH or DL-SCH */
3088 dissect_ulsch_or_dlsch(tvb, pinfo, mac_lte_tree, pdu_ti, offset,
3089 p_mac_lte_info->direction, p_mac_lte_info, &tap_info,
3090 retx_ti, context_tree);
3094 /* BCH over DL-SCH */
3095 dissect_bch(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info);
3099 /* Must be BCH over BCH... */
3100 dissect_bch(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info);
3108 /* Queue tap info */
3109 tap_queue_packet(mac_lte_tap, pinfo, &tap_info);
3115 /* Initializes the hash table and the mem_chunk area each time a new
3116 * file is loaded or re-loaded in wireshark */
3118 mac_lte_init_protocol(void)
3120 /* Destroy any existing tables. */
3121 if (mac_lte_msg3_hash) {
3122 g_hash_table_destroy(mac_lte_msg3_hash);
3124 if (mac_lte_cr_result_hash) {
3125 g_hash_table_destroy(mac_lte_cr_result_hash);
3128 if (mac_lte_dl_harq_hash) {
3129 g_hash_table_destroy(mac_lte_dl_harq_hash);
3131 if (mac_lte_dl_harq_result_hash) {
3132 g_hash_table_destroy(mac_lte_dl_harq_result_hash);
3134 if (mac_lte_ul_harq_hash) {
3135 g_hash_table_destroy(mac_lte_ul_harq_hash);
3137 if (mac_lte_ul_harq_result_hash) {
3138 g_hash_table_destroy(mac_lte_ul_harq_result_hash);
3140 if (mac_lte_ue_sr_state) {
3141 g_hash_table_destroy(mac_lte_ue_sr_state);
3143 if (mac_lte_sr_request_hash) {
3144 g_hash_table_destroy(mac_lte_sr_request_hash);
3147 /* Now create them over */
3148 mac_lte_msg3_hash = g_hash_table_new(mac_lte_rnti_hash_func, mac_lte_rnti_hash_equal);
3149 mac_lte_cr_result_hash = g_hash_table_new(mac_lte_framenum_hash_func, mac_lte_framenum_hash_equal);
3151 mac_lte_dl_harq_hash = g_hash_table_new(mac_lte_rnti_hash_func, mac_lte_rnti_hash_equal);
3152 mac_lte_dl_harq_result_hash = g_hash_table_new(mac_lte_framenum_hash_func, mac_lte_framenum_hash_equal);
3154 mac_lte_ul_harq_hash = g_hash_table_new(mac_lte_rnti_hash_func, mac_lte_rnti_hash_equal);
3155 mac_lte_ul_harq_result_hash = g_hash_table_new(mac_lte_framenum_hash_func, mac_lte_framenum_hash_equal);
3157 mac_lte_ue_sr_state = g_hash_table_new(mac_lte_rnti_hash_func, mac_lte_rnti_hash_equal);
3158 mac_lte_sr_request_hash = g_hash_table_new(mac_lte_framenum_hash_func, mac_lte_framenum_hash_equal);
3162 static void* lcid_drb_mapping_copy_cb(void* dest, const void* orig, unsigned len _U_)
3164 const lcid_drb_mapping_t *o = orig;
3165 lcid_drb_mapping_t *d = dest;
3167 /* Copy all items over */
3169 d->drbid = o->drbid;
3170 d->channel_type = o->channel_type;
3177 void proto_register_mac_lte(void)
3179 static hf_register_info hf[] =
3181 /**********************************/
3182 /* Items for decoding context */
3183 { &hf_mac_lte_context,
3185 "mac-lte.context", FT_STRING, BASE_NONE, NULL, 0x0,
3189 { &hf_mac_lte_context_radio_type,
3191 "mac-lte.radio-type", FT_UINT8, BASE_DEC, VALS(radio_type_vals), 0x0,
3195 { &hf_mac_lte_context_direction,
3197 "mac-lte.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
3198 "Direction of message", HFILL
3201 { &hf_mac_lte_context_rnti,
3203 "mac-lte.rnti", FT_UINT16, BASE_DEC, 0, 0x0,
3204 "RNTI associated with message", HFILL
3207 { &hf_mac_lte_context_rnti_type,
3209 "mac-lte.rnti-type", FT_UINT8, BASE_DEC, VALS(rnti_type_vals), 0x0,
3210 "Type of RNTI associated with message", HFILL
3213 { &hf_mac_lte_context_ueid,
3215 "mac-lte.ueid", FT_UINT16, BASE_DEC, 0, 0x0,
3216 "User Equipment Identifier associated with message", HFILL
3219 { &hf_mac_lte_context_subframe_number,
3221 "mac-lte.subframe", FT_UINT16, BASE_DEC, 0, 0x0,
3222 "Subframe number associated with message", HFILL
3225 { &hf_mac_lte_context_grant_subframe_number,
3227 "mac-lte.grant-subframe", FT_UINT16, BASE_DEC, 0, 0x0,
3228 "Subframe grant for this PDU was received", HFILL
3231 { &hf_mac_lte_context_predefined_frame,
3232 { "Predefined frame",
3233 "mac-lte.is-predefined-frame", FT_UINT8, BASE_DEC, VALS(predefined_frame_vals), 0x0,
3234 "Predefined test frame (or real MAC PDU)", HFILL
3237 { &hf_mac_lte_context_length,
3238 { "Length of frame",
3239 "mac-lte.length", FT_UINT8, BASE_DEC, 0, 0x0,
3240 "Original length of frame (including SDUs and padding)", HFILL
3243 { &hf_mac_lte_context_ul_grant_size,
3244 { "Uplink grant size",
3245 "mac-lte.ul-grant-size", FT_UINT8, BASE_DEC, 0, 0x0,
3246 "Uplink grant size (in bytes)", HFILL
3249 { &hf_mac_lte_context_bch_transport_channel,
3250 { "Transport channel",
3251 "mac-lte.bch-transport-channel", FT_UINT8, BASE_DEC, VALS(bch_transport_channel_vals), 0x0,
3252 "Transport channel BCH data was carried on", HFILL
3255 { &hf_mac_lte_context_retx_count,
3257 "mac-lte.retx-count", FT_UINT8, BASE_DEC, 0, 0x0,
3258 "Number of times this PDU has been retransmitted", HFILL
3261 { &hf_mac_lte_context_crc_status,
3263 "mac-lte.crc-status", FT_UINT8, BASE_DEC, VALS(crc_status_vals), 0x0,
3264 "CRC Status as reported by PHY", HFILL
3267 { &hf_mac_lte_context_rapid,
3269 "mac-lte.preamble-sent.rapid", FT_UINT8, BASE_DEC, 0, 0x0,
3270 "RAPID sent in RACH preamble", HFILL
3273 { &hf_mac_lte_context_rach_attempt_number,
3274 { "RACH Attempt Number",
3275 "mac-lte.preamble-sent.attempt", FT_UINT8, BASE_DEC, 0, 0x0,
3276 "RACH attempt number", HFILL
3280 /* Extra PHY context */
3281 { &hf_mac_lte_context_phy_ul,
3282 { "UL PHY attributes",
3283 "mac-lte.ul-phy", FT_STRING, BASE_NONE, 0, 0x0,
3287 { &hf_mac_lte_context_phy_ul_modulation_type,
3288 { "Modulation type",
3289 "mac-lte.ul-phy.modulation-type", FT_UINT8, BASE_DEC, VALS(modulation_type_vals), 0x0,
3293 { &hf_mac_lte_context_phy_ul_tbs_index,
3295 "mac-lte.ul-phy.tbs-index", FT_UINT8, BASE_DEC, 0, 0x0,
3299 { &hf_mac_lte_context_phy_ul_resource_block_length,
3300 { "Resource Block Length",
3301 "mac-lte.ul-phy.resource-block-length", FT_UINT8, BASE_DEC, 0, 0x0,
3305 { &hf_mac_lte_context_phy_ul_resource_block_start,
3306 { "Resource Block Start",
3307 "mac-lte.ul-phy.resource-block-start", FT_UINT8, BASE_DEC, 0, 0x0,
3313 { &hf_mac_lte_context_phy_dl,
3314 { "DL PHY attributes",
3315 "mac-lte.dl-phy", FT_STRING, BASE_NONE, 0, 0x0,
3319 { &hf_mac_lte_context_phy_dl_dci_format,
3321 "mac-lte.dl-phy.dci-format", FT_UINT8, BASE_DEC, VALS(dci_format_vals), 0x0,
3325 { &hf_mac_lte_context_phy_dl_resource_allocation_type,
3326 { "Resource Allocation Type",
3327 "mac-lte.dl-phy.resource-allocation-type", FT_UINT8, BASE_DEC, 0, 0x0,
3331 { &hf_mac_lte_context_phy_dl_aggregation_level,
3332 { "Aggregation Level",
3333 "mac-lte.dl-phy.aggregation-level", FT_UINT8, BASE_DEC, VALS(aggregation_level_vals), 0x0,
3337 { &hf_mac_lte_context_phy_dl_mcs_index,
3339 "mac-lte.dl-phy.mcs-index", FT_UINT8, BASE_DEC, 0, 0x0,
3343 { &hf_mac_lte_context_phy_dl_redundancy_version_index,
3345 "mac-lte.dl-phy.rv-index", FT_UINT8, BASE_DEC, 0, 0x0,
3349 { &hf_mac_lte_context_phy_dl_resource_block_length,
3351 "mac-lte.dl-phy.rb-length", FT_UINT8, BASE_DEC, 0, 0x0,
3355 { &hf_mac_lte_context_phy_dl_crc_status,
3357 "mac-lte.dl-phy.crc-status", FT_UINT8, BASE_DEC, VALS(crc_status_vals), 0x0,
3362 /* Out-of-band events */
3363 { &hf_mac_lte_oob_send_preamble,
3365 "mac-lte.preamble-sent", FT_STRING, BASE_NONE, NULL, 0x0,
3369 { &hf_mac_lte_oob_send_sr,
3370 { "Scheduling Request sent",
3371 "mac-lte.sr-req", FT_NONE, BASE_NONE, NULL, 0x0,
3375 { &hf_mac_lte_oob_sr_failure,
3376 { "Scheduling Request failure",
3377 "mac-lte.sr-failure", FT_NONE, BASE_NONE, NULL, 0x0,
3382 /*******************************************/
3383 /* MAC shared channel header fields */
3384 { &hf_mac_lte_ulsch,
3386 "mac-lte.ulsch", FT_STRING, BASE_NONE, NULL, 0x0,
3390 { &hf_mac_lte_ulsch_header,
3392 "mac-lte.ulsch.header", FT_STRING, BASE_NONE, NULL, 0x0,
3396 { &hf_mac_lte_dlsch_header,
3398 "mac-lte.dlsch.header", FT_STRING, BASE_NONE, NULL, 0x0,
3402 { &hf_mac_lte_dlsch,
3404 "mac-lte.dlsch", FT_STRING, BASE_NONE, NULL, 0x0,
3408 { &hf_mac_lte_sch_subheader,
3410 "mac-lte.sch.subheader", FT_STRING, BASE_NONE, NULL, 0x0,
3414 { &hf_mac_lte_sch_reserved,
3415 { "SCH reserved bits",
3416 "mac-lte.sch.reserved", FT_UINT8, BASE_HEX, NULL, 0xc0,
3420 { &hf_mac_lte_sch_extended,
3422 "mac-lte.sch.extended", FT_UINT8, BASE_HEX, 0, 0x20,
3423 "Extension - i.e. further headers after this one", HFILL
3426 { &hf_mac_lte_dlsch_lcid,
3428 "mac-lte.dlsch.lcid", FT_UINT8, BASE_HEX, VALS(dlsch_lcid_vals), 0x1f,
3429 "DL-SCH Logical Channel Identifier", HFILL
3432 { &hf_mac_lte_ulsch_lcid,
3434 "mac-lte.ulsch.lcid", FT_UINT8, BASE_HEX, VALS(ulsch_lcid_vals), 0x1f,
3435 "UL-SCH Logical Channel Identifier", HFILL
3438 { &hf_mac_lte_sch_format,
3440 "mac-lte.sch.format", FT_UINT8, BASE_HEX, VALS(format_vals), 0x80,
3444 { &hf_mac_lte_sch_length,
3446 "mac-lte.sch.length", FT_UINT16, BASE_DEC, 0, 0x0,
3447 "Length of MAC SDU or MAC control element", HFILL
3450 { &hf_mac_lte_sch_header_only,
3451 { "MAC PDU Header only",
3452 "mac-lte.sch.header-only", FT_UINT8, BASE_DEC, VALS(header_only_vals), 0x0,
3457 /********************************/
3459 { &hf_mac_lte_sch_sdu,
3461 "mac-lte.sch.sdu", FT_BYTES, BASE_NONE, 0, 0x0,
3462 "Shared channel SDU", HFILL
3465 { &hf_mac_lte_bch_pdu,
3467 "mac-lte.bch.pdu", FT_BYTES, BASE_NONE, 0, 0x0,
3471 { &hf_mac_lte_pch_pdu,
3473 "mac-lte.pch.pdu", FT_BYTES, BASE_NONE, 0, 0x0,
3477 { &hf_mac_lte_predefined_pdu,
3478 { "Predefined data",
3479 "mac-lte.predefined-data", FT_BYTES, BASE_NONE, 0, 0x0,
3480 "Predefined test data", HFILL
3483 { &hf_mac_lte_raw_pdu,
3485 "mac-lte.raw-data", FT_BYTES, BASE_NONE, 0, 0x0,
3486 "Raw bytes of PDU (e.g. if CRC failed)", HFILL
3489 { &hf_mac_lte_padding_data,
3491 "mac-lte.padding-data", FT_BYTES, BASE_NONE, 0, 0x0,
3495 { &hf_mac_lte_padding_length,
3497 "mac-lte.padding-length", FT_INT32, BASE_DEC, 0, 0x0,
3498 "Length of padding data not included at end of frame", HFILL
3504 /*********************************/
3508 "mac-lte.rar", FT_NONE, BASE_NONE, NULL, 0x0,
3512 { &hf_mac_lte_rar_headers,
3514 "mac-lte.rar.headers", FT_STRING, BASE_NONE, NULL, 0x0,
3518 { &hf_mac_lte_rar_header,
3520 "mac-lte.rar.header", FT_STRING, BASE_NONE, NULL, 0x0,
3524 { &hf_mac_lte_rar_extension,
3526 "mac-lte.rar.e", FT_UINT8, BASE_HEX, 0, 0x80,
3527 "Extension - i.e. further RAR headers after this one", HFILL
3530 { &hf_mac_lte_rar_t,
3532 "mac-lte.rar.t", FT_UINT8, BASE_HEX, VALS(rar_type_vals), 0x40,
3533 "Type field indicating whether the payload is RAPID or BI", HFILL
3536 { &hf_mac_lte_rar_bi,
3538 "mac-lte.rar.bi", FT_UINT8, BASE_HEX, VALS(rar_bi_vals), 0x0f,
3539 "Backoff Indicator (ms)", HFILL
3542 { &hf_mac_lte_rar_rapid,
3544 "mac-lte.rar.rapid", FT_UINT8, BASE_HEX_DEC, 0, 0x3f,
3545 "Random Access Preamble IDentifier", HFILL
3548 { &hf_mac_lte_rar_reserved,
3550 "mac-lte.rar.reserved", FT_UINT8, BASE_HEX, 0, 0x30,
3551 "Reserved bits in RAR header - should be 0", HFILL
3555 { &hf_mac_lte_rar_body,
3557 "mac-lte.rar.body", FT_STRING, BASE_NONE, NULL, 0x0,
3561 { &hf_mac_lte_rar_reserved2,
3563 "mac-lte.rar.reserved2", FT_UINT8, BASE_HEX, 0, 0x80,
3564 "Reserved bit in RAR body - should be 0", HFILL
3567 { &hf_mac_lte_rar_ta,
3569 "mac-lte.rar.ta", FT_UINT16, BASE_DEC, 0, 0x7ff0,
3570 "Required adjustment to uplink transmission timing", HFILL
3573 { &hf_mac_lte_rar_ul_grant,
3575 "mac-lte.rar.ul-grant", FT_UINT24, BASE_DEC, 0, 0x0fffff,
3576 "Size of UL Grant", HFILL
3579 { &hf_mac_lte_rar_ul_grant_hopping,
3581 "mac-lte.rar.ul-grant.hopping", FT_UINT8, BASE_DEC, 0, 0x08,
3585 { &hf_mac_lte_rar_ul_grant_fsrba,
3586 { "Fixed sized resource block assignment",
3587 "mac-lte.rar.ul-grant.fsrba", FT_UINT16, BASE_DEC, 0, 0x07fe,
3591 { &hf_mac_lte_rar_ul_grant_tmcs,
3592 { "Truncated Modulation and coding scheme",
3593 "mac-lte.rar.ul-grant.tmcs", FT_UINT16, BASE_DEC, 0, 0x01e0,
3597 { &hf_mac_lte_rar_ul_grant_tcsp,
3598 { "TPC command for scheduled PUSCH",
3599 "mac-lte.rar.ul-grant.tcsp", FT_UINT8, BASE_DEC, 0, 0x01c,
3603 { &hf_mac_lte_rar_ul_grant_ul_delay,
3605 "mac-lte.rar.ul-grant.ul-delay", FT_UINT8, BASE_DEC, 0, 0x02,
3609 { &hf_mac_lte_rar_ul_grant_cqi_request,
3611 "mac-lte.rar.ul-grant.cqi-request", FT_UINT8, BASE_DEC, 0, 0x01,
3615 { &hf_mac_lte_rar_temporary_crnti,
3616 { "Temporary C-RNTI",
3617 "mac-lte.rar.temporary-crnti", FT_UINT16, BASE_DEC, 0, 0x0,
3622 /**********************/
3623 /* Control PDU fields */
3624 { &hf_mac_lte_control_bsr,
3626 "mac-lte.control.bsr", FT_STRING, BASE_NONE, 0, 0x0,
3627 "Buffer Status Report", HFILL
3630 { &hf_mac_lte_control_bsr_lcg_id,
3631 { "Logical Channel Group ID",
3632 "mac-lte.control.bsr.lcg-id", FT_UINT8, BASE_DEC, 0, 0xc0,
3636 { &hf_mac_lte_control_short_bsr_buffer_size,
3638 "mac-lte.control.bsr.buffer-size", FT_UINT8, BASE_DEC, VALS(buffer_size_vals), 0x3f,
3639 "Buffer Size available in all channels in group", HFILL
3642 { &hf_mac_lte_control_long_bsr_buffer_size_0,
3644 "mac-lte.control.bsr.buffer-size-0", FT_UINT8, BASE_DEC, VALS(buffer_size_vals), 0xfc,
3645 "Buffer Size available in logical channel group 0", HFILL
3648 { &hf_mac_lte_control_long_bsr_buffer_size_1,
3650 "mac-lte.control.bsr.buffer-size-1", FT_UINT16, BASE_DEC, VALS(buffer_size_vals), 0x03f0,
3651 "Buffer Size available in logical channel group 1", HFILL
3654 { &hf_mac_lte_control_long_bsr_buffer_size_2,
3656 "mac-lte.control.bsr.buffer-size-2", FT_UINT16, BASE_DEC, VALS(buffer_size_vals), 0x0fc0,
3657 "Buffer Size available in logical channel group 2", HFILL
3660 { &hf_mac_lte_control_long_bsr_buffer_size_3,
3662 "mac-lte.control.bsr.buffer-size-3", FT_UINT8, BASE_DEC, VALS(buffer_size_vals), 0x3f,
3663 "Buffer Size available in logical channel group 3", HFILL
3666 { &hf_mac_lte_control_crnti,
3668 "mac-lte.control.crnti", FT_UINT16, BASE_DEC, 0, 0x0,
3669 "C-RNTI for the UE", HFILL
3672 { &hf_mac_lte_control_timing_advance,
3674 "mac-lte.control.timing-advance", FT_UINT8, BASE_DEC, 0, 0x3f,
3675 "Timing Advance (0-1282 - see 36.213, 4.2.3)", HFILL
3678 { &hf_mac_lte_control_timing_advance_reserved,
3680 "mac-lte.control.timing-advance.reserved", FT_UINT8, BASE_DEC, 0, 0xc0,
3681 "Reserved bits", HFILL
3684 { &hf_mac_lte_control_ue_contention_resolution,
3685 { "UE Contention Resolution",
3686 "mac-lte.control.ue-contention-resolution", FT_STRING, BASE_NONE, 0, 0x0,
3690 { &hf_mac_lte_control_ue_contention_resolution_identity,
3691 { "UE Contention Resolution Identity",
3692 "mac-lte.control.ue-contention-resolution.identity", FT_BYTES, BASE_NONE, 0, 0x0,
3696 { &hf_mac_lte_control_ue_contention_resolution_msg3,
3698 "mac-lte.control.ue-contention-resolution.msg3", FT_FRAMENUM, BASE_NONE, 0, 0x0,
3702 { &hf_mac_lte_control_ue_contention_resolution_msg3_matched,
3703 { "UE Contention Resolution Matches Msg3",
3704 "mac-lte.control.ue-contention-resolution.matches-msg3", FT_BOOLEAN, BASE_NONE, 0, 0x0,
3708 { &hf_mac_lte_control_ue_contention_resolution_time_since_msg3,
3709 { "Time since Msg3",
3710 "mac-lte.control.ue-contention-resolution.time-since-msg3", FT_UINT32, BASE_DEC, 0, 0x0,
3711 "Time in ms since corresponding Msg3", HFILL
3715 { &hf_mac_lte_control_power_headroom,
3717 "mac-lte.control.power-headroom", FT_STRING, BASE_NONE, 0, 0x0,
3721 { &hf_mac_lte_control_power_headroom_reserved,
3723 "mac-lte.control.power-headroom.reserved", FT_UINT8, BASE_DEC, 0, 0xc0,
3724 "Reserved bits, should be 0", HFILL
3727 { &hf_mac_lte_control_power_headroom_level,
3728 { "Power Headroom Level",
3729 "mac-lte.control.power-headroom.level", FT_UINT8, BASE_DEC,
3730 VALS(power_headroom_size_vals), 0x3f, "Power Headroom Level in dB", HFILL
3734 { &hf_mac_lte_control_padding,
3736 "mac-lte.control.padding", FT_NONE, BASE_NONE, 0, 0x0,
3741 /* Generated fields */
3742 { &hf_mac_lte_context_phy_dl_retx,
3744 "mac-lte.dlsch.retx", FT_BOOLEAN, BASE_DEC, 0, 0x0,
3748 { &hf_mac_lte_suspected_dl_retx_original_frame,
3749 { "Frame with previous tx",
3750 "mac-lte.dlsch.retx.original_frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
3755 { &hf_mac_lte_ul_harq_resend_original_frame,
3756 { "Frame with previous tx",
3757 "mac-lte.ulsch.retx.original-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
3762 { &hf_mac_lte_grant_answering_sr,
3763 { "First Grant Following SR from",
3764 "mac-lte.ulsch.grant-answering-sr", FT_FRAMENUM, BASE_NONE, 0, 0x0,
3768 { &hf_mac_lte_failure_answering_sr,
3769 { "SR which failed",
3770 "mac-lte.ulsch.failure-answering-sr", FT_FRAMENUM, BASE_NONE, 0, 0x0,
3774 { &hf_mac_lte_sr_leading_to_failure,
3776 "mac-lte.ulsch.failure-answering-sr-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
3780 { &hf_mac_lte_sr_leading_to_grant,
3781 { "This SR results in a grant here",
3782 "mac-lte.ulsch.grant-answering-sr-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
3786 { &hf_mac_lte_sr_invalid_event,
3788 "mac-lte.ulsch.sr-invalid-event", FT_NONE, BASE_NONE, 0, 0x0,
3792 { &hf_mac_lte_sr_time_since_request,
3793 { "Time since SR (ms)",
3794 "mac-lte.ulsch.time-since-sr", FT_UINT32, BASE_DEC, 0, 0x0,
3798 { &hf_mac_lte_sr_time_until_answer,
3799 { "Time until answer (ms)",
3800 "mac-lte.ulsch.time-until-sr-answer", FT_UINT32, BASE_DEC, 0, 0x0,
3807 static gint *ett[] =
3810 &ett_mac_lte_context,
3811 &ett_mac_lte_phy_context,
3812 &ett_mac_lte_rar_headers,
3813 &ett_mac_lte_rar_header,
3814 &ett_mac_lte_rar_body,
3815 &ett_mac_lte_rar_ul_grant,
3816 &ett_mac_lte_ulsch_header,
3817 &ett_mac_lte_dlsch_header,
3818 &ett_mac_lte_sch_subheader,
3822 &ett_mac_lte_contention_resolution,
3823 &ett_mac_lte_power_headroom,
3827 static enum_val_t show_info_col_vals[] = {
3828 {"show-phy", "PHY Info", ShowPHYLayer},
3829 {"show-mac", "MAC Info", ShowMACLayer},
3830 {"show-rlc", "RLC Info", ShowRLCLayer},
3834 module_t *mac_lte_module;
3836 static uat_field_t lcid_drb_mapping_flds[] = {
3837 UAT_FLD_VS(lcid_drb_mappings, lcid, "lcid", drb_lcid_vals, "The MAC LCID"),
3838 UAT_FLD_DEC(lcid_drb_mappings, drbid,"drb id (1-32)", "Identifier of logical data channel"),
3839 UAT_FLD_VS(lcid_drb_mappings, channel_type, "RLC Channel Type", rlc_channel_type_vals, "The MAC LCID"),
3843 /* Register protocol. */
3844 proto_mac_lte = proto_register_protocol("MAC-LTE", "MAC-LTE", "mac-lte");
3845 proto_register_field_array(proto_mac_lte, hf, array_length(hf));
3846 proto_register_subtree_array(ett, array_length(ett));
3848 /* Allow other dissectors to find this one by name. */
3849 register_dissector("mac-lte", dissect_mac_lte, proto_mac_lte);
3851 /* Register the tap name */
3852 mac_lte_tap = register_tap("mac-lte");
3855 mac_lte_module = prefs_register_protocol(proto_mac_lte, NULL);
3857 /* Obsolete preferences */
3858 prefs_register_obsolete_preference(mac_lte_module, "single_rar");
3859 prefs_register_obsolete_preference(mac_lte_module, "check_reserved_bits");
3860 prefs_register_obsolete_preference(mac_lte_module, "decode_rar_ul_grant");
3861 prefs_register_obsolete_preference(mac_lte_module, "show_rlc_info_column");
3862 prefs_register_obsolete_preference(mac_lte_module, "attempt_to_detect_dl_harq_resend");
3864 prefs_register_uint_preference(mac_lte_module, "retx_count_warn",
3865 "Number of Re-Transmits before expert warning triggered",
3866 "Number of Re-Transmits before expert warning triggered",
3867 10, &global_mac_lte_retx_counter_trigger);
3869 prefs_register_bool_preference(mac_lte_module, "attempt_rrc_decode",
3870 "Attempt to decode BCH, PCH and CCCH data using LTE RRC dissector",
3871 "Attempt to decode BCH, PCH and CCCH data using LTE RRC dissector",
3872 &global_mac_lte_attempt_rrc_decode);
3874 prefs_register_bool_preference(mac_lte_module, "attempt_to_dissect_crc_failures",
3875 "Dissect frames that have failed CRC check",
3876 "Attempt to dissect frames that have failed CRC check",
3877 &global_mac_lte_dissect_crc_failures);
3879 prefs_register_bool_preference(mac_lte_module, "heuristic_mac_lte_over_udp",
3880 "Try Heuristic LTE-MAC over UDP framing",
3881 "When enabled, use heuristic dissector to find MAC-LTE frames sent with "
3883 &global_mac_lte_heur);
3885 prefs_register_bool_preference(mac_lte_module, "attempt_to_dissect_srb_sdus",
3886 "Attempt to dissect LCID 1&2 as srb1&2",
3887 "Will call LTE RLC dissector with standard settings as per RRC spec",
3888 &global_mac_lte_attempt_srb_decode);
3890 lcid_drb_mappings_uat = uat_new("LCID -> drb Table",
3891 sizeof(lcid_drb_mapping_t),
3894 (void*) &lcid_drb_mappings,
3895 &num_lcid_drb_mappings,
3897 "", /* TODO: is this ref to help manual? */
3898 lcid_drb_mapping_copy_cb,
3902 lcid_drb_mapping_flds );
3904 prefs_register_uat_preference(mac_lte_module,
3906 "LCID -> DRB Mappings Table",
3907 "A table that maps from configurable lcids -> RLC logical channels",
3908 lcid_drb_mappings_uat);
3910 prefs_register_bool_preference(mac_lte_module, "attempt_to_track_ul_harq_resend",
3911 "Attempt to track UL HARQ resends",
3912 "When logging at UE side, will look for original transmission",
3913 &global_mac_lte_attempt_ul_harq_resend_track);
3915 prefs_register_uint_preference(mac_lte_module, "bsr_warn_threshold",
3916 "BSR size when warning should be issued (0 - 63)",
3917 "If any BSR report is >= this number, an expert warning will be added",
3918 10, &global_mac_lte_bsr_warn_threshold);
3920 prefs_register_bool_preference(mac_lte_module, "track_sr",
3921 "Track status of SRs within UEs",
3922 "Track status of SRs, providing links between requests, failure indications and grants",
3923 &global_mac_lte_track_sr);
3925 prefs_register_enum_preference(mac_lte_module, "layer_to_show",
3926 "Which layer info to show in Info column",
3927 "Can show PHY, MAC or RLC layer info in Info column",
3928 &global_mac_lte_layer_to_show, show_info_col_vals, FALSE);
3930 register_init_routine(&mac_lte_init_protocol);
3934 proto_reg_handoff_mac_lte(void)
3936 static dissector_handle_t mac_lte_handle;
3937 if (!mac_lte_handle) {
3938 mac_lte_handle = find_dissector("mac-lte");
3940 /* Add as a heuristic UDP dissector */
3941 heur_dissector_add("udp", dissect_mac_lte_heur, proto_mac_lte);