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?
47 - include detected DL retransmits in stats?
50 /* Initialize the protocol and registered fields. */
51 int proto_mac_lte = -1;
53 static int mac_lte_tap = -1;
55 /* Decoding context */
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_predefined_frame = -1;
63 static int hf_mac_lte_context_length = -1;
64 static int hf_mac_lte_context_ul_grant_size = -1;
65 static int hf_mac_lte_context_bch_transport_channel = -1;
66 static int hf_mac_lte_context_retx_count = -1;
67 static int hf_mac_lte_context_crc_status = -1;
68 static int hf_mac_lte_context_rapid = -1;
69 static int hf_mac_lte_context_rach_attempt_number = -1;
71 /* Out-of-band events */
72 static int hf_mac_lte_oob_send_preamble = -1;
73 static int hf_mac_lte_oob_send_sr = -1;
74 static int hf_mac_lte_oob_sr_failure = -1;
76 /* MAC SCH header fields */
77 static int hf_mac_lte_ulsch_header = -1;
78 static int hf_mac_lte_dlsch_header = -1;
79 static int hf_mac_lte_sch_subheader = -1;
81 static int hf_mac_lte_sch_reserved = -1;
82 static int hf_mac_lte_dlsch_lcid = -1;
83 static int hf_mac_lte_ulsch_lcid = -1;
84 static int hf_mac_lte_sch_extended = -1;
85 static int hf_mac_lte_sch_format = -1;
86 static int hf_mac_lte_sch_length = -1;
88 static int hf_mac_lte_sch_header_only = -1;
91 static int hf_mac_lte_sch_sdu = -1;
92 static int hf_mac_lte_bch_pdu = -1;
93 static int hf_mac_lte_pch_pdu = -1;
94 static int hf_mac_lte_predefined_pdu = -1;
95 static int hf_mac_lte_raw_pdu = -1;
96 static int hf_mac_lte_padding_data = -1;
97 static int hf_mac_lte_padding_length = -1;
101 static int hf_mac_lte_rar = -1;
102 static int hf_mac_lte_rar_headers = -1;
103 static int hf_mac_lte_rar_header = -1;
104 static int hf_mac_lte_rar_extension = -1;
105 static int hf_mac_lte_rar_t = -1;
106 static int hf_mac_lte_rar_bi = -1;
107 static int hf_mac_lte_rar_rapid = -1;
108 static int hf_mac_lte_rar_reserved = -1;
109 static int hf_mac_lte_rar_body = -1;
110 static int hf_mac_lte_rar_reserved2 = -1;
111 static int hf_mac_lte_rar_ta = -1;
112 static int hf_mac_lte_rar_ul_grant = -1;
113 static int hf_mac_lte_rar_ul_grant_hopping = -1;
114 static int hf_mac_lte_rar_ul_grant_fsrba = -1;
115 static int hf_mac_lte_rar_ul_grant_tmcs = -1;
116 static int hf_mac_lte_rar_ul_grant_tcsp = -1;
117 static int hf_mac_lte_rar_ul_grant_ul_delay = -1;
118 static int hf_mac_lte_rar_ul_grant_cqi_request = -1;
119 static int hf_mac_lte_rar_temporary_crnti = -1;
121 /* Common channel control values */
122 static int hf_mac_lte_control_bsr = -1;
123 static int hf_mac_lte_control_bsr_lcg_id = -1;
124 static int hf_mac_lte_control_short_bsr_buffer_size = -1;
125 static int hf_mac_lte_control_long_bsr_buffer_size_0 = -1;
126 static int hf_mac_lte_control_long_bsr_buffer_size_1 = -1;
127 static int hf_mac_lte_control_long_bsr_buffer_size_2 = -1;
128 static int hf_mac_lte_control_long_bsr_buffer_size_3 = -1;
129 static int hf_mac_lte_control_crnti = -1;
130 static int hf_mac_lte_control_timing_advance = -1;
131 static int hf_mac_lte_control_timing_advance_reserved = -1;
132 static int hf_mac_lte_control_ue_contention_resolution = -1;
133 static int hf_mac_lte_control_ue_contention_resolution_identity = -1;
134 static int hf_mac_lte_control_ue_contention_resolution_msg3 = -1;
135 static int hf_mac_lte_control_ue_contention_resolution_msg3_matched = -1;
136 static int hf_mac_lte_control_power_headroom = -1;
137 static int hf_mac_lte_control_power_headroom_reserved = -1;
138 static int hf_mac_lte_control_power_headroom_level = -1;
139 static int hf_mac_lte_control_padding = -1;
141 static int hf_mac_lte_suspected_dl_harq_resend = -1;
142 static int hf_mac_lte_suspected_dl_harq_resend_original_frame = -1;
144 static int hf_mac_lte_ul_harq_resend_original_frame = -1;
148 static int ett_mac_lte = -1;
149 static int ett_mac_lte_context = -1;
150 static int ett_mac_lte_ulsch_header = -1;
151 static int ett_mac_lte_dlsch_header = -1;
152 static int ett_mac_lte_sch_subheader = -1;
153 static int ett_mac_lte_rar_headers = -1;
154 static int ett_mac_lte_rar_header = -1;
155 static int ett_mac_lte_rar_body = -1;
156 static int ett_mac_lte_rar_ul_grant = -1;
157 static int ett_mac_lte_bsr = -1;
158 static int ett_mac_lte_bch = -1;
159 static int ett_mac_lte_pch = -1;
160 static int ett_mac_lte_contention_resolution = -1;
161 static int ett_mac_lte_power_headroom = -1;
165 /* Constants and value strings */
167 static const value_string radio_type_vals[] =
175 static const value_string direction_vals[] =
177 { DIRECTION_UPLINK, "Uplink"},
178 { DIRECTION_DOWNLINK, "Downlink"},
183 static const value_string rnti_type_vals[] =
185 { NO_RNTI, "NO-RNTI"},
187 { RA_RNTI, "RA-RNTI"},
189 { SI_RNTI, "SI-RNTI"},
190 { SPS_RNTI, "SPS-RNTI"},
194 static const value_string bch_transport_channel_vals[] =
196 { SI_RNTI, "DL-SCH"},
201 static const value_string crc_status_vals[] =
203 { 0, "CRC Status Failed"},
204 { 1, "CRC Status OK"},
210 #define UE_CONTENTION_RESOLUTION_IDENTITY_LCID 0x1c
211 #define TIMING_ADVANCE_LCID 0x1d
212 #define DRX_COMMAND_LCID 0x1e
213 #define PADDING_LCID 0x1f
215 static const value_string dlsch_lcid_vals[] =
228 { UE_CONTENTION_RESOLUTION_IDENTITY_LCID, "UE Contention Resolution Identity"},
229 { TIMING_ADVANCE_LCID , "Timing Advance"},
230 { DRX_COMMAND_LCID , "DRX Command"},
231 { PADDING_LCID , "Padding" },
235 #define POWER_HEADROOM_REPORT_LCID 0x1a
236 #define CRNTI_LCID 0x1b
237 #define TRUNCATED_BSR_LCID 0x1c
238 #define SHORT_BSR_LCID 0x1d
239 #define LONG_BSR_LCID 0x1e
241 static const value_string ulsch_lcid_vals[] =
254 { POWER_HEADROOM_REPORT_LCID, "Power Headroom Report"},
255 { CRNTI_LCID, "C-RNTI"},
256 { TRUNCATED_BSR_LCID, "Truncated BSR"},
257 { SHORT_BSR_LCID, "Short BSR"},
258 { LONG_BSR_LCID, "Long BSR"},
259 { PADDING_LCID, "Padding" },
264 static const value_string format_vals[] =
266 { 0, "Data length is < 128 bytes"},
267 { 1, "Data length is >= 128 bytes"},
272 static const value_string rar_type_vals[] =
274 { 0, "Backoff Indicator present"},
275 { 1, "RAPID present"},
280 static const value_string rar_bi_vals[] =
299 static const value_string buffer_size_vals[] =
302 { 1, "0 < BS <= 10"},
303 { 2, "10 < BS <= 12"},
304 { 3, "12 < BS <= 14"},
305 { 4, "14 < BS <= 17"},
306 { 5, "17 < BS <= 19"},
307 { 6, "19 < BS <= 22"},
308 { 7, "22 < BS <= 26"},
309 { 8, "26 < BS <= 31"},
310 { 9, "31 < BS <= 36"},
311 { 10, "36 < BS <= 42"},
312 { 11, "42 < BS <= 49"},
313 { 12, "49 < BS <= 57"},
314 { 13, "47 < BS <= 67"},
315 { 14, "67 < BS <= 78"},
316 { 15, "78 < BS <= 91"},
317 { 16, "91 < BS <= 107"},
318 { 17, "107 < BS <= 125"},
319 { 18, "125 < BS <= 146"},
320 { 19, "146 < BS <= 171"},
321 { 20, "171 < BS <= 200"},
322 { 21, "200 < BS <= 234"},
323 { 22, "234 < BS <= 274"},
324 { 23, "274 < BS <= 321"},
325 { 24, "321 < BS <= 376"},
326 { 25, "376 < BS <= 440"},
327 { 26, "440 < BS <= 515"},
328 { 27, "515 < BS <= 603"},
329 { 28, "603 < BS <= 706"},
330 { 29, "706 < BS <= 826"},
331 { 30, "826 < BS <= 967"},
332 { 31, "967 < BS <= 1132"},
333 { 32, "1132 < BS <= 1326"},
334 { 33, "1326 < BS <= 1552"},
335 { 34, "1552 < BS <= 1817"},
336 { 35, "1817 < BS <= 2127"},
337 { 36, "2127 < BS <= 2490"},
338 { 37, "2490 < BS <= 2915"},
339 { 38, "2915 < BS <= 3413"},
340 { 39, "3413 < BS <= 3995"},
341 { 40, "3995 < BS <= 4677"},
342 { 41, "4677 < BS <= 5476"},
343 { 42, "5476 < BS <= 6411"},
344 { 43, "6411 < BS <= 7505"},
345 { 44, "7505 < BS <= 8787"},
346 { 45, "8787 < BS <= 10276"},
347 { 46, "10287 < BS <= 12043"},
348 { 47, "12043 < BS <= 14099"},
349 { 48, "14099 < BS <= 16507"},
350 { 49, "16507 < BS <= 19325"},
351 { 50, "19325 < BS <= 22624"},
352 { 51, "22624 < BS <= 26487"},
353 { 52, "26487 < BS <= 31009"},
354 { 53, "31009 < BS <= 36304"},
355 { 54, "36304 < BS <= 42502"},
356 { 55, "42502 < BS <= 49759"},
357 { 56, "49759 < BS <= 58255"},
358 { 57, "58255 < BS <= 68201"},
359 { 58, "68201 < BS <= 79846"},
360 { 59, "79846 < BS <= 93479"},
361 { 60, "93479 < BS <= 109439"},
362 { 61, "109439 < BS <= 128125"},
363 { 62, "128125 < BS <= 150000"},
364 { 63, "BS > 150000"},
368 static const value_string header_only_vals[] =
370 { 0, "MAC PDU Headers and body present"},
371 { 1, "MAC PDU Headers only"},
375 static const value_string predefined_frame_vals[] =
377 { 0, "Real MAC PDU present - will dissect"},
378 { 1, "Predefined frame present - will not dissect"},
383 /* If this PDU has been NACK'd (by HARQ) more than a certain number of times,
384 we trigger an expert warning. */
385 static gint global_mac_lte_retx_counter_trigger = 3;
387 /* By default try to decode transparent data (BCH, PCH and CCCH) data using LTE RRC dissector */
388 static gboolean global_mac_lte_attempt_rrc_decode = TRUE;
390 /* Whether should attempt to dissect frames failing CRC check */
391 static gboolean global_mac_lte_dissect_crc_failures = FALSE;
393 /* Whether should attempt to decode lcid 1&2 SDUs as srb1/2 (i.e. AM RLC) */
394 static gboolean global_mac_lte_attempt_srb_decode = FALSE;
396 /* Whether should attempt to detect and flag DL HARQ resends */
397 static gboolean global_mac_lte_attempt_dl_harq_resend_detect = TRUE;
399 /* Whether should attempt to track UL HARQ resends */
400 static gboolean global_mac_lte_attempt_ul_harq_resend_track = TRUE;
402 /* Threshold for warning in expert info about high BSR values */
403 static gint global_mac_lte_bsr_warn_threshold = 50; /* default is 19325 -> 22624 */
406 /***********************************************************************/
407 /* How to dissect lcid 3-10 (presume drb logical channels) */
409 static const value_string drb_lcid_vals[] = {
421 typedef enum rlc_channel_type_t {
427 } rlc_channel_type_t;
429 static const value_string rlc_channel_type_vals[] = {
431 { rlcUM5 , "UM, SN Len=5"},
432 { rlcUM10, "UM, SN Len=10"},
439 typedef struct drb_mapping_t {
442 rlc_channel_type_t channel_type;
443 } lcid_drb_mapping_t;
446 static lcid_drb_mapping_t *lcid_drb_mappings = NULL;
447 static guint num_lcid_drb_mappings = 0;
449 UAT_VS_DEF(lcid_drb_mappings, lcid, lcid_drb_mapping_t, 3, "LCID 3")
450 UAT_DEC_CB_DEF(lcid_drb_mappings, drbid, lcid_drb_mapping_t)
451 UAT_VS_DEF(lcid_drb_mappings, channel_type, lcid_drb_mapping_t, 2, "AM")
454 static uat_t* lcid_drb_mappings_uat;
456 extern int proto_rlc_lte;
458 /***************************************************************/
462 /***************************************************************/
463 /* Keeping track of Msg3 bodies so they can be compared with */
464 /* Contention Resolution bodies. */
466 typedef struct Msg3Data {
472 /* This table stores (RNTI -> Msg3Data*). Will be populated when
473 Msg3 frames are first read. */
474 static GHashTable *mac_lte_msg3_hash = NULL;
476 /* Hash table functions for mac_lte_msg3_hash. Hash is just the (RNTI) key */
477 static gint mac_lte_rnti_hash_equal(gconstpointer v, gconstpointer v2)
482 static guint mac_lte_rnti_hash_func(gconstpointer v)
484 return GPOINTER_TO_UINT(v);
489 typedef enum ContentionResolutionStatus {
493 } ContentionResolutionStatus;
495 typedef struct ContentionResolutionResult {
496 ContentionResolutionStatus status;
498 } ContentionResolutionResult;
501 /* This table stores (CRFrameNum -> CRResult). It is assigned during the first
502 pass and used thereafter */
503 static GHashTable *mac_lte_cr_result_hash = NULL;
505 /* Hash table functions for mac_lte_cr_result_hash. Hash is just the (framenum) key */
506 static gint mac_lte_framenum_hash_equal(gconstpointer v, gconstpointer v2)
511 static guint mac_lte_framenum_hash_func(gconstpointer v)
513 return GPOINTER_TO_UINT(v);
516 /**************************************************************************/
520 /****************************************************************/
521 /* Keeping track of last DL frames per C-RNTI so can guess when */
522 /* there has been a HARQ retransmission */
524 /* Could be bigger, but more than enough to flag suspected resends */
525 #define MAX_EXPECTED_PDU_LENGTH 2048
527 typedef struct LastFrameData {
530 guint subframeNumber;
531 nstime_t received_time;
533 guint8 data[MAX_EXPECTED_PDU_LENGTH];
536 typedef struct LastFrameDataAllSubframes {
537 LastFrameData subframe[10];
538 } LastFrameDataAllSubframes;
541 /* This table stores (RNTI -> LastFrameDataAllSubframes*). Will be populated when
542 DL frames are first read. */
543 static GHashTable *mac_lte_dl_harq_hash = NULL;
545 typedef struct DLHARQResult {
547 guint previousFrameNum;
551 /* This table stores (CRFrameNum -> DLHARQResult). It is assigned during the first
552 pass and used thereafter */
553 static GHashTable *mac_lte_dl_harq_result_hash = NULL;
555 /**************************************************************************/
558 /*****************************************************************/
559 /* Keeping track of last UL frames per C-RNTI so can verify when */
560 /* told that a frame is a retx */
562 /* This table stores (RNTI -> LastFrameDataAllSubframes*). Will be populated when
563 UL frames are first read. */
564 static GHashTable *mac_lte_ul_harq_hash = NULL;
566 typedef struct ULHARQResult {
567 guint previousFrameNum;
571 /* This table stores (CRFrameNum -> ULHARQResult). It is assigned during the first
572 pass and used thereafter */
573 static GHashTable *mac_lte_ul_harq_result_hash = NULL;
575 /**************************************************************************/
582 /* Forward declarations */
583 void proto_reg_handoff_mac_lte(void);
584 void dissect_mac_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
587 /* Heuristic dissection */
588 static gboolean global_mac_lte_heur = FALSE;
590 /* Heuristic dissector looks for supported framing protocol (see wiki page) */
591 static gboolean dissect_mac_lte_heur(tvbuff_t *tvb, packet_info *pinfo,
595 struct mac_lte_info *p_mac_lte_info;
598 gboolean infoAlreadySet = FALSE;
600 /* This is a heuristic dissector, which means we get all the UDP
601 * traffic not sent to a known dissector and not claimed by
602 * a heuristic dissector called before us!
605 if (!global_mac_lte_heur) {
609 /* If redissecting, use previous info struct (if available) */
610 p_mac_lte_info = p_get_proto_data(pinfo->fd, proto_mac_lte);
611 if (p_mac_lte_info == NULL) {
612 /* Allocate new info struct for this frame */
613 p_mac_lte_info = se_alloc0(sizeof(struct mac_lte_info));
614 if (p_mac_lte_info == NULL) {
617 infoAlreadySet = FALSE;
620 infoAlreadySet = TRUE;
623 /* Do this again on re-dissection to re-discover offset of actual PDU */
625 /* Needs to be at least as long as:
626 - the signature string
629 - at least one byte of MAC PDU payload */
630 if ((size_t)tvb_length_remaining(tvb, offset) < (strlen(MAC_LTE_START_STRING)+3+2)) {
634 /* OK, compare with signature string */
635 if (tvb_strneql(tvb, offset, MAC_LTE_START_STRING, (gint)strlen(MAC_LTE_START_STRING)) != 0) {
638 offset += (gint)strlen(MAC_LTE_START_STRING);
640 /* Read fixed fields */
641 p_mac_lte_info->radioType = tvb_get_guint8(tvb, offset++);
642 p_mac_lte_info->direction = tvb_get_guint8(tvb, offset++);
643 p_mac_lte_info->rntiType = tvb_get_guint8(tvb, offset++);
645 /* Read optional fields */
646 while (tag != MAC_LTE_PAYLOAD_TAG) {
647 /* Process next tag */
648 tag = tvb_get_guint8(tvb, offset++);
650 case MAC_LTE_RNTI_TAG:
651 p_mac_lte_info->rnti = tvb_get_ntohs(tvb, offset);
654 case MAC_LTE_UEID_TAG:
655 p_mac_lte_info->ueid = tvb_get_ntohs(tvb, offset);
658 case MAC_LTE_SUBFRAME_TAG:
659 p_mac_lte_info->subframeNumber = tvb_get_ntohs(tvb, offset);
662 case MAC_LTE_PREDFINED_DATA_TAG:
663 p_mac_lte_info->isPredefinedData = tvb_get_guint8(tvb, offset);
666 case MAC_LTE_RETX_TAG:
667 p_mac_lte_info->reTxCount = tvb_get_guint8(tvb, offset);
670 case MAC_LTE_CRC_STATUS_TAG:
671 p_mac_lte_info->crcStatusValid = TRUE;
672 p_mac_lte_info->crcStatus = tvb_get_guint8(tvb, offset);
676 case MAC_LTE_PAYLOAD_TAG:
677 /* Have reached data, so set payload length and get out of loop */
678 p_mac_lte_info->length= tvb_length_remaining(tvb, offset);
682 /* It must be a recognised tag */
686 if (!infoAlreadySet) {
687 /* Store info in packet */
688 p_add_proto_data(pinfo->fd, proto_mac_lte, p_mac_lte_info);
693 /**************************************/
694 /* OK, now dissect as MAC LTE */
696 /* Create tvb that starts at actual MAC PDU */
697 mac_tvb = tvb_new_subset(tvb, offset, -1, tvb_reported_length(tvb)-offset);
698 dissect_mac_lte(mac_tvb, pinfo, tree);
702 /* Dissect a single Random Access Reponse body */
703 static gint dissect_rar_entry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
704 gint offset, guint8 rapid)
707 guint start_body_offset = offset;
709 proto_item *rar_body_ti;
710 proto_tree *rar_body_tree;
711 proto_tree *ul_grant_tree;
712 proto_item *ul_grant_ti;
713 guint16 timing_advance;
717 /* Create tree for this Body */
718 rar_body_ti = proto_tree_add_item(tree,
720 tvb, offset, 0, FALSE);
721 rar_body_tree = proto_item_add_subtree(rar_body_ti, ett_mac_lte_rar_body);
723 /* Dissect an RAR entry */
725 /* Check reserved bit */
726 reserved = (tvb_get_guint8(tvb, offset) & 0x80) >> 7;
727 ti = proto_tree_add_item(rar_body_tree, hf_mac_lte_rar_reserved2, tvb, offset, 1, FALSE);
729 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
730 "RAR body Reserved bit not zero (found 0x%x)", reserved);
734 timing_advance = (tvb_get_ntohs(tvb, offset) & 0x7ff0) >> 4;
735 ti = proto_tree_add_item(rar_body_tree, hf_mac_lte_rar_ta, tvb, offset, 2, FALSE);
736 if (timing_advance != 0) {
737 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
738 "RAR Timing advance not zero (%u)", timing_advance);
743 ul_grant = (tvb_get_ntohl(tvb, offset) & 0x0fffff00) >> 8;
744 ul_grant_ti = proto_tree_add_item(rar_body_tree, hf_mac_lte_rar_ul_grant, tvb, offset, 3, FALSE);
746 /* Break these 20 bits down as described in 36.213, section 6.2 */
747 /* Create subtree for UL grant break-down */
748 ul_grant_tree = proto_item_add_subtree(ul_grant_ti, ett_mac_lte_rar_ul_grant);
750 /* Hopping flag (1 bit) */
751 proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_hopping,
752 tvb, offset, 1, FALSE);
754 /* Fixed sized resource block assignment (10 bits) */
755 proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_fsrba,
756 tvb, offset, 2, FALSE);
758 /* Truncated Modulation and coding scheme (4 bits) */
759 proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_tmcs,
760 tvb, offset+1, 2, FALSE);
762 /* TPC command for scheduled PUSCH (3 bits) */
763 proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_tcsp,
764 tvb, offset+2, 1, FALSE);
766 /* UL delay (1 bit) */
767 proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_ul_delay,
768 tvb, offset+2, 1, FALSE);
770 /* CQI request (1 bit) */
771 proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_cqi_request,
772 tvb, offset+2, 1, FALSE);
776 /* Temporary C-RNTI */
777 temp_crnti = tvb_get_ntohs(tvb, offset);
778 proto_tree_add_item(rar_body_tree, hf_mac_lte_rar_temporary_crnti, tvb, offset, 2, FALSE);
781 proto_item_append_text(rar_body_ti, " RAPID=%u (TA=%u, UL-Grant=%u, Temp C-RNTI=%u)",
782 rapid, timing_advance, ul_grant, temp_crnti);
784 col_append_fstr(pinfo->cinfo, COL_INFO, "(RAPID=%u: TA=%u, UL-Grant=%u, Temp C-RNTI=%u) ",
785 rapid, timing_advance, ul_grant, temp_crnti);
787 proto_item_set_len(rar_body_ti, offset-start_body_offset);
793 /* Dissect Random Access Reponse (RAR) PDU */
794 static void dissect_rar(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *pdu_ti,
795 gint offset, mac_lte_info *p_mac_lte_info, mac_lte_tap_info *tap_info)
797 gint number_of_rars = 0; /* No of RAR bodies expected following headers */
799 gboolean backoff_indicator_seen = FALSE;
800 guint8 backoff_indicator = 0;
803 proto_tree *rar_headers_tree;
805 proto_item *rar_headers_ti;
806 int start_headers_offset = offset;
808 col_append_fstr(pinfo->cinfo, COL_INFO, "RAR (RA-RNTI=%u, SF=%u) ",
809 p_mac_lte_info->rnti, p_mac_lte_info->subframeNumber);
811 /* Create hidden 'virtual root' so can filter on mac-lte.rar */
812 ti = proto_tree_add_item(tree, hf_mac_lte_rar, tvb, offset, -1, FALSE);
813 PROTO_ITEM_SET_HIDDEN(ti);
815 /* Create headers tree */
816 rar_headers_ti = proto_tree_add_item(tree,
817 hf_mac_lte_rar_headers,
818 tvb, offset, 0, FALSE);
819 rar_headers_tree = proto_item_add_subtree(rar_headers_ti, ett_mac_lte_rar_headers);
822 /***************************/
823 /* Read the header entries */
825 int start_header_offset = offset;
826 proto_tree *rar_header_tree;
827 proto_item *rar_header_ti;
829 guint8 first_byte = tvb_get_guint8(tvb, offset);
831 /* Create tree for this header */
832 rar_header_ti = proto_tree_add_item(rar_headers_tree,
833 hf_mac_lte_rar_header,
834 tvb, offset, 0, FALSE);
835 rar_header_tree = proto_item_add_subtree(rar_header_ti, ett_mac_lte_rar_header);
838 extension = (first_byte & 0x80) >> 7;
839 proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_extension, tvb, offset, 1, FALSE);
842 type_value = (first_byte & 0x40) >> 6;
843 proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_t, tvb, offset, 1, FALSE);
845 if (type_value == 0) {
846 /* Backoff Indicator (BI) case */
852 /* 2 Reserved bits */
853 reserved = (tvb_get_guint8(tvb, offset) & 0x30) >> 4;
854 ti = proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_reserved, tvb, offset, 1, FALSE);
856 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
857 "RAR header Reserved bits not zero (found 0x%x)", reserved);
860 /* Backoff Indicator */
861 backoff_indicator = tvb_get_guint8(tvb, offset) & 0x0f;
862 bi_ti = proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_bi, tvb, offset, 1, FALSE);
864 /* As of March 2009 spec, it must be first, and may only appear once */
865 if (backoff_indicator_seen) {
866 expert_add_info_format(pinfo, bi_ti, PI_MALFORMED, PI_ERROR,
867 "MAC RAR PDU has > 1 Backoff Indicator subheader present");
869 backoff_indicator_seen = TRUE;
871 proto_item_append_text(rar_header_ti, "(Backoff Indicator=%sms)",
872 val_to_str(backoff_indicator, rar_bi_vals, "Illegal-value "));
874 col_append_fstr(pinfo->cinfo, COL_INFO, "(Backoff Indicator=%s ms) ",
875 val_to_str(backoff_indicator, rar_bi_vals, "Illegal-value"));
877 /* If present, it must be the first subheader */
878 if (number_of_rars > 0) {
879 expert_add_info_format(pinfo, bi_ti, PI_MALFORMED, PI_WARN,
880 "Backoff Indicator must appear as first subheader");
886 /* TODO: complain if the same RAPID appears twice in same frame? */
887 rapids[number_of_rars] = tvb_get_guint8(tvb, offset) & 0x3f;
888 proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_rapid, tvb, offset, 1, FALSE);
890 proto_item_append_text(rar_header_ti, "(RAPID=%u)", rapids[number_of_rars]);
897 /* Finalise length of header tree selection */
898 proto_item_set_len(rar_header_ti, offset - start_header_offset);
902 /* Append summary to headers root */
903 proto_item_append_text(rar_headers_ti, " (%u RARs", number_of_rars);
904 if (backoff_indicator_seen) {
905 proto_item_append_text(rar_headers_ti, ", BI=%sms)",
906 val_to_str(backoff_indicator, rar_bi_vals, "Illegal-value "));
909 proto_item_append_text(rar_headers_ti, ")");
912 /* Set length for headers root */
913 proto_item_set_len(rar_headers_ti, offset-start_headers_offset);
916 /***************************/
917 /* Read any indicated RARs */
918 for (n=0; n < number_of_rars; n++) {
919 offset = dissect_rar_entry(tvb, pinfo, tree, offset, rapids[n]);
922 /* Update TAP info */
923 tap_info->number_of_rars += number_of_rars;
925 /* Warn if we don't seem to have reached the end of the frame yet */
926 if (tvb_length_remaining(tvb, offset) != 0) {
927 expert_add_info_format(pinfo, pdu_ti, PI_MALFORMED, PI_ERROR,
928 "%u bytes remaining after RAR PDU dissected",
929 tvb_length_remaining(tvb, offset));
934 /* Dissect BCH PDU */
935 static void dissect_bch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
936 int offset, mac_lte_info *p_mac_lte_info)
940 col_append_fstr(pinfo->cinfo, COL_INFO, "BCH PDU (%u bytes, on %s transport) ",
941 tvb_length_remaining(tvb, offset),
942 val_to_str(p_mac_lte_info->rntiType,
943 bch_transport_channel_vals,
946 /* Show which transport layer it came in on (inferred from RNTI type) */
947 ti = proto_tree_add_uint(tree, hf_mac_lte_context_bch_transport_channel,
948 tvb, offset, 0, p_mac_lte_info->rntiType);
949 PROTO_ITEM_SET_GENERATED(ti);
951 /****************************************/
952 /* Whole frame is BCH data */
955 ti = proto_tree_add_item(tree, hf_mac_lte_bch_pdu,
956 tvb, offset, -1, FALSE);
958 if (global_mac_lte_attempt_rrc_decode) {
959 /* Attempt to decode payload using LTE RRC dissector */
960 tvbuff_t *rrc_tvb = tvb_new_subset(tvb, offset, -1, tvb_length_remaining(tvb, offset));
962 /* Get appropriate dissector handle */
963 dissector_handle_t protocol_handle = 0;
964 if (p_mac_lte_info->rntiType == SI_RNTI) {
965 protocol_handle = find_dissector("lte-rrc.bcch.dl.sch");
968 protocol_handle = find_dissector("lte-rrc.bcch.bch");
971 /* Hide raw view of bytes */
972 PROTO_ITEM_SET_HIDDEN(ti);
974 /* Call it (catch exceptions so that stats will be updated) */
975 /* TODO: couldn't avoid warnings for 'ti' by using volatile
978 call_dissector_only(protocol_handle, rrc_tvb, pinfo, tree);
985 /* Check that this *is* downlink! */
986 if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
987 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
988 "BCH data should not be received in Uplink!");
993 /* Dissect PCH PDU */
994 static void dissect_pch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
995 int offset, guint8 direction)
999 col_append_fstr(pinfo->cinfo, COL_INFO, "PCH PDU (%u bytes) ",
1000 tvb_length_remaining(tvb, offset));
1002 /****************************************/
1003 /* Whole frame is PCH data */
1005 /* Always show as raw data */
1006 ti = proto_tree_add_item(tree, hf_mac_lte_pch_pdu,
1007 tvb, offset, -1, FALSE);
1009 if (global_mac_lte_attempt_rrc_decode) {
1011 /* Attempt to decode payload using LTE RRC dissector */
1012 tvbuff_t *rrc_tvb = tvb_new_subset(tvb, offset, -1, tvb_length_remaining(tvb, offset));
1014 /* Get appropriate dissector handle */
1015 dissector_handle_t protocol_handle = find_dissector("lte-rrc.pcch");
1017 /* Hide raw view of bytes */
1018 PROTO_ITEM_SET_HIDDEN(ti);
1020 /* Call it (catch exceptions so that stats will be updated) */
1022 call_dissector_only(protocol_handle, rrc_tvb, pinfo, tree);
1029 /* Check that this *is* downlink! */
1030 if (direction == DIRECTION_UPLINK) {
1031 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
1032 "PCH data should not be received in Uplink!");
1037 /* Does this header entry correspond to a fixed-sized control element? */
1038 static int is_fixed_sized_control_element(guint8 lcid, guint8 direction)
1040 if (direction == DIRECTION_UPLINK) {
1043 case POWER_HEADROOM_REPORT_LCID:
1045 case TRUNCATED_BSR_LCID:
1046 case SHORT_BSR_LCID:
1055 /* Assume Downlink */
1057 case UE_CONTENTION_RESOLUTION_IDENTITY_LCID:
1058 case TIMING_ADVANCE_LCID:
1059 case DRX_COMMAND_LCID:
1069 /* Is this a BSR report header? */
1070 static int is_bsr_lcid(guint8 lcid)
1072 return ((lcid == TRUNCATED_BSR_LCID) ||
1073 (lcid == SHORT_BSR_LCID) ||
1074 (lcid == LONG_BSR_LCID));
1078 /* Helper function to call RLC dissector for SDUs (where channel params are known) */
1079 static void call_rlc_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1080 int offset, guint16 data_length,
1081 guint8 mode, guint8 direction, guint16 ueid,
1082 guint16 channelType, guint16 channelId,
1083 guint8 UMSequenceNumberLength)
1085 tvbuff_t *srb_tvb = tvb_new_subset(tvb, offset, data_length, data_length);
1086 struct rlc_lte_info *p_rlc_lte_info;
1088 /* Get RLC dissector handle */
1089 volatile dissector_handle_t protocol_handle = find_dissector("rlc-lte");
1091 /* Resuse or create RLC info */
1092 p_rlc_lte_info = p_get_proto_data(pinfo->fd, proto_rlc_lte);
1093 if (p_rlc_lte_info == NULL) {
1094 p_rlc_lte_info = se_alloc0(sizeof(struct rlc_lte_info));
1097 /* Fill in struct details for srb channels */
1098 p_rlc_lte_info->rlcMode = mode;
1099 p_rlc_lte_info->direction = direction;
1100 p_rlc_lte_info->priority = 0; /* ?? */
1101 p_rlc_lte_info->ueid = ueid;
1102 p_rlc_lte_info->channelType = channelType;
1103 p_rlc_lte_info->channelId = channelId;
1104 p_rlc_lte_info->pduLength = data_length;
1105 p_rlc_lte_info->UMSequenceNumberLength = UMSequenceNumberLength;
1107 /* Store info in packet */
1108 p_add_proto_data(pinfo->fd, proto_rlc_lte, p_rlc_lte_info);
1110 /* Don't want these columns replaced */
1111 col_set_writable(pinfo->cinfo, FALSE);
1113 /* Call it (catch exceptions so that stats will be updated) */
1115 call_dissector_only(protocol_handle, srb_tvb, pinfo, tree);
1121 col_set_writable(pinfo->cinfo, TRUE);
1125 /* Track DL frames, and look for likely cases of likely HARQ retx */
1126 static void DetectIfDLHARQResend(packet_info *pinfo, tvbuff_t *tvb, volatile int offset,
1127 proto_tree *tree, mac_lte_info *p_mac_lte_info)
1129 DLHARQResult *result = NULL;
1130 proto_item *result_ti;
1132 if (!pinfo->fd->flags.visited) {
1133 /* First time, so set result and update DL harq table */
1134 LastFrameData *lastData = NULL;
1135 LastFrameData *thisData = NULL;
1137 /* Look up entry for this UE/RNTI */
1138 LastFrameDataAllSubframes *ueData =
1139 g_hash_table_lookup(mac_lte_dl_harq_hash, GUINT_TO_POINTER((guint)p_mac_lte_info->rnti));
1140 if (ueData != NULL) {
1141 /* Looking for a frame sent 8 subframes previously */
1142 lastData = &(ueData->subframe[(p_mac_lte_info->subframeNumber+2) % 10]);
1143 if (lastData->inUse) {
1144 /* Compare time, sf, data to see if this looks like a retx */
1145 if ((tvb_length_remaining(tvb, offset) == lastData->length) &&
1146 (memcmp(lastData->data,
1147 tvb_get_ptr(tvb, offset, lastData->length),
1148 MIN(lastData->length, MAX_EXPECTED_PDU_LENGTH)) == 0)) {
1150 /* Work out gap between frames */
1151 gint seconds_between_packets = (gint)
1152 (pinfo->fd->abs_ts.secs - lastData->received_time.secs);
1153 gint nseconds_between_packets =
1154 pinfo->fd->abs_ts.nsecs - lastData->received_time.nsecs;
1156 gint total_gap = (seconds_between_packets*1000) +
1157 (nseconds_between_packets / 1000000);
1159 /* Should be 8 ms apart, but allow some leeway */
1160 if ((total_gap >= 7) && (total_gap <= 9)) {
1161 /* Resend detected!!! Store result */
1162 result = se_alloc(sizeof(DLHARQResult));
1163 result->previousFrameNum = lastData->framenum;
1164 g_hash_table_insert(mac_lte_dl_harq_result_hash, GUINT_TO_POINTER(pinfo->fd->num), result);
1171 /* Allocate entry in table for this UE/RNTI */
1172 ueData = se_alloc0(sizeof(LastFrameDataAllSubframes));
1173 g_hash_table_insert(mac_lte_dl_harq_hash, GUINT_TO_POINTER((guint)p_mac_lte_info->rnti), ueData);
1176 /* Store this frame's details in table */
1177 thisData = &(ueData->subframe[p_mac_lte_info->subframeNumber]);
1178 thisData->inUse = TRUE;
1179 thisData->length = tvb_length_remaining(tvb, offset);
1180 memcpy(thisData->data, tvb_get_ptr(tvb, offset, MIN(thisData->length, MAX_EXPECTED_PDU_LENGTH)), thisData->length);
1181 thisData->subframeNumber = p_mac_lte_info->subframeNumber;
1182 thisData->framenum = pinfo->fd->num;
1183 thisData->received_time = pinfo->fd->abs_ts;
1186 /* Not first time, so just set whats already stored in result */
1187 result = g_hash_table_lookup(mac_lte_dl_harq_result_hash, GUINT_TO_POINTER(pinfo->fd->num));
1190 /* Show result, with link back to original frame */
1191 result_ti = proto_tree_add_boolean(tree, hf_mac_lte_suspected_dl_harq_resend,
1192 tvb, 0, 0, (result != NULL));
1193 if (result != NULL) {
1194 proto_item *original_ti;
1195 expert_add_info_format(pinfo, result_ti, PI_SEQUENCE, PI_WARN,
1196 "Suspected DL HARQ resend (UE=%u)", p_mac_lte_info->ueid);
1197 original_ti = proto_tree_add_uint(tree, hf_mac_lte_suspected_dl_harq_resend_original_frame,
1198 tvb, 0, 0, result->previousFrameNum);
1199 PROTO_ITEM_SET_GENERATED(original_ti);
1202 /* Don't show negatives */
1203 PROTO_ITEM_SET_HIDDEN(result_ti);
1205 PROTO_ITEM_SET_GENERATED(result_ti);
1208 /* Track UL frames, so that when a retx is indicated, we can search for
1209 the original tx. We will either find it, and provide a link back to it,
1210 or flag that we couldn't find as an expert error */
1211 static void TrackReportedULHARQResend(packet_info *pinfo, tvbuff_t *tvb, volatile int offset,
1212 proto_tree *tree, mac_lte_info *p_mac_lte_info,
1213 proto_item *retx_ti)
1215 ULHARQResult *result = NULL;
1217 if (!pinfo->fd->flags.visited) {
1218 /* First time, so set result and update UL harq table */
1219 LastFrameData *lastData = NULL;
1220 LastFrameData *thisData = NULL;
1222 /* Look up entry for this UE/RNTI */
1223 LastFrameDataAllSubframes *ueData =
1224 g_hash_table_lookup(mac_lte_ul_harq_hash, GUINT_TO_POINTER((guint)p_mac_lte_info->rnti));
1225 if (ueData != NULL) {
1227 if (p_mac_lte_info->reTxCount >= 1) {
1228 /* Looking for a frame sent 8 subframes previously */
1229 lastData = &(ueData->subframe[(p_mac_lte_info->subframeNumber+2) % 10]);
1230 if (lastData->inUse) {
1231 /* Compare time, sf, data to see if this looks like a retx */
1232 if ((tvb_length_remaining(tvb, offset) == lastData->length) &&
1233 (memcmp(lastData->data,
1234 tvb_get_ptr(tvb, offset, lastData->length),
1235 MIN(lastData->length, MAX_EXPECTED_PDU_LENGTH)) == 0)) {
1237 /* Work out gap between frames */
1238 gint seconds_between_packets = (gint)
1239 (pinfo->fd->abs_ts.secs - lastData->received_time.secs);
1240 gint nseconds_between_packets =
1241 pinfo->fd->abs_ts.nsecs - lastData->received_time.nsecs;
1243 gint total_gap = (seconds_between_packets*1000) +
1244 (nseconds_between_packets / 1000000);
1246 /* Should be 8 ms apart, but allow some leeway */
1247 if ((total_gap >= 7) && (total_gap <= 9)) {
1248 /* Original detected!!! Store result */
1249 result = se_alloc(sizeof(ULHARQResult));
1250 result->previousFrameNum = lastData->framenum;
1251 g_hash_table_insert(mac_lte_ul_harq_result_hash, GUINT_TO_POINTER(pinfo->fd->num), result);
1258 /* Allocate entry in table for this UE/RNTI */
1259 ueData = se_alloc0(sizeof(LastFrameDataAllSubframes));
1260 g_hash_table_insert(mac_lte_ul_harq_hash, GUINT_TO_POINTER((guint)p_mac_lte_info->rnti), ueData);
1263 /* Store this frame's details in table */
1264 thisData = &(ueData->subframe[p_mac_lte_info->subframeNumber]);
1265 thisData->inUse = TRUE;
1266 thisData->length = tvb_length_remaining(tvb, offset);
1267 memcpy(thisData->data, tvb_get_ptr(tvb, offset, MIN(thisData->length, MAX_EXPECTED_PDU_LENGTH)), thisData->length);
1268 thisData->subframeNumber = p_mac_lte_info->subframeNumber;
1269 thisData->framenum = pinfo->fd->num;
1270 thisData->received_time = pinfo->fd->abs_ts;
1273 /* Not first time, so just set whats already stored in result */
1274 result = g_hash_table_lookup(mac_lte_ul_harq_result_hash, GUINT_TO_POINTER(pinfo->fd->num));
1277 if (retx_ti != NULL) {
1278 if (result != NULL) {
1279 proto_item *original_ti;
1281 original_ti = proto_tree_add_uint(tree, hf_mac_lte_ul_harq_resend_original_frame,
1282 tvb, 0, 0, result->previousFrameNum);
1283 PROTO_ITEM_SET_GENERATED(original_ti);
1286 expert_add_info_format(pinfo, retx_ti, PI_SEQUENCE, PI_ERROR,
1287 "Original Tx of UL frame not found (UE %u) !!", p_mac_lte_info->ueid);
1296 #define MAX_HEADERS_IN_PDU 1024
1298 /* UL-SCH and DL-SCH formats have much in common, so handle them in a common
1300 static void dissect_ulsch_or_dlsch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1302 volatile int offset, guint8 direction,
1303 mac_lte_info *p_mac_lte_info, mac_lte_tap_info *tap_info,
1304 proto_item *retx_ti)
1308 proto_item *truncated_ti;
1309 proto_item *padding_length_ti;
1311 /* Keep track of LCIDs and lengths as we dissect the header */
1312 volatile guint8 number_of_headers = 0;
1313 guint8 lcids[MAX_HEADERS_IN_PDU];
1314 gint16 pdu_lengths[MAX_HEADERS_IN_PDU];
1316 proto_item *pdu_header_ti;
1317 proto_tree *pdu_header_tree;
1319 gboolean have_seen_data_header = FALSE;
1320 gboolean have_seen_bsr = FALSE;
1321 gboolean expecting_body_data = FALSE;
1322 volatile guint32 is_truncated = FALSE;
1324 col_append_fstr(pinfo->cinfo, COL_INFO, "%s: (SF=%u) UEId=%u ",
1325 (direction == DIRECTION_UPLINK) ? "UL-SCH" : "DL-SCH",
1326 p_mac_lte_info->subframeNumber,
1327 p_mac_lte_info->ueid);
1330 /* For downlink frames, can try to work out if this looks like a HARQ resend */
1331 if ((direction == DIRECTION_DOWNLINK) && global_mac_lte_attempt_dl_harq_resend_detect) {
1332 DetectIfDLHARQResend(pinfo, tvb, offset, tree, p_mac_lte_info);
1336 /* For uplink frames, if this is logged as a resend, look for original tx */
1337 if ((direction == DIRECTION_UPLINK) && global_mac_lte_attempt_ul_harq_resend_track) {
1338 TrackReportedULHARQResend(pinfo, tvb, offset, tree, p_mac_lte_info, retx_ti);
1342 /* Add PDU block header subtree */
1343 pdu_header_ti = proto_tree_add_string_format(tree,
1344 (direction == DIRECTION_UPLINK) ?
1345 hf_mac_lte_ulsch_header :
1346 hf_mac_lte_dlsch_header,
1350 pdu_header_tree = proto_item_add_subtree(pdu_header_ti,
1351 (direction == DIRECTION_UPLINK) ?
1352 ett_mac_lte_ulsch_header :
1353 ett_mac_lte_dlsch_header);
1356 /************************************************************************/
1357 /* Dissect each sub-header. */
1361 proto_item *pdu_subheader_ti;
1362 proto_tree *pdu_subheader_tree;
1363 proto_item *lcid_ti;
1365 gint offset_start_subheader = offset;
1366 guint8 first_byte = tvb_get_guint8(tvb, offset);
1368 /* Add PDU block header subtree */
1369 pdu_subheader_ti = proto_tree_add_string_format(pdu_header_tree,
1370 hf_mac_lte_sch_subheader,
1374 pdu_subheader_tree = proto_item_add_subtree(pdu_subheader_ti,
1375 ett_mac_lte_sch_subheader);
1377 /* Check 1st 2 reserved bits */
1378 reserved = (first_byte & 0xc0) >> 6;
1379 ti = proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_sch_reserved,
1380 tvb, offset, 1, FALSE);
1381 if (reserved != 0) {
1382 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
1383 "U/DL-SCH header Reserved bits not zero");
1387 extension = (first_byte & 0x20) >> 5;
1388 proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_sch_extended,
1389 tvb, offset, 1, FALSE);
1391 /* LCID. Has different meaning depending upon direction. */
1392 lcids[number_of_headers] = first_byte & 0x1f;
1393 if (direction == DIRECTION_UPLINK) {
1394 lcid_ti = proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_ulsch_lcid,
1395 tvb, offset, 1, FALSE);
1396 col_append_fstr(pinfo->cinfo, COL_INFO, "(%s",
1397 val_to_str(lcids[number_of_headers],
1398 ulsch_lcid_vals, "(Unknown LCID)"));
1401 lcid_ti = proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_dlsch_lcid,
1402 tvb, offset, 1, FALSE);
1403 col_append_fstr(pinfo->cinfo, COL_INFO, "(%s",
1404 val_to_str(lcids[number_of_headers],
1405 dlsch_lcid_vals, "(Unknown LCID)"));
1409 /* Remember if we've seen a data subheader */
1410 if (lcids[number_of_headers] <= 10) {
1411 have_seen_data_header = TRUE;
1412 expecting_body_data = TRUE;
1415 /* Show an expert item if a contol subheader (except Padding) appears
1416 *after* a data PDU */
1417 if (have_seen_data_header &&
1418 (lcids[number_of_headers] > 10) && (lcids[number_of_headers] != PADDING_LCID)) {
1419 expert_add_info_format(pinfo, lcid_ti, PI_MALFORMED, PI_ERROR,
1420 "Control subheaders should not appear after data subheaders");
1423 /* Show an expert item if we're seeing more then one BSR in a frame */
1424 if ((direction == DIRECTION_UPLINK) && is_bsr_lcid(lcids[number_of_headers])) {
1425 if (have_seen_bsr) {
1426 expert_add_info_format(pinfo, lcid_ti, PI_MALFORMED, PI_ERROR,
1427 "There shouldn't be > 1 BSR in a frame");
1429 have_seen_bsr = TRUE;
1433 /********************************************************************/
1434 /* Length field follows if not the last header or for a fixed-sized
1437 if (is_fixed_sized_control_element(lcids[number_of_headers], direction)) {
1438 pdu_lengths[number_of_headers] = 0;
1441 pdu_lengths[number_of_headers] = -1;
1445 if (!is_fixed_sized_control_element(lcids[number_of_headers], direction) &&
1446 (lcids[number_of_headers] != PADDING_LCID)) {
1450 /* F(ormat) bit tells us how long the length field is */
1451 format = (tvb_get_guint8(tvb, offset) & 0x80) >> 7;
1452 proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_sch_format,
1453 tvb, offset, 1, FALSE);
1455 /* Now read length field itself */
1457 /* >= 128 - use 15 bits */
1458 proto_tree_add_bits_ret_val(pdu_subheader_tree, hf_mac_lte_sch_length,
1459 tvb, offset*8 + 1, 15, &length, FALSE);
1464 /* Less than 128 - only 7 bits */
1465 proto_tree_add_bits_ret_val(pdu_subheader_tree, hf_mac_lte_sch_length,
1466 tvb, offset*8 + 1, 7, &length, FALSE);
1469 pdu_lengths[number_of_headers] = (gint16)length;
1472 pdu_lengths[number_of_headers] = 0;
1477 /* Close off description in info column */
1478 switch (pdu_lengths[number_of_headers]) {
1480 col_append_str(pinfo->cinfo, COL_INFO, ") ");
1483 col_append_str(pinfo->cinfo, COL_INFO, ":remainder) ");
1486 col_append_fstr(pinfo->cinfo, COL_INFO, ":%u bytes) ",
1487 pdu_lengths[number_of_headers]);
1491 /* Append summary to subheader root */
1492 proto_item_append_text(pdu_subheader_ti, " (lcid=%s",
1493 val_to_str(lcids[number_of_headers],
1494 (direction == DIRECTION_UPLINK) ?
1499 switch (pdu_lengths[number_of_headers]) {
1501 proto_item_append_text(pdu_subheader_ti, ", length is remainder)");
1504 proto_item_append_text(pdu_subheader_ti, ")");
1507 proto_item_append_text(pdu_subheader_ti, ", length=%u)",
1508 pdu_lengths[number_of_headers]);
1513 /* Flag unknown lcid values in expert info */
1514 if (strncmp(val_to_str(lcids[number_of_headers],
1515 (direction == DIRECTION_UPLINK) ? ulsch_lcid_vals : dlsch_lcid_vals,
1518 sizeof("Unknown")) == 0) {
1519 expert_add_info_format(pinfo, pdu_subheader_ti, PI_MALFORMED, PI_ERROR,
1520 "Unexpected LCID received (%u)", lcids[number_of_headers]);
1523 /* Set length of this subheader */
1524 proto_item_set_len(pdu_subheader_ti, offset- offset_start_subheader);
1526 number_of_headers++;
1527 } while (extension);
1529 /* Append summary to overall PDU header root */
1530 proto_item_append_text(pdu_header_ti, " (%u subheaders)",
1533 /* And set its length to offset */
1534 proto_item_set_len(pdu_header_ti, offset);
1539 /************************************************************************/
1540 /* Dissect SDUs / control elements / padding. */
1541 /************************************************************************/
1543 /* Dissect control element bodies first */
1545 for (n=0; n < number_of_headers; n++) {
1546 /* Get out of loop once see any data SDU subheaders */
1547 if (lcids[n] <= 10) {
1551 /* Process what should be a valid control PDU type */
1552 if (direction == DIRECTION_DOWNLINK) {
1554 /****************************/
1555 /* DL-SCH Control PDUs */
1557 case UE_CONTENTION_RESOLUTION_IDENTITY_LCID:
1560 proto_tree *cr_tree;
1562 ContentionResolutionResult *crResult;
1564 /* Create CR root */
1565 cr_ti = proto_tree_add_string_format(tree,
1566 hf_mac_lte_control_ue_contention_resolution,
1569 "Contention Resolution");
1570 cr_tree = proto_item_add_subtree(cr_ti, ett_mac_lte_contention_resolution);
1573 proto_tree_add_item(cr_tree, hf_mac_lte_control_ue_contention_resolution_identity,
1574 tvb, offset, 6, FALSE);
1576 /* Get pointer to result struct for this frame */
1577 crResult = g_hash_table_lookup(mac_lte_cr_result_hash, GUINT_TO_POINTER(pinfo->fd->num));
1578 if (crResult == NULL) {
1580 /* Need to set result by looking for and comparing with Msg3 */
1582 guint msg3Key = p_mac_lte_info->rnti;
1584 /* Allocate result and add it to the table */
1585 crResult = se_alloc(sizeof(ContentionResolutionResult));
1586 g_hash_table_insert(mac_lte_cr_result_hash, GUINT_TO_POINTER(pinfo->fd->num), crResult);
1589 msg3Data = g_hash_table_lookup(mac_lte_msg3_hash, GUINT_TO_POINTER(msg3Key));
1591 /* Compare CCCH bytes */
1592 if (msg3Data != NULL) {
1593 crResult->msg3FrameNum = msg3Data->framenum;
1594 if (memcmp(&msg3Data->data, tvb_get_ptr(tvb, offset, 6), 6) == 0) {
1595 crResult->status = Msg3Match;
1598 crResult->status = Msg3NoMatch;
1602 crResult->status = NoMsg3;
1606 /* Now show CR result in tree */
1607 switch (crResult->status) {
1609 proto_item_append_text(cr_ti, " (no corresponding Msg3 found!)");
1613 ti = proto_tree_add_uint(cr_tree, hf_mac_lte_control_ue_contention_resolution_msg3,
1614 tvb, 0, 0, crResult->msg3FrameNum);
1615 PROTO_ITEM_SET_GENERATED(ti);
1616 ti = proto_tree_add_boolean(cr_tree, hf_mac_lte_control_ue_contention_resolution_msg3_matched,
1618 PROTO_ITEM_SET_GENERATED(ti);
1619 proto_item_append_text(cr_ti, " (matches Msg3 from frame %u)", crResult->msg3FrameNum);
1623 ti = proto_tree_add_uint(cr_tree, hf_mac_lte_control_ue_contention_resolution_msg3,
1624 tvb, 0, 0, crResult->msg3FrameNum);
1625 PROTO_ITEM_SET_GENERATED(ti);
1626 ti = proto_tree_add_boolean(cr_tree, hf_mac_lte_control_ue_contention_resolution_msg3_matched,
1628 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
1629 "CR body in Msg4 doesn't match Msg3 CCCH in frame %u",
1630 crResult->msg3FrameNum);
1631 PROTO_ITEM_SET_GENERATED(ti);
1632 proto_item_append_text(cr_ti, " (doesn't match Msg3 from frame %u)", crResult->msg3FrameNum);
1639 case TIMING_ADVANCE_LCID:
1642 proto_item *reserved_ti;
1646 /* Check 2 reserved bits */
1647 reserved = (tvb_get_guint8(tvb, offset) & 0xc0) >> 6;
1648 reserved_ti = proto_tree_add_item(tree, hf_mac_lte_control_timing_advance_reserved, tvb, offset, 1, FALSE);
1649 if (reserved != 0) {
1650 expert_add_info_format(pinfo, reserved_ti, PI_MALFORMED, PI_ERROR,
1651 "Timing Advance Reserved bits not zero (found 0x%x)", reserved);
1655 ta_value = tvb_get_guint8(tvb, offset) & 0x3f;
1656 ta_ti = proto_tree_add_item(tree, hf_mac_lte_control_timing_advance,
1657 tvb, offset, 1, FALSE);
1658 expert_add_info_format(pinfo, ta_ti, PI_SEQUENCE, PI_WARN,
1659 "Timing Advance control element received (%u)",
1664 case DRX_COMMAND_LCID:
1668 /* No payload (in this position) */
1677 /**********************************/
1678 /* UL-SCH Control PDUs */
1680 case POWER_HEADROOM_REPORT_LCID:
1683 proto_tree *phr_tree;
1688 /* Create PHR root */
1689 phr_ti = proto_tree_add_string_format(tree,
1690 hf_mac_lte_control_power_headroom,
1694 phr_tree = proto_item_add_subtree(phr_ti, ett_mac_lte_power_headroom);
1696 /* Check 2 Reserved bits */
1697 reserved = (tvb_get_guint8(tvb, offset) & 0xc0) >> 6;
1698 ti = proto_tree_add_item(phr_tree, hf_mac_lte_control_power_headroom_reserved,
1699 tvb, offset, 1, FALSE);
1700 if (reserved != 0) {
1701 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
1702 "Power Headroom Reserved bits not zero (found 0x%x)", reserved);
1706 level = tvb_get_guint8(tvb, offset) & 0x3f;
1707 proto_tree_add_item(phr_tree, hf_mac_lte_control_power_headroom_level,
1708 tvb, offset, 1, FALSE);
1710 /* Show value in root label */
1711 proto_item_append_text(phr_ti, " (POWER_HEADROOM_%u)", level);
1718 proto_tree_add_item(tree, hf_mac_lte_control_crnti,
1719 tvb, offset, 2, FALSE);
1722 case TRUNCATED_BSR_LCID:
1723 case SHORT_BSR_LCID:
1725 proto_tree *bsr_tree;
1727 proto_item *buffer_size_ti;
1731 bsr_ti = proto_tree_add_string_format(tree,
1732 hf_mac_lte_control_bsr,
1736 bsr_tree = proto_item_add_subtree(bsr_ti, ett_mac_lte_bsr);
1739 lcgid = (tvb_get_guint8(tvb, offset) & 0xc0) >> 6;
1740 proto_tree_add_item(bsr_tree, hf_mac_lte_control_bsr_lcg_id,
1741 tvb, offset, 1, FALSE);
1743 buffer_size = tvb_get_guint8(tvb, offset) & 0x3f;
1744 buffer_size_ti = proto_tree_add_item(bsr_tree, hf_mac_lte_control_short_bsr_buffer_size,
1745 tvb, offset, 1, FALSE);
1747 if (buffer_size >= global_mac_lte_bsr_warn_threshold) {
1748 expert_add_info_format(pinfo, buffer_size_ti, PI_SEQUENCE, PI_WARN,
1749 "UE %u - BSR for LCG %u exceeds threshold: %u (%s)",
1750 p_mac_lte_info->ueid,
1752 buffer_size, val_to_str(buffer_size, buffer_size_vals, "Unknown"));
1756 proto_item_append_text(bsr_ti, " (lcgid=%u %s)",
1758 val_to_str(buffer_size, buffer_size_vals, "Unknown"));
1763 proto_tree *bsr_tree;
1765 proto_item *buffer_size_ti;
1766 guint8 buffer_size[4];
1767 bsr_ti = proto_tree_add_string_format(tree,
1768 hf_mac_lte_control_bsr,
1772 bsr_tree = proto_item_add_subtree(bsr_ti, ett_mac_lte_bsr);
1775 buffer_size_ti = proto_tree_add_item(bsr_tree, hf_mac_lte_control_long_bsr_buffer_size_0,
1776 tvb, offset, 1, FALSE);
1777 buffer_size[0] = (tvb_get_guint8(tvb, offset) & 0xfc) >> 2;
1778 if (buffer_size[0] >= global_mac_lte_bsr_warn_threshold) {
1779 expert_add_info_format(pinfo, buffer_size_ti, PI_SEQUENCE, PI_WARN,
1780 "UE %u - BSR for LCG 0 exceeds threshold: %u (%s)",
1781 p_mac_lte_info->ueid,
1782 buffer_size[0], val_to_str(buffer_size[0], buffer_size_vals, "Unknown"));
1786 buffer_size_ti = proto_tree_add_item(bsr_tree, hf_mac_lte_control_long_bsr_buffer_size_1,
1787 tvb, offset, 2, FALSE);
1788 buffer_size[1] = ((tvb_get_guint8(tvb, offset) & 0x03) << 4) | ((tvb_get_guint8(tvb, offset+1) & 0xf0) >> 4);
1790 if (buffer_size[1] >= global_mac_lte_bsr_warn_threshold) {
1791 expert_add_info_format(pinfo, buffer_size_ti, PI_SEQUENCE, PI_WARN,
1792 "UE %u - BSR for LCG 1 exceeds threshold: %u (%s)",
1793 p_mac_lte_info->ueid,
1794 buffer_size[1], val_to_str(buffer_size[1], buffer_size_vals, "Unknown"));
1798 buffer_size_ti = proto_tree_add_item(bsr_tree, hf_mac_lte_control_long_bsr_buffer_size_2,
1799 tvb, offset, 2, FALSE);
1801 buffer_size[2] = ((tvb_get_guint8(tvb, offset) & 0x0f) << 2) | ((tvb_get_guint8(tvb, offset+1) & 0xc0) >> 6);
1803 if (buffer_size[2] >= global_mac_lte_bsr_warn_threshold) {
1804 expert_add_info_format(pinfo, buffer_size_ti, PI_SEQUENCE, PI_WARN,
1805 "UE %u - BSR for LCG 2 exceeds threshold: %u (%s)",
1806 p_mac_lte_info->ueid,
1807 buffer_size[2], val_to_str(buffer_size[2], buffer_size_vals, "Unknown"));
1811 buffer_size_ti = proto_tree_add_item(bsr_tree, hf_mac_lte_control_long_bsr_buffer_size_3,
1812 tvb, offset, 1, FALSE);
1813 buffer_size[3] = tvb_get_guint8(tvb, offset) & 0x3f;
1815 if (buffer_size[3] >= global_mac_lte_bsr_warn_threshold) {
1816 expert_add_info_format(pinfo, buffer_size_ti, PI_SEQUENCE, PI_WARN,
1817 "UE %u - BSR for LCG 3 exceeds threshold: %u (%s)",
1818 p_mac_lte_info->ueid,
1819 buffer_size[3], val_to_str(buffer_size[3], buffer_size_vals, "Unknown"));
1822 /* Append summary to parent */
1823 proto_item_append_text(bsr_ti, " 0:(%s) 1:(%s) 2:(%s) 3:(%s)",
1824 val_to_str(buffer_size[0], buffer_size_vals, "Unknown"),
1825 val_to_str(buffer_size[1], buffer_size_vals, "Unknown"),
1826 val_to_str(buffer_size[2], buffer_size_vals, "Unknown"),
1827 val_to_str(buffer_size[3], buffer_size_vals, "Unknown"));
1831 /* No payload, in this position */
1841 /* There might not be any data, if only headers (plus control data) were logged */
1842 is_truncated = ((tvb_length_remaining(tvb, offset) == 0) && expecting_body_data);
1843 truncated_ti = proto_tree_add_uint(tree, hf_mac_lte_sch_header_only, tvb, 0, 0,
1846 PROTO_ITEM_SET_GENERATED(truncated_ti);
1847 expert_add_info_format(pinfo, truncated_ti, PI_SEQUENCE, PI_NOTE,
1848 "MAC PDU SDUs have been ommitted");
1852 PROTO_ITEM_SET_HIDDEN(truncated_ti);
1856 /* Now process remaining bodies, which should all be data */
1857 for (; n < number_of_headers; n++) {
1859 /* Data SDUs treated identically for Uplink or downlink channels */
1861 volatile guint16 data_length;
1863 /* Break out if meet padding */
1864 if (lcids[n] == PADDING_LCID) {
1868 /* Work out length */
1869 data_length = (pdu_lengths[n] == -1) ?
1870 tvb_length_remaining(tvb, offset) :
1873 /* Dissect SDU as raw bytes */
1874 sdu_ti = proto_tree_add_bytes_format(tree, hf_mac_lte_sch_sdu, tvb, offset, pdu_lengths[n],
1875 tvb_get_ptr(tvb, offset, pdu_lengths[n]),
1876 "SDU (%s, length=%u bytes)",
1877 val_to_str(lcids[n],
1878 (direction == DIRECTION_UPLINK) ?
1884 /* Look for Msg3 data so that it may be compared with later
1885 Contention Resolution body */
1886 if ((lcids[n] == 0) && (direction == DIRECTION_UPLINK) && (data_length == 6)) {
1887 if (!pinfo->fd->flags.visited) {
1888 guint key = p_mac_lte_info->rnti;
1889 Msg3Data *data = g_hash_table_lookup(mac_lte_msg3_hash, GUINT_TO_POINTER(key));
1891 /* Look for previous entry for this UE */
1893 /* Allocate space for data and add to table */
1894 data = se_alloc(sizeof(Msg3Data));
1895 g_hash_table_insert(mac_lte_msg3_hash, GUINT_TO_POINTER(key), data);
1898 /* Fill in data details */
1899 data->framenum = pinfo->fd->num;
1900 memcpy(&data->data, tvb_get_ptr(tvb, offset, data_length), data_length);
1904 /* CCCH frames can be dissected directly by LTE RRC... */
1905 if ((lcids[n] == 0) && global_mac_lte_attempt_rrc_decode) {
1906 tvbuff_t *rrc_tvb = tvb_new_subset(tvb, offset, data_length, data_length);
1908 /* Get appropriate dissector handle */
1909 volatile dissector_handle_t protocol_handle = 0;
1910 if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
1911 protocol_handle = find_dissector("lte-rrc.ul.ccch");
1914 protocol_handle = find_dissector("lte-rrc.dl.ccch");
1917 /* Hide raw view of bytes */
1918 PROTO_ITEM_SET_HIDDEN(sdu_ti);
1920 /* Call it (catch exceptions so that stats will be updated) */
1922 call_dissector_only(protocol_handle, rrc_tvb, pinfo, tree);
1929 /* LCID 1 and 2 can be assumed to be srb1&2, so can dissect as RLC AM */
1930 if ((lcids[n] == 1) || (lcids[n] == 2)) {
1931 if (global_mac_lte_attempt_srb_decode) {
1932 /* Call RLC dissector */
1933 call_rlc_dissector(tvb, pinfo, tree, offset, data_length,
1934 RLC_AM_MODE, direction, p_mac_lte_info->ueid,
1935 CHANNEL_TYPE_SRB, lcids[n], 0);
1937 /* Hide raw view of bytes */
1938 PROTO_ITEM_SET_HIDDEN(sdu_ti);
1942 else if ((lcids[n] >= 2) && (lcids[n] <= 10)) {
1944 /* Look for mapping for this LCID to drb channel set by UAT table */
1945 rlc_channel_type_t rlc_channel_type = rlcRaw;
1946 guint8 UM_seqnum_length = 0;
1950 for (m=0; m < num_lcid_drb_mappings; m++) {
1951 if (lcids[n] == lcid_drb_mappings[m].lcid) {
1953 rlc_channel_type = lcid_drb_mappings[m].channel_type;
1955 /* Set UM_seqnum_length */
1956 switch (lcid_drb_mappings[m].channel_type) {
1958 UM_seqnum_length = 5;
1961 UM_seqnum_length = 10;
1968 drb_id = lcid_drb_mappings[m].drbid;
1973 /* Dissect according to channel type */
1974 switch (rlc_channel_type) {
1976 call_rlc_dissector(tvb, pinfo, tree, offset, data_length,
1977 RLC_UM_MODE, direction, p_mac_lte_info->ueid,
1978 CHANNEL_TYPE_DRB, (guint16)drb_id, UM_seqnum_length);
1981 call_rlc_dissector(tvb, pinfo, tree, offset, data_length,
1982 RLC_UM_MODE, direction, p_mac_lte_info->ueid,
1983 CHANNEL_TYPE_DRB, (guint16)drb_id, UM_seqnum_length);
1986 call_rlc_dissector(tvb, pinfo, tree, offset, data_length,
1987 RLC_AM_MODE, direction, p_mac_lte_info->ueid,
1988 CHANNEL_TYPE_DRB, (guint16)drb_id, 0);
1991 call_rlc_dissector(tvb, pinfo, tree, offset, data_length,
1992 RLC_TM_MODE, direction, p_mac_lte_info->ueid,
1993 CHANNEL_TYPE_DRB, (guint16)drb_id, 0);
1996 /* Nothing to do! */
2000 if (rlc_channel_type != rlcRaw) {
2001 /* Hide raw view of bytes */
2002 PROTO_ITEM_SET_HIDDEN(sdu_ti);
2007 offset += data_length;
2009 /* Update tap byte count for this channel */
2010 tap_info->bytes_for_lcid[lcids[n]] += data_length;
2011 tap_info->sdus_for_lcid[lcids[n]]++;
2014 /* Now padding, if present, extends to the end of the PDU */
2015 if (lcids[number_of_headers-1] == PADDING_LCID) {
2016 if (tvb_length_remaining(tvb, offset) > 0) {
2017 proto_tree_add_item(tree, hf_mac_lte_padding_data,
2018 tvb, offset, -1, FALSE);
2020 padding_length_ti = proto_tree_add_int(tree, hf_mac_lte_padding_length,
2022 p_mac_lte_info->length - offset);
2023 PROTO_ITEM_SET_GENERATED(padding_length_ti);
2025 /* Make sure the PDU isn't bigger than reported! */
2026 if (offset > p_mac_lte_info->length) {
2027 expert_add_info_format(pinfo, padding_length_ti, PI_MALFORMED, PI_ERROR,
2028 "MAC PDU is longer than reported length (reported=%u, actual=%u)",
2029 p_mac_lte_info->length, offset);
2033 /* There is no padding at the end of the frame */
2034 if (!is_truncated && (offset < p_mac_lte_info->length)) {
2035 /* There is a problem if we haven't used all of the PDU */
2036 expert_add_info_format(pinfo, pdu_ti, PI_MALFORMED, PI_ERROR,
2037 "MAC PDU is shorter than reported length (reported=%u, actual=%u)",
2038 p_mac_lte_info->length, offset);
2046 /*****************************/
2047 /* Main dissection function. */
2048 void dissect_mac_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2050 proto_tree *mac_lte_tree;
2052 proto_item *retx_ti = NULL;
2055 struct mac_lte_info *p_mac_lte_info = NULL;
2058 static mac_lte_tap_info tap_info;
2059 memset(&tap_info, 0, sizeof(mac_lte_tap_info));
2061 /* Set protocol name */
2062 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MAC-LTE");
2064 /* Create protocol tree. */
2065 pdu_ti = proto_tree_add_item(tree, proto_mac_lte, tvb, offset, -1, FALSE);
2066 mac_lte_tree = proto_item_add_subtree(pdu_ti, ett_mac_lte);
2069 /* Look for packet info! */
2070 p_mac_lte_info = p_get_proto_data(pinfo->fd, proto_mac_lte);
2072 /* Can't dissect anything without it... */
2073 if (p_mac_lte_info == NULL) {
2075 proto_tree_add_text(mac_lte_tree, tvb, offset, -1,
2076 "Can't dissect LTE MAC frame because no per-frame info was attached!");
2077 PROTO_ITEM_SET_GENERATED(ti);
2081 /* Clear info column */
2082 col_clear(pinfo->cinfo, COL_INFO);
2085 /*****************************************/
2086 /* Show context information */
2088 ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_context_radio_type,
2089 tvb, 0, 0, p_mac_lte_info->radioType);
2090 PROTO_ITEM_SET_GENERATED(ti);
2092 ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_context_direction,
2093 tvb, 0, 0, p_mac_lte_info->direction);
2094 PROTO_ITEM_SET_GENERATED(ti);
2096 if (p_mac_lte_info->ueid != 0) {
2097 ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_context_ueid,
2098 tvb, 0, 0, p_mac_lte_info->ueid);
2099 PROTO_ITEM_SET_GENERATED(ti);
2102 /* There are several out-of-band MAC events that may be indicated in the context info. */
2103 /* Handle them here */
2104 if (p_mac_lte_info->length == 0) {
2105 switch (p_mac_lte_info->oob_event) {
2106 case ltemac_send_preamble:
2107 ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_context_rapid,
2108 tvb, 0, 0, p_mac_lte_info->rapid);
2109 PROTO_ITEM_SET_GENERATED(ti);
2110 ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_context_rach_attempt_number,
2111 tvb, 0, 0, p_mac_lte_info->rach_attempt_number);
2112 PROTO_ITEM_SET_GENERATED(ti);
2113 ti = proto_tree_add_item(mac_lte_tree, hf_mac_lte_oob_send_preamble,
2115 PROTO_ITEM_SET_GENERATED(ti);
2118 col_append_fstr(pinfo->cinfo, COL_INFO, "RACH Preamble sent for UE %u (RAPID=%u, attempt=%u)",
2119 p_mac_lte_info->ueid, p_mac_lte_info->rapid, p_mac_lte_info->rach_attempt_number);
2121 /* Add expert info (a note, unless attempt > 1) */
2122 expert_add_info_format(pinfo, ti, PI_SEQUENCE,
2123 (p_mac_lte_info->rach_attempt_number > 1) ? PI_WARN : PI_NOTE,
2124 "RACH Preamble sent for UE %u (RAPID=%u, attempt=%u)",
2125 p_mac_lte_info->ueid, p_mac_lte_info->rapid,
2126 p_mac_lte_info->rach_attempt_number);
2128 case ltemac_send_sr:
2129 ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_context_rnti,
2130 tvb, 0, 0, p_mac_lte_info->rnti);
2131 PROTO_ITEM_SET_GENERATED(ti);
2132 ti = proto_tree_add_item(mac_lte_tree, hf_mac_lte_oob_send_sr,
2134 PROTO_ITEM_SET_GENERATED(ti);
2137 col_append_fstr(pinfo->cinfo, COL_INFO, "Scheduling Request sent for UE %u (C-RNTI=%u)",
2138 p_mac_lte_info->ueid, p_mac_lte_info->rnti);
2140 /* Add expert info (an note) */
2141 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_NOTE,
2142 "Scheduling Request send for UE %u (RNTI %u)",
2143 p_mac_lte_info->ueid, p_mac_lte_info->rnti);
2145 case ltemac_sr_failure:
2146 ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_context_rnti,
2147 tvb, 0, 0, p_mac_lte_info->rnti);
2148 PROTO_ITEM_SET_GENERATED(ti);
2149 ti = proto_tree_add_item(mac_lte_tree, hf_mac_lte_oob_sr_failure,
2151 PROTO_ITEM_SET_GENERATED(ti);
2154 col_append_fstr(pinfo->cinfo, COL_INFO, "Scheduling Request FAILED (C-RNTI=%u)!",
2155 p_mac_lte_info->rnti);
2157 /* Add expert info (an error) */
2158 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_ERROR,
2159 "Scheduling Request failed for RNTI %u",
2160 p_mac_lte_info->rnti);
2164 /* Our work here is done */
2169 ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_context_subframe_number,
2170 tvb, 0, 0, p_mac_lte_info->subframeNumber);
2171 PROTO_ITEM_SET_GENERATED(ti);
2173 if (p_mac_lte_info->rntiType != NO_RNTI) {
2174 ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_context_rnti,
2175 tvb, 0, 0, p_mac_lte_info->rnti);
2176 PROTO_ITEM_SET_GENERATED(ti);
2179 ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_context_rnti_type,
2180 tvb, 0, 0, p_mac_lte_info->rntiType);
2181 PROTO_ITEM_SET_GENERATED(ti);
2183 ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_context_predefined_frame,
2184 tvb, 0, 0, p_mac_lte_info->isPredefinedData);
2185 if (p_mac_lte_info->isPredefinedData) {
2186 PROTO_ITEM_SET_GENERATED(ti);
2189 PROTO_ITEM_SET_HIDDEN(ti);
2192 ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_context_length,
2193 tvb, 0, 0, p_mac_lte_info->length);
2194 PROTO_ITEM_SET_GENERATED(ti);
2195 /* Infer uplink grant size */
2196 if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
2197 ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_context_ul_grant_size,
2198 tvb, 0, 0, p_mac_lte_info->length);
2199 PROTO_ITEM_SET_GENERATED(ti);
2203 if (p_mac_lte_info->reTxCount) {
2204 retx_ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_context_retx_count,
2205 tvb, 0, 0, p_mac_lte_info->reTxCount);
2206 PROTO_ITEM_SET_GENERATED(retx_ti);
2208 if (p_mac_lte_info->reTxCount >= global_mac_lte_retx_counter_trigger) {
2209 expert_add_info_format(pinfo, retx_ti, PI_SEQUENCE, PI_ERROR,
2210 "UE %u: UL MAC frame ReTX no. %u",
2211 p_mac_lte_info->ueid, p_mac_lte_info->reTxCount);
2215 if (p_mac_lte_info->crcStatusValid) {
2216 ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_context_crc_status,
2217 tvb, 0, 0, p_mac_lte_info->crcStatus);
2218 PROTO_ITEM_SET_GENERATED(ti);
2219 if (p_mac_lte_info->crcStatus != TRUE) {
2220 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
2221 "%s Frame has CRC error",
2222 (p_mac_lte_info->direction == DIRECTION_UPLINK) ? "UL" : "DL");
2223 col_append_fstr(pinfo->cinfo, COL_INFO, "%s: <CRC FAILURE> UEId=%u %s=%u ",
2224 (p_mac_lte_info->direction == DIRECTION_UPLINK) ? "UL" : "DL",
2225 p_mac_lte_info->ueid,
2226 val_to_str(p_mac_lte_info->rntiType, rnti_type_vals,
2227 "Unknown RNTI type"),
2228 p_mac_lte_info->rnti);
2233 /* Set context-info parts of tap struct */
2234 tap_info.rnti = p_mac_lte_info->rnti;
2235 tap_info.rntiType = p_mac_lte_info->rntiType;
2236 tap_info.isPredefinedData = p_mac_lte_info->isPredefinedData;
2237 tap_info.reTxCount = p_mac_lte_info->reTxCount;
2238 tap_info.crcStatusValid = p_mac_lte_info->crcStatusValid;
2239 tap_info.crcStatus = p_mac_lte_info->crcStatus;
2240 tap_info.direction = p_mac_lte_info->direction;
2242 /* Also set total number of bytes (won't be used for UL/DL-SCH) */
2243 tap_info.single_number_of_bytes = tvb_length_remaining(tvb, offset);
2245 /* If we know its predefined data, don't try to decode any further */
2246 if (p_mac_lte_info->isPredefinedData) {
2247 proto_tree_add_item(mac_lte_tree, hf_mac_lte_predefined_pdu, tvb, offset, -1, FALSE);
2248 col_append_fstr(pinfo->cinfo, COL_INFO, "Predefined data (%u bytes)", tvb_length_remaining(tvb, offset));
2250 /* Queue tap info */
2251 if (!pinfo->in_error_pkt) {
2252 tap_queue_packet(mac_lte_tap, pinfo, &tap_info);
2258 /* IF CRC status failed, just do decode as raw bytes */
2259 if (!global_mac_lte_dissect_crc_failures &&
2260 (p_mac_lte_info->crcStatusValid && !p_mac_lte_info->crcStatus)) {
2262 proto_tree_add_item(mac_lte_tree, hf_mac_lte_raw_pdu, tvb, offset, -1, FALSE);
2263 col_append_fstr(pinfo->cinfo, COL_INFO, "Raw data (%u bytes)", tvb_length_remaining(tvb, offset));
2265 /* Queue tap info */
2266 if (!pinfo->in_error_pkt) {
2267 tap_queue_packet(mac_lte_tap, pinfo, &tap_info);
2275 /* Dissect the MAC PDU itself. Format depends upon RNTI type. */
2276 switch (p_mac_lte_info->rntiType) {
2280 dissect_pch(tvb, pinfo, mac_lte_tree, offset, p_mac_lte_info->direction);
2285 dissect_rar(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info, &tap_info);
2290 /* Can be UL-SCH or DL-SCH */
2291 dissect_ulsch_or_dlsch(tvb, pinfo, mac_lte_tree, pdu_ti, offset,
2292 p_mac_lte_info->direction, p_mac_lte_info, &tap_info,
2297 /* BCH over DL-SCH */
2298 dissect_bch(tvb, pinfo, mac_lte_tree, offset, p_mac_lte_info);
2302 /* Must be BCH over BCH... */
2303 dissect_bch(tvb, pinfo, mac_lte_tree, offset, p_mac_lte_info);
2311 /* Queue tap info */
2312 /* TODO: if any of above (esp RRC dissection) throws exception, this isn't reached,
2313 but if call too early, won't have details... */
2314 tap_queue_packet(mac_lte_tap, pinfo, &tap_info);
2320 /* Initializes the hash table and the mem_chunk area each time a new
2321 * file is loaded or re-loaded in wireshark */
2323 mac_lte_init_protocol(void)
2325 /* Destroy any existing tables. */
2326 if (mac_lte_msg3_hash) {
2327 g_hash_table_destroy(mac_lte_msg3_hash);
2329 if (mac_lte_cr_result_hash) {
2330 g_hash_table_destroy(mac_lte_cr_result_hash);
2333 if (mac_lte_dl_harq_hash) {
2334 g_hash_table_destroy(mac_lte_dl_harq_hash);
2336 if (mac_lte_dl_harq_result_hash) {
2337 g_hash_table_destroy(mac_lte_dl_harq_result_hash);
2339 if (mac_lte_ul_harq_hash) {
2340 g_hash_table_destroy(mac_lte_ul_harq_hash);
2342 if (mac_lte_ul_harq_result_hash) {
2343 g_hash_table_destroy(mac_lte_ul_harq_result_hash);
2348 /* Now create them over */
2349 mac_lte_msg3_hash = g_hash_table_new(mac_lte_rnti_hash_func, mac_lte_rnti_hash_equal);
2350 mac_lte_cr_result_hash = g_hash_table_new(mac_lte_framenum_hash_func, mac_lte_framenum_hash_equal);
2352 mac_lte_dl_harq_hash = g_hash_table_new(mac_lte_rnti_hash_func, mac_lte_rnti_hash_equal);
2353 mac_lte_dl_harq_result_hash = g_hash_table_new(mac_lte_framenum_hash_func, mac_lte_framenum_hash_equal);
2355 mac_lte_ul_harq_hash = g_hash_table_new(mac_lte_rnti_hash_func, mac_lte_rnti_hash_equal);
2356 mac_lte_ul_harq_result_hash = g_hash_table_new(mac_lte_framenum_hash_func, mac_lte_framenum_hash_equal);
2360 static void* lcid_drb_mapping_copy_cb(void* dest, const void* orig, unsigned len _U_)
2362 const lcid_drb_mapping_t *o = orig;
2363 lcid_drb_mapping_t *d = dest;
2365 /* Copy all items over */
2367 d->drbid = o->drbid;
2368 d->channel_type = o->channel_type;
2375 void proto_register_mac_lte(void)
2377 static hf_register_info hf[] =
2379 /**********************************/
2380 /* Items for decoding context */
2381 { &hf_mac_lte_context_radio_type,
2383 "mac-lte.radio-type", FT_UINT8, BASE_DEC, VALS(radio_type_vals), 0x0,
2387 { &hf_mac_lte_context_direction,
2389 "mac-lte.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
2390 "Direction of message", HFILL
2393 { &hf_mac_lte_context_rnti,
2395 "mac-lte.rnti", FT_UINT16, BASE_DEC, 0, 0x0,
2396 "RNTI associated with message", HFILL
2399 { &hf_mac_lte_context_rnti_type,
2401 "mac-lte.rnti-type", FT_UINT8, BASE_DEC, VALS(rnti_type_vals), 0x0,
2402 "Type of RNTI associated with message", HFILL
2405 { &hf_mac_lte_context_ueid,
2407 "mac-lte.ueid", FT_UINT16, BASE_DEC, 0, 0x0,
2408 "User Equipment Identifier associated with message", HFILL
2411 { &hf_mac_lte_context_subframe_number,
2413 "mac-lte.subframe", FT_UINT16, BASE_DEC, 0, 0x0,
2414 "Subframe number associate with message", HFILL
2417 { &hf_mac_lte_context_predefined_frame,
2418 { "Predefined frame",
2419 "mac-lte.is-predefined-frame", FT_UINT8, BASE_DEC, VALS(predefined_frame_vals), 0x0,
2420 "Predefined test frame (or real MAC PDU)", HFILL
2423 { &hf_mac_lte_context_length,
2424 { "Length of frame",
2425 "mac-lte.length", FT_UINT8, BASE_DEC, 0, 0x0,
2426 "Original length of frame (including SDUs and padding)", HFILL
2429 { &hf_mac_lte_context_ul_grant_size,
2430 { "Uplink grant size",
2431 "mac-lte.ul-grant-size", FT_UINT8, BASE_DEC, 0, 0x0,
2432 "Uplink grant size (in bytes)", HFILL
2435 { &hf_mac_lte_context_bch_transport_channel,
2436 { "Transport channel",
2437 "mac-lte.bch-transport-channel", FT_UINT8, BASE_DEC, VALS(bch_transport_channel_vals), 0x0,
2438 "Transport channel BCH data was carried on", HFILL
2441 { &hf_mac_lte_context_retx_count,
2443 "mac-lte.retx-count", FT_UINT8, BASE_DEC, 0, 0x0,
2444 "Number of times this PDU has been retransmitted", HFILL
2447 { &hf_mac_lte_context_crc_status,
2449 "mac-lte.crc-status", FT_UINT8, BASE_DEC, VALS(crc_status_vals), 0x0,
2450 "CRC Status as reported by PHY", HFILL
2453 { &hf_mac_lte_context_rapid,
2455 "mac-lte.preamble-sent.rapid", FT_UINT8, BASE_DEC, 0, 0x0,
2456 "RAPID sent in RACH preamble", HFILL
2459 { &hf_mac_lte_context_rach_attempt_number,
2460 { "RACH Attempt Number",
2461 "mac-lte.preamble-sent.attempt", FT_UINT8, BASE_DEC, 0, 0x0,
2462 "RACH attempt number", HFILL
2466 /* Out-of-band events */
2467 { &hf_mac_lte_oob_send_preamble,
2468 { "RACH Preamble sent",
2469 "mac-lte.preamble-sent", FT_NONE, BASE_NONE, NULL, 0x0,
2473 { &hf_mac_lte_oob_send_sr,
2474 { "Scheduling Request sent",
2475 "mac-lte.sr-req", FT_NONE, BASE_NONE, NULL, 0x0,
2479 { &hf_mac_lte_oob_sr_failure,
2480 { "Scheduling Request Failure",
2481 "mac-lte.sr-failure", FT_NONE, BASE_NONE, NULL, 0x0,
2486 /*******************************************/
2487 /* MAC shared channel header fields */
2488 { &hf_mac_lte_ulsch_header,
2490 "mac-lte.ulsch.header", FT_STRING, BASE_NONE, NULL, 0x0,
2494 { &hf_mac_lte_dlsch_header,
2496 "mac-lte.dlsch.header", FT_STRING, BASE_NONE, NULL, 0x0,
2500 { &hf_mac_lte_sch_subheader,
2502 "mac-lte.sch.subheader", FT_STRING, BASE_NONE, NULL, 0x0,
2506 { &hf_mac_lte_sch_reserved,
2507 { "SCH reserved bits",
2508 "mac-lte.sch.reserved", FT_UINT8, BASE_HEX, NULL, 0xc0,
2512 { &hf_mac_lte_sch_extended,
2514 "mac-lte.sch.extended", FT_UINT8, BASE_HEX, 0, 0x20,
2515 "Extension - i.e. further headers after this one", HFILL
2518 { &hf_mac_lte_dlsch_lcid,
2520 "mac-lte.dlsch.lcid", FT_UINT8, BASE_HEX, VALS(dlsch_lcid_vals), 0x1f,
2521 "DL-SCH Logical Channel Identifier", HFILL
2524 { &hf_mac_lte_ulsch_lcid,
2526 "mac-lte.ulsch.lcid", FT_UINT8, BASE_HEX, VALS(ulsch_lcid_vals), 0x1f,
2527 "UL-SCH Logical Channel Identifier", HFILL
2530 { &hf_mac_lte_sch_format,
2532 "mac-lte.sch.format", FT_UINT8, BASE_HEX, VALS(format_vals), 0x80,
2536 { &hf_mac_lte_sch_length,
2538 "mac-lte.sch.length", FT_UINT16, BASE_DEC, 0, 0x0,
2539 "Length of MAC SDU or MAC control element", HFILL
2542 { &hf_mac_lte_sch_header_only,
2543 { "MAC PDU Header only",
2544 "mac-lte.sch.header-only", FT_UINT8, BASE_DEC, VALS(header_only_vals), 0x0,
2549 /********************************/
2551 { &hf_mac_lte_sch_sdu,
2553 "mac-lte.sch.sdu", FT_BYTES, BASE_NONE, 0, 0x0,
2554 "Shared channel SDU", HFILL
2557 { &hf_mac_lte_bch_pdu,
2559 "mac-lte.bch.pdu", FT_BYTES, BASE_NONE, 0, 0x0,
2563 { &hf_mac_lte_pch_pdu,
2565 "mac-lte.pch.pdu", FT_BYTES, BASE_NONE, 0, 0x0,
2569 { &hf_mac_lte_predefined_pdu,
2570 { "Predefined data",
2571 "mac-lte.predefined-data", FT_BYTES, BASE_NONE, 0, 0x0,
2572 "Predefined test data", HFILL
2575 { &hf_mac_lte_raw_pdu,
2577 "mac-lte.raw-data", FT_BYTES, BASE_NONE, 0, 0x0,
2578 "Raw bytes of PDU (e.g. if CRC failed)", HFILL
2581 { &hf_mac_lte_padding_data,
2583 "mac-lte.padding-data", FT_BYTES, BASE_NONE, 0, 0x0,
2587 { &hf_mac_lte_padding_length,
2589 "mac-lte.padding-length", FT_INT32, BASE_DEC, 0, 0x0,
2590 "Length of padding data not included at end of frame", HFILL
2596 /*********************************/
2600 "mac-lte.rar", FT_NONE, BASE_NONE, NULL, 0x0,
2604 { &hf_mac_lte_rar_headers,
2606 "mac-lte.rar.headers", FT_STRING, BASE_NONE, NULL, 0x0,
2610 { &hf_mac_lte_rar_header,
2612 "mac-lte.rar.header", FT_STRING, BASE_NONE, NULL, 0x0,
2616 { &hf_mac_lte_rar_extension,
2618 "mac-lte.rar.e", FT_UINT8, BASE_HEX, 0, 0x80,
2619 "Extension - i.e. further RAR headers after this one", HFILL
2622 { &hf_mac_lte_rar_t,
2624 "mac-lte.rar.t", FT_UINT8, BASE_HEX, VALS(rar_type_vals), 0x40,
2625 "Type field indicating whether the payload is RAPID or BI", HFILL
2628 { &hf_mac_lte_rar_bi,
2630 "mac-lte.rar.bi", FT_UINT8, BASE_HEX, VALS(rar_bi_vals), 0x0f,
2631 "Backoff Indicator (ms)", HFILL
2634 { &hf_mac_lte_rar_rapid,
2636 "mac-lte.rar.rapid", FT_UINT8, BASE_HEX_DEC, 0, 0x3f,
2637 "Random Access Preamble IDentifier", HFILL
2640 { &hf_mac_lte_rar_reserved,
2642 "mac-lte.rar.reserved", FT_UINT8, BASE_HEX, 0, 0x30,
2643 "Reserved bits in RAR header - should be 0", HFILL
2647 { &hf_mac_lte_rar_body,
2649 "mac-lte.rar.body", FT_STRING, BASE_NONE, NULL, 0x0,
2653 { &hf_mac_lte_rar_reserved2,
2655 "mac-lte.rar.reserved2", FT_UINT8, BASE_HEX, 0, 0x80,
2656 "Reserved bit in RAR body - should be 0", HFILL
2659 { &hf_mac_lte_rar_ta,
2661 "mac-lte.rar.ta", FT_UINT16, BASE_DEC, 0, 0x7ff0,
2662 "Required adjustment to uplink transmission timing", HFILL
2665 { &hf_mac_lte_rar_ul_grant,
2667 "mac-lte.rar.ul-grant", FT_UINT24, BASE_DEC, 0, 0x0fffff,
2668 "Size of UL Grant", HFILL
2671 { &hf_mac_lte_rar_ul_grant_hopping,
2673 "mac-lte.rar.ul-grant.hopping", FT_UINT8, BASE_DEC, 0, 0x08,
2674 "Size of UL Grant", HFILL
2677 { &hf_mac_lte_rar_ul_grant_fsrba,
2678 { "Fixed sized resource block assignment",
2679 "mac-lte.rar.ul-grant.fsrba", FT_UINT16, BASE_DEC, 0, 0x07fe,
2683 { &hf_mac_lte_rar_ul_grant_tmcs,
2684 { "Truncated Modulation and coding scheme",
2685 "mac-lte.rar.ul-grant.tmcs", FT_UINT16, BASE_DEC, 0, 0x01e0,
2689 { &hf_mac_lte_rar_ul_grant_tcsp,
2690 { "TPC command for scheduled PUSCH",
2691 "mac-lte.rar.ul-grant.tcsp", FT_UINT8, BASE_DEC, 0, 0x01c,
2695 { &hf_mac_lte_rar_ul_grant_ul_delay,
2697 "mac-lte.rar.ul-grant.ul-delay", FT_UINT8, BASE_DEC, 0, 0x02,
2701 { &hf_mac_lte_rar_ul_grant_cqi_request,
2703 "mac-lte.rar.ul-grant.cqi-request", FT_UINT8, BASE_DEC, 0, 0x01,
2707 { &hf_mac_lte_rar_temporary_crnti,
2708 { "Temporary C-RNTI",
2709 "mac-lte.rar.temporary-crnti", FT_UINT16, BASE_DEC, 0, 0x0,
2714 /**********************/
2715 /* Control PDU fields */
2716 { &hf_mac_lte_control_bsr,
2718 "mac-lte.control.bsr", FT_STRING, BASE_NONE, 0, 0x0,
2719 "Buffer Status Report", HFILL
2722 { &hf_mac_lte_control_bsr_lcg_id,
2723 { "Logical Channel Group ID",
2724 "mac-lte.control.bsr.lcg-id", FT_UINT8, BASE_DEC, 0, 0xc0,
2728 { &hf_mac_lte_control_short_bsr_buffer_size,
2730 "mac-lte.control.bsr.buffer-size", FT_UINT8, BASE_DEC, VALS(buffer_size_vals), 0x3f,
2731 "Buffer Size available in all channels in group", HFILL
2734 { &hf_mac_lte_control_long_bsr_buffer_size_0,
2736 "mac-lte.control.bsr.buffer-size-0", FT_UINT8, BASE_DEC, VALS(buffer_size_vals), 0xfc,
2737 "Buffer Size available in logical channel group 0", HFILL
2740 { &hf_mac_lte_control_long_bsr_buffer_size_1,
2742 "mac-lte.control.bsr.buffer-size-1", FT_UINT16, BASE_DEC, VALS(buffer_size_vals), 0x03f0,
2743 "Buffer Size available in logical channel group 1", HFILL
2746 { &hf_mac_lte_control_long_bsr_buffer_size_2,
2748 "mac-lte.control.bsr.buffer-size-2", FT_UINT16, BASE_DEC, VALS(buffer_size_vals), 0x0fc0,
2749 "Buffer Size available in logical channel group 2", HFILL
2752 { &hf_mac_lte_control_long_bsr_buffer_size_3,
2754 "mac-lte.control.bsr.buffer-size-3", FT_UINT8, BASE_DEC, VALS(buffer_size_vals), 0x3f,
2755 "Buffer Size available in logical channel group 3", HFILL
2758 { &hf_mac_lte_control_crnti,
2760 "mac-lte.control.crnti", FT_UINT16, BASE_DEC, 0, 0x0,
2761 "C-RNTI for the UE", HFILL
2764 { &hf_mac_lte_control_timing_advance,
2766 "mac-lte.control.timing-advance", FT_UINT8, BASE_DEC, 0, 0x3f,
2767 "Timing Advance (0-1282 - see 36.213, 4.2.3)", HFILL
2770 { &hf_mac_lte_control_timing_advance_reserved,
2772 "mac-lte.control.timing-advance.reserved", FT_UINT8, BASE_DEC, 0, 0xc0,
2773 "Reserved bits", HFILL
2776 { &hf_mac_lte_control_ue_contention_resolution,
2777 { "UE Contention Resolution",
2778 "mac-lte.control.ue-contention-resolution", FT_STRING, BASE_NONE, 0, 0x0,
2782 { &hf_mac_lte_control_ue_contention_resolution_identity,
2783 { "UE Contention Resolution Identity",
2784 "mac-lte.control.ue-contention-resolution.identity", FT_BYTES, BASE_NONE, 0, 0x0,
2788 { &hf_mac_lte_control_ue_contention_resolution_msg3,
2790 "mac-lte.control.ue-contention-resolution.msg3", FT_FRAMENUM, BASE_NONE, 0, 0x0,
2794 { &hf_mac_lte_control_ue_contention_resolution_msg3_matched,
2795 { "UE Contention Resolution Matches Msg3",
2796 "mac-lte.control.ue-contention-resolution.matches-msg3", FT_BOOLEAN, BASE_NONE, 0, 0x0,
2801 { &hf_mac_lte_control_power_headroom,
2803 "mac-lte.control.power-headroom", FT_STRING, BASE_NONE, 0, 0x0,
2807 { &hf_mac_lte_control_power_headroom_reserved,
2809 "mac-lte.control.power-headroom.reserved", FT_UINT8, BASE_DEC, 0, 0xc0,
2810 "Reserved bits, should be 0", HFILL
2813 { &hf_mac_lte_control_power_headroom_level,
2814 { "Power Headroom Level",
2815 "mac-lte.control.power-headroom.level", FT_UINT8, BASE_DEC, 0, 0x3f,
2820 { &hf_mac_lte_control_padding,
2822 "mac-lte.control.padding", FT_NONE, BASE_NONE, 0, 0x0,
2827 { &hf_mac_lte_suspected_dl_harq_resend,
2828 { "Suspected DL HARQ resend",
2829 "mac-lte.dlsch.suspected-harq-resend", FT_BOOLEAN, BASE_NONE, 0, 0x0,
2833 { &hf_mac_lte_suspected_dl_harq_resend_original_frame,
2834 { "Frame with previous tx",
2835 "mac-lte.dlsch.suspected-harq-resend-original_frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
2840 { &hf_mac_lte_ul_harq_resend_original_frame,
2841 { "Frame with previous tx",
2842 "mac-lte.ulsch.harq-resend-original_frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
2848 static gint *ett[] =
2851 &ett_mac_lte_context,
2852 &ett_mac_lte_rar_headers,
2853 &ett_mac_lte_rar_header,
2854 &ett_mac_lte_rar_body,
2855 &ett_mac_lte_rar_ul_grant,
2856 &ett_mac_lte_ulsch_header,
2857 &ett_mac_lte_dlsch_header,
2858 &ett_mac_lte_sch_subheader,
2862 &ett_mac_lte_contention_resolution,
2863 &ett_mac_lte_power_headroom
2866 module_t *mac_lte_module;
2868 static uat_field_t lcid_drb_mapping_flds[] = {
2869 UAT_FLD_VS(lcid_drb_mappings, lcid, "lcid", drb_lcid_vals, "The MAC LCID"),
2870 UAT_FLD_DEC(lcid_drb_mappings, drbid,"drb id (1-32)", "Identifier of logical data channel"),
2871 UAT_FLD_VS(lcid_drb_mappings, channel_type, "RLC Channel Type", rlc_channel_type_vals, "The MAC LCID"),
2876 /* Register protocol. */
2877 proto_mac_lte = proto_register_protocol("MAC-LTE", "MAC-LTE", "mac-lte");
2878 proto_register_field_array(proto_mac_lte, hf, array_length(hf));
2879 proto_register_subtree_array(ett, array_length(ett));
2881 /* Allow other dissectors to find this one by name. */
2882 register_dissector("mac-lte", dissect_mac_lte, proto_mac_lte);
2884 /* Register the tap name */
2885 mac_lte_tap = register_tap("mac-lte");
2888 mac_lte_module = prefs_register_protocol(proto_mac_lte, NULL);
2890 /* Obsolete preferences */
2891 prefs_register_obsolete_preference(mac_lte_module, "single_rar");
2892 prefs_register_obsolete_preference(mac_lte_module, "check_reserved_bits");
2893 prefs_register_obsolete_preference(mac_lte_module, "decode_rar_ul_grant");
2895 prefs_register_uint_preference(mac_lte_module, "retx_count_warn",
2896 "Number of Re-Transmits before expert warning triggered",
2897 "Number of Re-Transmits before expert warning triggered",
2898 10, &global_mac_lte_retx_counter_trigger);
2900 prefs_register_bool_preference(mac_lte_module, "attempt_rrc_decode",
2901 "Attempt to decode BCH, PCH and CCCH data using LTE RRC dissector",
2902 "Attempt to decode BCH, PCH and CCCH data using LTE RRC dissector",
2903 &global_mac_lte_attempt_rrc_decode);
2905 prefs_register_bool_preference(mac_lte_module, "attempt_to_dissect_crc_failures",
2906 "Dissect frames that have failed CRC check",
2907 "Attempt to dissect frames that have failed CRC check",
2908 &global_mac_lte_dissect_crc_failures);
2910 prefs_register_bool_preference(mac_lte_module, "heuristic_mac_lte_over_udp",
2911 "Try Heuristic LTE-MAC over UDP framing",
2912 "When enabled, use heuristic dissector to find MAC-LTE frames sent with "
2914 &global_mac_lte_heur);
2916 prefs_register_bool_preference(mac_lte_module, "attempt_to_dissect_srb_sdus",
2917 "Attempt to dissect LCID 1&2 as srb1&2",
2918 "Will call LTE RLC dissector with standard settings as per RRC spec",
2919 &global_mac_lte_attempt_srb_decode);
2921 lcid_drb_mappings_uat = uat_new("LCID -> drb Table",
2922 sizeof(lcid_drb_mapping_t),
2925 (void*) &lcid_drb_mappings,
2926 &num_lcid_drb_mappings,
2928 "", /* TODO: is this ref to help manual? */
2929 lcid_drb_mapping_copy_cb,
2932 lcid_drb_mapping_flds );
2934 prefs_register_uat_preference(mac_lte_module,
2936 "LCID -> DRB Mappings Table",
2937 "A table that maps from configurable lcids -> RLC logical channels",
2938 lcid_drb_mappings_uat);
2940 prefs_register_bool_preference(mac_lte_module, "attempt_to_detect_dl_harq_resend",
2941 "Attempt to detect DL HARQ resends",
2942 "Attempt to detect DL HARQ resends (useful if logging UE side so need to infer)",
2943 &global_mac_lte_attempt_dl_harq_resend_detect);
2945 prefs_register_bool_preference(mac_lte_module, "attempt_to_track_ul_harq_resend",
2946 "Attempt to track UL HARQ resends",
2947 "When logging at UE side, will look for original transmission",
2948 &global_mac_lte_attempt_ul_harq_resend_track);
2950 prefs_register_uint_preference(mac_lte_module, "bsr_warn_threshold",
2951 "BSR size when warning should be issued (0 - 63)",
2952 "If any BSR report is >= this number, an expert warning will be added",
2953 10, &global_mac_lte_bsr_warn_threshold);
2955 register_init_routine(&mac_lte_init_protocol);
2959 proto_reg_handoff_mac_lte(void)
2961 static dissector_handle_t mac_lte_handle;
2962 if (!mac_lte_handle) {
2963 mac_lte_handle = find_dissector("mac-lte");
2965 /* Add as a heuristic UDP dissector */
2966 heur_dissector_add("udp", dissect_mac_lte_heur, proto_mac_lte);