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>
33 #include "packet-mac-lte.h"
37 * 3GPP TS 36.321 Evolved Universal Terrestrial Radio Access (E-UTRA)
38 * Medium Access Control (MAC) protocol specification (Release 8)
44 - add a preference so that padding can be verified against an expected pattern?
47 /* Initialize the protocol and registered fields. */
48 int proto_mac_lte = -1;
50 static int mac_lte_tap = -1;
52 /* Decoding context */
53 static int hf_mac_lte_context_radio_type = -1;
54 static int hf_mac_lte_context_direction = -1;
55 static int hf_mac_lte_context_rnti = -1;
56 static int hf_mac_lte_context_rnti_type = -1;
57 static int hf_mac_lte_context_ueid = -1;
58 static int hf_mac_lte_context_subframe_number = -1;
59 static int hf_mac_lte_context_predefined_frame = -1;
60 static int hf_mac_lte_context_length = -1;
61 static int hf_mac_lte_context_bch_transport_channel = -1;
62 static int hf_mac_lte_context_retx_count = -1;
63 static int hf_mac_lte_context_crc_status = -1;
65 /* MAC SCH header fields */
66 static int hf_mac_lte_ulsch_header = -1;
67 static int hf_mac_lte_dlsch_header = -1;
68 static int hf_mac_lte_sch_subheader = -1;
70 static int hf_mac_lte_sch_reserved = -1;
71 static int hf_mac_lte_dlsch_lcid = -1;
72 static int hf_mac_lte_ulsch_lcid = -1;
73 static int hf_mac_lte_sch_extended = -1;
74 static int hf_mac_lte_sch_format = -1;
75 static int hf_mac_lte_sch_length = -1;
77 static int hf_mac_lte_sch_header_only = -1;
80 static int hf_mac_lte_sch_sdu = -1;
81 static int hf_mac_lte_bch_pdu = -1;
82 static int hf_mac_lte_pch_pdu = -1;
83 static int hf_mac_lte_predefined_pdu = -1;
84 static int hf_mac_lte_raw_pdu = -1;
85 static int hf_mac_lte_padding_data = -1;
86 static int hf_mac_lte_padding_length = -1;
90 static int hf_mac_lte_rar = -1;
91 static int hf_mac_lte_rar_headers = -1;
92 static int hf_mac_lte_rar_header = -1;
93 static int hf_mac_lte_rar_extension = -1;
94 static int hf_mac_lte_rar_t = -1;
95 static int hf_mac_lte_rar_bi = -1;
96 static int hf_mac_lte_rar_rapid = -1;
97 static int hf_mac_lte_rar_reserved = -1;
98 static int hf_mac_lte_rar_body = -1;
99 static int hf_mac_lte_rar_reserved2 = -1;
100 static int hf_mac_lte_rar_ta = -1;
101 static int hf_mac_lte_rar_ul_grant = -1;
102 static int hf_mac_lte_rar_ul_grant_hopping = -1;
103 static int hf_mac_lte_rar_ul_grant_fsrba = -1;
104 static int hf_mac_lte_rar_ul_grant_tmcs = -1;
105 static int hf_mac_lte_rar_ul_grant_tcsp = -1;
106 static int hf_mac_lte_rar_ul_grant_ul_delay = -1;
107 static int hf_mac_lte_rar_ul_grant_cqi_request = -1;
108 static int hf_mac_lte_rar_temporary_crnti = -1;
110 /* Common channel control values */
111 static int hf_mac_lte_control_bsr = -1;
112 static int hf_mac_lte_control_bsr_lcg_id = -1;
113 static int hf_mac_lte_control_bsr_buffer_size = -1;
114 static int hf_mac_lte_control_bsr_buffer_size_1 = -1;
115 static int hf_mac_lte_control_bsr_buffer_size_2 = -1;
116 static int hf_mac_lte_control_bsr_buffer_size_3 = -1;
117 static int hf_mac_lte_control_bsr_buffer_size_4 = -1;
118 static int hf_mac_lte_control_crnti = -1;
119 static int hf_mac_lte_control_timing_advance = -1;
120 static int hf_mac_lte_control_timing_advance_reserved = -1;
121 static int hf_mac_lte_control_ue_contention_resolution = -1;
122 static int hf_mac_lte_control_ue_contention_resolution_identity = -1;
123 static int hf_mac_lte_control_ue_contention_resolution_msg3 = -1;
124 static int hf_mac_lte_control_ue_contention_resolution_msg3_matched = -1;
125 static int hf_mac_lte_control_power_headroom = -1;
126 static int hf_mac_lte_control_power_headroom_reserved = -1;
127 static int hf_mac_lte_control_power_headroom_level = -1;
128 static int hf_mac_lte_control_padding = -1;
132 static int ett_mac_lte = -1;
133 static int ett_mac_lte_context = -1;
134 static int ett_mac_lte_ulsch_header = -1;
135 static int ett_mac_lte_dlsch_header = -1;
136 static int ett_mac_lte_sch_subheader = -1;
137 static int ett_mac_lte_rar_headers = -1;
138 static int ett_mac_lte_rar_header = -1;
139 static int ett_mac_lte_rar_body = -1;
140 static int ett_mac_lte_rar_ul_grant = -1;
141 static int ett_mac_lte_bsr = -1;
142 static int ett_mac_lte_bch = -1;
143 static int ett_mac_lte_pch = -1;
144 static int ett_mac_lte_contention_resolution = -1;
145 static int ett_mac_lte_power_headroom = -1;
149 /* Constants and value strings */
151 static const value_string radio_type_vals[] =
159 static const value_string direction_vals[] =
161 { DIRECTION_UPLINK, "Uplink"},
162 { DIRECTION_DOWNLINK, "Downlink"},
167 static const value_string rnti_type_vals[] =
169 { NO_RNTI, "NO-RNTI"},
171 { RA_RNTI, "RA-RNTI"},
173 { SI_RNTI, "SI-RNTI"},
177 static const value_string bch_transport_channel_vals[] =
179 { SI_RNTI, "DL-SCH"},
184 static const value_string crc_status_vals[] =
186 { 0, "CRC Status Failed"},
187 { 1, "CRC Status OK"},
193 #define UE_CONTENTION_RESOLUTION_IDENTITY_LCID 0x1c
194 #define TIMING_ADVANCE_LCID 0x1d
195 #define DRX_COMMAND_LCID 0x1e
196 #define PADDING_LCID 0x1f
198 static const value_string dlsch_lcid_vals[] =
211 { UE_CONTENTION_RESOLUTION_IDENTITY_LCID, "UE Contention Resolution Identity"},
212 { TIMING_ADVANCE_LCID , "Timing Advance"},
213 { DRX_COMMAND_LCID , "DRX Command"},
214 { PADDING_LCID , "Padding" },
218 #define POWER_HEADROOM_REPORT_LCID 0x1a
219 #define CRNTI_LCID 0x1b
220 #define TRUNCATED_BSR_LCID 0x1c
221 #define SHORT_BSR_LCID 0x1d
222 #define LONG_BSR_LCID 0x1e
224 static const value_string ulsch_lcid_vals[] =
237 { POWER_HEADROOM_REPORT_LCID, "Power Headroom Report"},
238 { CRNTI_LCID, "C-RNTI"},
239 { TRUNCATED_BSR_LCID, "Truncated BSR"},
240 { SHORT_BSR_LCID, "Short BSR"},
241 { LONG_BSR_LCID, "Long BSR"},
242 { PADDING_LCID, "Padding" },
247 static const value_string format_vals[] =
249 { 0, "Data length is < 128 bytes"},
250 { 1, "Data length is >= 128 bytes"},
255 static const value_string rar_type_vals[] =
257 { 0, "Backoff Indicator present"},
258 { 1, "RAPID present"},
263 static const value_string rar_bi_vals[] =
282 static const value_string buffer_size_vals[] =
285 { 1, "0 < BS <= 10"},
286 { 2, "10 < BS <= 12"},
287 { 3, "12 < BS <= 14"},
288 { 4, "14 < BS <= 17"},
289 { 5, "17 < BS <= 19"},
290 { 6, "19 < BS <= 22"},
291 { 7, "22 < BS <= 26"},
292 { 8, "26 < BS <= 31"},
293 { 9, "31 < BS <= 36"},
294 { 10, "36 < BS <= 42"},
295 { 11, "42 < BS <= 49"},
296 { 12, "49 < BS <= 57"},
297 { 13, "47 < BS <= 67"},
298 { 14, "67 < BS <= 78"},
299 { 15, "78 < BS <= 91"},
300 { 16, "91 < BS <= 107"},
301 { 17, "107 < BS <= 125"},
302 { 18, "125 < BS <= 146"},
303 { 19, "146 < BS <= 171"},
304 { 20, "171 < BS <= 200"},
305 { 21, "200 < BS <= 234"},
306 { 22, "234 < BS <= 274"},
307 { 23, "274 < BS <= 321"},
308 { 24, "321 < BS <= 376"},
309 { 25, "376 < BS <= 440"},
310 { 26, "440 < BS <= 515"},
311 { 27, "515 < BS <= 603"},
312 { 28, "603 < BS <= 706"},
313 { 29, "706 < BS <= 826"},
314 { 30, "826 < BS <= 967"},
315 { 31, "967 < BS <= 1132"},
316 { 32, "1132 < BS <= 1326"},
317 { 33, "1326 < BS <= 1552"},
318 { 34, "1552 < BS <= 1817"},
319 { 35, "1817 < BS <= 2127"},
320 { 36, "2127 < BS <= 2490"},
321 { 37, "2490 < BS <= 2915"},
322 { 38, "2915 < BS <= 3413"},
323 { 39, "3413 < BS <= 3995"},
324 { 40, "3995 < BS <= 4677"},
325 { 41, "4677 < BS <= 5476"},
326 { 42, "5476 < BS <= 6411"},
327 { 43, "6411 < BS <= 7505"},
328 { 44, "7505 < BS <= 8787"},
329 { 45, "8787 < BS <= 10276"},
330 { 46, "10287 < BS <= 12043"},
331 { 47, "12043 < BS <= 14099"},
332 { 48, "14099 < BS <= 16507"},
333 { 49, "16507 < BS <= 19325"},
334 { 50, "19325 < BS <= 22624"},
335 { 51, "22624 < BS <= 26487"},
336 { 52, "26487 < BS <= 31009"},
337 { 53, "31009 < BS <= 36304"},
338 { 54, "36304 < BS <= 42502"},
339 { 55, "42502 < BS <= 49759"},
340 { 56, "49759 < BS <= 58255"},
341 { 57, "58255 < BS <= 68201"},
342 { 58, "68201 < BS <= 79846"},
343 { 59, "79846 < BS <= 93479"},
344 { 60, "93479 < BS <= 109439"},
345 { 61, "109439 < BS <= 128125"},
346 { 62, "128125 < BS <= 150000"},
347 { 63, "BS > 150000"},
351 static const value_string header_only_vals[] =
353 { 0, "MAC PDU Headers and body present"},
354 { 1, "MAC PDU Headers only"},
358 static const value_string predefined_frame_vals[] =
360 { 0, "Real MAC PDU present - will dissect"},
361 { 1, "Predefined frame present - will not dissect"},
366 /* By default check and warn about reserved bits not being zero.
367 December '08 spec says they should be ignored... */
368 static gboolean global_mac_lte_check_reserved_bits = TRUE;
370 /* If this PDU has been NACK'd (by HARQ) more than a certain number of times,
371 we trigger an expert warning. */
372 static gint global_mac_lte_retx_counter_trigger = 3;
374 /* By default try to decode transparent data (BCH, PCH and CCCH) data using LTE RRC dissector */
375 static gboolean global_mac_lte_attempt_rrc_decode = TRUE;
377 /* Control whether decoding details of RAR UL grant or not */
378 static gboolean global_mac_lte_decode_rar_ul_grant = TRUE;
380 /* Whether should attempt to dissect frames failing CRC check */
381 static gboolean global_mac_lte_dissect_crc_failures = FALSE;
385 /***************************************************************/
386 /* Keeping track of Msg3 bodies so they can be compared with */
387 /* Contention Resolution bodies. */
389 typedef struct Msg3Data {
395 /* This table stores (RNTI -> Msg3Data*). Will be populated when
396 Msg3 frames are first read. */
397 static GHashTable *mac_lte_msg3_hash = NULL;
399 /* Hash table functions for mac_lte_msg3_hash. Hash is just the (RNTI) key */
400 static gint mac_lte_msg3_hash_equal(gconstpointer v, gconstpointer v2)
405 static guint mac_lte_msg3_hash_func(gconstpointer v)
407 return GPOINTER_TO_UINT(v);
413 typedef enum ContentionResolutionStatus {
417 } ContentionResolutionStatus;
419 typedef struct ContentionResolutionResult {
420 ContentionResolutionStatus status;
422 } ContentionResolutionResult;
425 /* This table stores (CRFrameNum -> CRResult). It is assigned during the first
426 pass and used thereafter */
427 static GHashTable *mac_lte_cr_result_hash = NULL;
429 /* Hash table functions for mac_lte_cr_result_hash. Hash is just the (framenum) key */
430 static gint mac_lte_cr_result_hash_equal(gconstpointer v, gconstpointer v2)
435 static guint mac_lte_cr_result_hash_func(gconstpointer v)
437 return GPOINTER_TO_UINT(v);
442 /**************************************************************************/
446 /* Forward declarations */
447 void proto_reg_handoff_mac_lte(void);
448 void dissect_mac_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
451 /* Heuristic dissection */
452 static gboolean global_mac_lte_heur = FALSE;
454 static gboolean dissect_mac_lte_heur(tvbuff_t *tvb, packet_info *pinfo,
458 struct mac_lte_info *p_mac_lte_info;
461 gboolean infoAlreadySet = FALSE;
463 /* This is a heuristic dissector, which means we get all the UDP
464 * traffic not sent to a known dissector and not claimed by
465 * a heuristic dissector called before us!
468 if (!global_mac_lte_heur) {
472 /* If redissecting, use previous info struct (if available) */
473 p_mac_lte_info = p_get_proto_data(pinfo->fd, proto_mac_lte);
474 if (p_mac_lte_info == NULL) {
475 /* Allocate new info struct for this frame */
476 p_mac_lte_info = se_alloc0(sizeof(struct mac_lte_info));
477 if (p_mac_lte_info == NULL) {
480 infoAlreadySet = FALSE;
483 infoAlreadySet = TRUE;
486 /* Do this again on re-dissection to re-discover offset of actual PDU */
488 /* Needs to be at least as long as:
489 - the signature string
492 - at least one byte of MAC PDU payload */
493 if ((size_t)tvb_length_remaining(tvb, offset) < (strlen(MAC_LTE_START_STRING)+3+2)) {
497 /* OK, compare with signature string */
498 if (tvb_strneql(tvb, offset, MAC_LTE_START_STRING, (gint)strlen(MAC_LTE_START_STRING)) != 0) {
501 offset += (gint)strlen(MAC_LTE_START_STRING);
503 /* Read fixed fields */
504 p_mac_lte_info->radioType = tvb_get_guint8(tvb, offset++);
505 p_mac_lte_info->direction = tvb_get_guint8(tvb, offset++);
506 p_mac_lte_info->rntiType = tvb_get_guint8(tvb, offset++);
508 /* Read optional fields */
509 while (tag != MAC_LTE_PAYLOAD_TAG) {
510 /* Process next tag */
511 tag = tvb_get_guint8(tvb, offset++);
513 case MAC_LTE_RNTI_TAG:
514 p_mac_lte_info->rnti = tvb_get_ntohs(tvb, offset);
517 case MAC_LTE_UEID_TAG:
518 p_mac_lte_info->ueid = tvb_get_ntohs(tvb, offset);
521 case MAC_LTE_SUBFRAME_TAG:
522 p_mac_lte_info->subframeNumber = tvb_get_ntohs(tvb, offset);
525 case MAC_LTE_PREDFINED_DATA_TAG:
526 p_mac_lte_info->isPredefinedData = tvb_get_guint8(tvb, offset);
529 case MAC_LTE_RETX_TAG:
530 p_mac_lte_info->reTxCount = tvb_get_guint8(tvb, offset);
533 case MAC_LTE_CRC_STATUS_TAG:
534 p_mac_lte_info->crcStatusValid = TRUE;
535 p_mac_lte_info->crcStatus = tvb_get_guint8(tvb, offset);
539 case MAC_LTE_PAYLOAD_TAG:
540 /* Have reached data, so set payload length and get out of loop */
541 p_mac_lte_info->length= tvb_length_remaining(tvb, offset);
545 /* It must be a recognised tag */
549 if (!infoAlreadySet) {
550 /* Store info in packet */
551 p_add_proto_data(pinfo->fd, proto_mac_lte, p_mac_lte_info);
556 /**************************************/
557 /* OK, now dissect as MAC LTE */
559 /* Create tvb that starts at actual MAC PDU */
560 mac_tvb = tvb_new_subset(tvb, offset, -1, tvb_reported_length(tvb)-offset);
561 dissect_mac_lte(mac_tvb, pinfo, tree);
565 /* Dissect a single Random Access Reponse body */
566 static gint dissect_rar_entry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
567 gint offset, guint8 rapid)
570 guint start_body_offset = offset;
572 proto_item *rar_body_ti;
573 proto_tree *rar_body_tree;
574 proto_item *ul_grant_ti;
575 guint16 timing_advance;
579 /* Create tree for this Body */
580 rar_body_ti = proto_tree_add_item(tree,
582 tvb, offset, 0, FALSE);
583 rar_body_tree = proto_item_add_subtree(rar_body_ti, ett_mac_lte_rar_body);
585 /* Dissect an RAR entry */
587 /* Check reserved bit */
588 reserved = (tvb_get_guint8(tvb, offset) & 0x80) >> 7;
589 ti = proto_tree_add_item(rar_body_tree, hf_mac_lte_rar_reserved2, tvb, offset, 1, FALSE);
590 if (global_mac_lte_check_reserved_bits && (reserved != 0)) {
591 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
592 "RAR body Reserved bit not zero (found 0x%x)", reserved);
596 timing_advance = (tvb_get_ntohs(tvb, offset) & 0x7ff0) >> 4;
597 proto_tree_add_item(rar_body_tree, hf_mac_lte_rar_ta, tvb, offset, 2, FALSE);
601 ul_grant = (tvb_get_ntohl(tvb, offset) & 0x0fffff00) >> 8;
602 ul_grant_ti = proto_tree_add_item(rar_body_tree, hf_mac_lte_rar_ul_grant, tvb, offset, 3, FALSE);
604 /* Break these 20 bits down as described in 36.213, section 6.2 */
605 if (global_mac_lte_decode_rar_ul_grant) {
606 /* Create subtree for UL grant break-down */
607 proto_tree *ul_grant_tree = proto_item_add_subtree(ul_grant_ti, ett_mac_lte_rar_ul_grant);
609 /* Hopping flag (1 bit) */
610 proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_hopping,
611 tvb, offset, 1, FALSE);
613 /* Fixed sized resource block assignment (10 bits) */
614 proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_fsrba,
615 tvb, offset, 2, FALSE);
617 /* Truncated Modulation and coding scheme (4 bits) */
618 proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_tmcs,
619 tvb, offset+1, 2, FALSE);
621 /* TPC command for scheduled PUSCH (3 bits) */
622 proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_tcsp,
623 tvb, offset+2, 1, FALSE);
625 /* UL delay (1 bit) */
626 proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_ul_delay,
627 tvb, offset+2, 1, FALSE);
629 /* CQI request (1 bit) */
630 proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_cqi_request,
631 tvb, offset+2, 1, FALSE);
636 /* Temporary C-RNTI */
637 temp_crnti = tvb_get_ntohs(tvb, offset);
638 proto_tree_add_item(rar_body_tree, hf_mac_lte_rar_temporary_crnti, tvb, offset, 2, FALSE);
641 proto_item_append_text(rar_body_ti, " RAPID=%u (TA=%u, UL-Grant=%u, Temp C-RNTI=%u)",
642 rapid, timing_advance, ul_grant, temp_crnti);
644 col_append_fstr(pinfo->cinfo, COL_INFO, "(RAPID=%u: TA=%u, UL-Grant=%u, Temp C-RNTI=%u) ",
645 rapid, timing_advance, ul_grant, temp_crnti);
647 proto_item_set_len(rar_body_ti, offset-start_body_offset);
653 /* Dissect Random Access Reponse (RAR) PDU */
654 static void dissect_rar(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
655 gint offset, mac_lte_info *p_mac_lte_info, mac_lte_tap_info *tap_info)
657 gint number_of_rars = 0; /* No of RAR bodies expected following headers */
659 gboolean backoff_indicator_seen = FALSE;
660 guint8 backoff_indicator = 0;
663 proto_tree *rar_headers_tree;
665 proto_item *rar_headers_ti;
666 int start_headers_offset = offset;
668 col_append_fstr(pinfo->cinfo, COL_INFO, "RAR (RA-RNTI=%u, SF=%u) ",
669 p_mac_lte_info->rnti, p_mac_lte_info->subframeNumber);
671 /* Create hidden 'virtual root' so can filter on mac-lte.rar */
672 ti = proto_tree_add_item(tree, hf_mac_lte_rar, tvb, offset, -1, FALSE);
673 PROTO_ITEM_SET_HIDDEN(ti);
675 /* Create headers tree */
676 rar_headers_ti = proto_tree_add_item(tree,
677 hf_mac_lte_rar_headers,
678 tvb, offset, 0, FALSE);
679 rar_headers_tree = proto_item_add_subtree(rar_headers_ti, ett_mac_lte_rar_headers);
682 /***************************/
683 /* Read the header entries */
685 int start_header_offset = offset;
686 proto_tree *rar_header_tree;
687 proto_item *rar_header_ti;
689 guint8 first_byte = tvb_get_guint8(tvb, offset);
691 /* Create tree for this header */
692 rar_header_ti = proto_tree_add_item(rar_headers_tree,
693 hf_mac_lte_rar_header,
694 tvb, offset, 0, FALSE);
695 rar_header_tree = proto_item_add_subtree(rar_header_ti, ett_mac_lte_rar_header);
698 extension = (first_byte & 0x80) >> 7;
699 proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_extension, tvb, offset, 1, FALSE);
702 type_value = (first_byte & 0x40) >> 6;
703 proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_t, tvb, offset, 1, FALSE);
705 if (type_value == 0) {
706 /* Backoff Indicator (BI) case */
712 /* 2 Reserved bits */
713 reserved = (tvb_get_guint8(tvb, offset) & 0x30) >> 4;
714 ti = proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_reserved, tvb, offset, 1, FALSE);
715 if (global_mac_lte_check_reserved_bits && (reserved != 0)) {
716 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
717 "RAR header Reserved bits not zero (found 0x%x)", reserved);
720 /* Backoff Indicator */
721 backoff_indicator = tvb_get_guint8(tvb, offset) & 0x0f;
722 bi_ti = proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_bi, tvb, offset, 1, FALSE);
724 /* As of March 2009 spec, it must be first, and may only appear once */
725 if (backoff_indicator_seen) {
726 expert_add_info_format(pinfo, bi_ti, PI_MALFORMED, PI_ERROR,
727 "MAC RAR PDU has > 1 Backoff Indicator subheader present");
729 backoff_indicator_seen = TRUE;
731 proto_item_append_text(rar_header_ti, "(Backoff Indicator=%sms)",
732 val_to_str(backoff_indicator, rar_bi_vals, "Illegal-value "));
734 col_append_fstr(pinfo->cinfo, COL_INFO, "(Backoff Indicator=%s ms) ",
735 val_to_str(backoff_indicator, rar_bi_vals, "Illegal-value"));
737 /* If present, it must be the first subheader */
738 if (number_of_rars > 0) {
739 expert_add_info_format(pinfo, bi_ti, PI_MALFORMED, PI_WARN,
740 "Backoff Indicator must appear as first subheader");
746 /* TODO: complain if the same RAPID appears twice in same frame? */
747 rapids[number_of_rars] = tvb_get_guint8(tvb, offset) & 0x3f;
748 proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_rapid, tvb, offset, 1, FALSE);
750 proto_item_append_text(rar_header_ti, "(RAPID=%u)", rapids[number_of_rars]);
757 /* Finalise length of header tree selection */
758 proto_item_set_len(rar_header_ti, offset - start_header_offset);
762 /* Append summary to headers root */
763 proto_item_append_text(rar_headers_ti, " (%u RARs", number_of_rars);
764 if (backoff_indicator_seen) {
765 proto_item_append_text(rar_headers_ti, ", BI=%sms)",
766 val_to_str(backoff_indicator, rar_bi_vals, "Illegal-value "));
769 proto_item_append_text(rar_headers_ti, ")");
772 /* Set length for headers root */
773 proto_item_set_len(rar_headers_ti, offset-start_headers_offset);
776 /***************************/
777 /* Read any indicated RARs */
778 for (n=0; n < number_of_rars; n++) {
779 offset = dissect_rar_entry(tvb, pinfo, tree, offset, rapids[n]);
782 /* Update TAP info */
783 tap_info->number_of_rars += number_of_rars;
785 /* Warn if we don't seem to have reached the end of the frame yet */
786 if (tvb_length_remaining(tvb, offset) != 0) {
787 expert_add_info_format(pinfo, rar_headers_ti, PI_MALFORMED, PI_ERROR,
788 "%u bytes remaining after RAR PDU dissected",
789 tvb_length_remaining(tvb, offset));
794 /* Dissect BCH PDU */
795 static void dissect_bch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
796 int offset, mac_lte_info *p_mac_lte_info)
800 col_append_fstr(pinfo->cinfo, COL_INFO, "BCH PDU (%u bytes, on %s transport) ",
801 tvb_length_remaining(tvb, offset),
802 val_to_str(p_mac_lte_info->rntiType,
803 bch_transport_channel_vals,
806 /* Show which transport layer it came in on (inferred from RNTI type) */
807 ti = proto_tree_add_uint(tree, hf_mac_lte_context_bch_transport_channel,
808 tvb, offset, 0, p_mac_lte_info->rntiType);
809 PROTO_ITEM_SET_GENERATED(ti);
811 /****************************************/
812 /* Whole frame is BCH data */
815 ti = proto_tree_add_item(tree, hf_mac_lte_bch_pdu,
816 tvb, offset, -1, FALSE);
818 if (global_mac_lte_attempt_rrc_decode) {
819 /* Attempt to decode payload using LTE RRC dissector */
820 tvbuff_t *rrc_tvb = tvb_new_subset(tvb, offset, -1, tvb_length_remaining(tvb, offset));
822 /* Get appropriate dissector handle */
823 dissector_handle_t protocol_handle = 0;
824 if (p_mac_lte_info->rntiType == SI_RNTI) {
825 protocol_handle = find_dissector("lte-rrc.bcch.dl.sch");
828 protocol_handle = find_dissector("lte-rrc.bcch.bch");
831 /* Hide raw view of bytes */
832 PROTO_ITEM_SET_HIDDEN(ti);
834 /* Call it (catch exceptions so that stats will be updated) */
835 /* TODO: couldn't avoid warnings for 'ti' by using volatile
838 call_dissector_only(protocol_handle, rrc_tvb, pinfo, tree);
845 /* Check that this *is* downlink! */
846 if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
847 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
848 "BCH data should not be received in Uplink!");
853 /* Dissect PCH PDU */
854 static void dissect_pch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
855 int offset, guint8 direction)
859 col_append_fstr(pinfo->cinfo, COL_INFO, "PCH PDU (%u bytes) ",
860 tvb_length_remaining(tvb, offset));
862 /****************************************/
863 /* Whole frame is PCH data */
865 /* Always show as raw data */
866 ti = proto_tree_add_item(tree, hf_mac_lte_pch_pdu,
867 tvb, offset, -1, FALSE);
869 if (global_mac_lte_attempt_rrc_decode) {
871 /* Attempt to decode payload using LTE RRC dissector */
872 tvbuff_t *rrc_tvb = tvb_new_subset(tvb, offset, -1, tvb_length_remaining(tvb, offset));
874 /* Get appropriate dissector handle */
875 dissector_handle_t protocol_handle = find_dissector("lte-rrc.pcch");
877 /* Hide raw view of bytes */
878 PROTO_ITEM_SET_HIDDEN(ti);
880 /* Call it (catch exceptions so that stats will be updated) */
882 call_dissector_only(protocol_handle, rrc_tvb, pinfo, tree);
889 /* Check that this *is* downlink! */
890 if (direction == DIRECTION_UPLINK) {
891 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
892 "PCH data should not be received in Uplink!");
897 /* Does this header entry correspond to a fixed-sized control element? */
898 static int is_fixed_sized_control_element(guint8 lcid, guint8 direction)
900 if (direction == DIRECTION_UPLINK) {
903 case POWER_HEADROOM_REPORT_LCID:
905 case TRUNCATED_BSR_LCID:
915 /* Assume Downlink */
917 case UE_CONTENTION_RESOLUTION_IDENTITY_LCID:
918 case TIMING_ADVANCE_LCID:
919 case DRX_COMMAND_LCID:
929 /* Is this a BSR report header? */
930 static int is_bsr_lcid(guint8 lcid)
932 return ((lcid == TRUNCATED_BSR_LCID) ||
933 (lcid == SHORT_BSR_LCID) ||
934 (lcid == LONG_BSR_LCID));
938 #define MAX_HEADERS_IN_PDU 1024
940 /* UL-SCH and DL-SCH formats have much in common, so handle them in a common
942 static void dissect_ulsch_or_dlsch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
943 volatile int offset, guint8 direction,
944 mac_lte_info *p_mac_lte_info, mac_lte_tap_info *tap_info)
948 proto_item *truncated_ti;
949 proto_item *padding_length_ti;
951 /* Keep track of LCIDs and lengths as we dissect the header */
952 volatile guint8 number_of_headers = 0;
953 guint8 lcids[MAX_HEADERS_IN_PDU];
954 gint16 pdu_lengths[MAX_HEADERS_IN_PDU];
956 proto_item *pdu_header_ti;
957 proto_tree *pdu_header_tree;
959 gboolean have_seen_data_header = FALSE;
960 gboolean have_seen_bsr = FALSE;
961 gboolean expecting_body_data = FALSE;
963 col_append_fstr(pinfo->cinfo, COL_INFO, "%s: (SF=%u) ",
964 (direction == DIRECTION_UPLINK) ? "UL-SCH" : "DL-SCH",
965 p_mac_lte_info->subframeNumber);
967 /* Add PDU block header subtree */
968 pdu_header_ti = proto_tree_add_string_format(tree,
969 (direction == DIRECTION_UPLINK) ?
970 hf_mac_lte_ulsch_header :
971 hf_mac_lte_dlsch_header,
975 pdu_header_tree = proto_item_add_subtree(pdu_header_ti,
976 (direction == DIRECTION_UPLINK) ?
977 ett_mac_lte_ulsch_header :
978 ett_mac_lte_dlsch_header);
981 /************************************************************************/
982 /* Dissect each sub-header. */
986 proto_item *pdu_subheader_ti;
987 proto_tree *pdu_subheader_tree;
990 gint offset_start_subheader = offset;
991 guint8 first_byte = tvb_get_guint8(tvb, offset);
993 /* Add PDU block header subtree */
994 pdu_subheader_ti = proto_tree_add_string_format(pdu_header_tree,
995 hf_mac_lte_sch_subheader,
999 pdu_subheader_tree = proto_item_add_subtree(pdu_subheader_ti,
1000 ett_mac_lte_sch_subheader);
1002 /* Check 1st 2 reserved bits */
1003 reserved = (first_byte & 0xc0) >> 6;
1004 ti = proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_sch_reserved,
1005 tvb, offset, 1, FALSE);
1006 if (global_mac_lte_check_reserved_bits && (reserved != 0)) {
1007 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
1008 "U/DL-SCH header Reserved bits not zero");
1012 extension = (first_byte & 0x20) >> 5;
1013 proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_sch_extended,
1014 tvb, offset, 1, FALSE);
1016 /* LCID. Has different meaning depending upon direction. */
1017 lcids[number_of_headers] = first_byte & 0x1f;
1018 if (direction == DIRECTION_UPLINK) {
1019 lcid_ti = proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_ulsch_lcid,
1020 tvb, offset, 1, FALSE);
1021 col_append_fstr(pinfo->cinfo, COL_INFO, "(%s",
1022 val_to_str(lcids[number_of_headers],
1023 ulsch_lcid_vals, "(Unknown LCID)"));
1026 lcid_ti = proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_dlsch_lcid,
1027 tvb, offset, 1, FALSE);
1028 col_append_fstr(pinfo->cinfo, COL_INFO, "(%s",
1029 val_to_str(lcids[number_of_headers],
1030 dlsch_lcid_vals, "(Unknown LCID)"));
1034 /* Remember if we've seen a data subheader */
1035 if (lcids[number_of_headers] <= 10) {
1036 have_seen_data_header = TRUE;
1037 expecting_body_data = TRUE;
1040 /* Show an expert item if a contol subheader (except Padding) appears
1041 *after* a data PDU */
1042 if (have_seen_data_header &&
1043 (lcids[number_of_headers] > 10) && (lcids[number_of_headers] != PADDING_LCID)) {
1044 expert_add_info_format(pinfo, lcid_ti, PI_MALFORMED, PI_ERROR,
1045 "Control subheaders should not appear after data subheaders");
1048 /* Show an expert item if we're seeing more then one BSR in a frame */
1049 if ((direction == DIRECTION_UPLINK) && is_bsr_lcid(lcids[number_of_headers])) {
1050 if (have_seen_bsr) {
1051 expert_add_info_format(pinfo, lcid_ti, PI_MALFORMED, PI_ERROR,
1052 "There shouldn't be > 1 BSR in a frame");
1054 have_seen_bsr = TRUE;
1058 /********************************************************************/
1059 /* Length field follows if not the last header or for a fixed-sized
1062 if (is_fixed_sized_control_element(lcids[number_of_headers], direction)) {
1063 pdu_lengths[number_of_headers] = 0;
1066 pdu_lengths[number_of_headers] = -1;
1070 if (!is_fixed_sized_control_element(lcids[number_of_headers], direction) &&
1071 (lcids[number_of_headers] != PADDING_LCID)) {
1075 /* F(ormat) bit tells us how long the length field is */
1076 format = (tvb_get_guint8(tvb, offset) & 0x80) >> 7;
1077 proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_sch_format,
1078 tvb, offset, 1, FALSE);
1080 /* Now read length field itself */
1082 /* >= 128 - use 15 bits */
1083 proto_tree_add_bits_ret_val(pdu_subheader_tree, hf_mac_lte_sch_length,
1084 tvb, offset*8 + 1, 15, &length, FALSE);
1089 /* Less than 128 - only 7 bits */
1090 proto_tree_add_bits_ret_val(pdu_subheader_tree, hf_mac_lte_sch_length,
1091 tvb, offset*8 + 1, 7, &length, FALSE);
1094 pdu_lengths[number_of_headers] = (gint16)length;
1097 pdu_lengths[number_of_headers] = 0;
1102 /* Close off description in info column */
1103 switch (pdu_lengths[number_of_headers]) {
1105 col_append_str(pinfo->cinfo, COL_INFO, ") ");
1108 col_append_str(pinfo->cinfo, COL_INFO, ":remainder) ");
1111 col_append_fstr(pinfo->cinfo, COL_INFO, ":%u bytes) ",
1112 pdu_lengths[number_of_headers]);
1116 /* Append summary to subheader root */
1117 proto_item_append_text(pdu_subheader_ti, " (lcid=%s",
1118 val_to_str(lcids[number_of_headers],
1119 (direction == DIRECTION_UPLINK) ?
1124 switch (pdu_lengths[number_of_headers]) {
1126 proto_item_append_text(pdu_subheader_ti, ", length is remainder)");
1129 proto_item_append_text(pdu_subheader_ti, ")");
1132 proto_item_append_text(pdu_subheader_ti, ", length=%u)",
1133 pdu_lengths[number_of_headers]);
1138 /* Flag unknown lcid values in expert info */
1139 if (strncmp(val_to_str(lcids[number_of_headers],
1140 (direction == DIRECTION_UPLINK) ? ulsch_lcid_vals : dlsch_lcid_vals,
1143 sizeof("Unknown")) == 0) {
1144 expert_add_info_format(pinfo, pdu_subheader_ti, PI_MALFORMED, PI_ERROR,
1145 "Unexpected LCID received (%u)", lcids[number_of_headers]);
1148 /* Set length of this subheader */
1149 proto_item_set_len(pdu_subheader_ti, offset- offset_start_subheader);
1151 number_of_headers++;
1152 } while (extension);
1154 /* Append summary to overall PDU header root */
1155 proto_item_append_text(pdu_header_ti, " (%u subheaders)",
1158 /* And set its length to offset */
1159 proto_item_set_len(pdu_header_ti, offset);
1162 /* TODO: some valid PDUs don't have any bodies, so don't want expert info.
1163 Use expecting_body_data to track this */
1165 /* There might not be any data, if only headers were logged */
1166 truncated_ti = proto_tree_add_uint(tree, hf_mac_lte_sch_header_only, tvb, 0, 0,
1167 tvb_length_remaining(tvb, offset) == 0);
1168 if (tvb_length_remaining(tvb, offset) == 0) {
1169 PROTO_ITEM_SET_GENERATED(truncated_ti);
1170 expert_add_info_format(pinfo, truncated_ti, PI_SEQUENCE, PI_NOTE,
1171 "MAC PDU SDUs have been ommitted");
1175 PROTO_ITEM_SET_HIDDEN(truncated_ti);
1179 /************************************************************************/
1180 /* Dissect SDUs / control elements / padding. */
1181 /************************************************************************/
1183 for (n=0; n < number_of_headers; n++) {
1185 /* Data SDUs treated identically for Uplink or downlink channels */
1186 if (lcids[n] <= 10) {
1188 volatile guint16 data_length = (pdu_lengths[n] == -1) ?
1189 tvb_length_remaining(tvb, offset) :
1193 sdu_ti = proto_tree_add_bytes_format(tree, hf_mac_lte_sch_sdu, tvb, offset, pdu_lengths[n],
1194 tvb_get_ptr(tvb, offset, pdu_lengths[n]),
1195 "SDU (%s, length=%u bytes)",
1196 val_to_str(lcids[n],
1197 (direction == DIRECTION_UPLINK) ?
1203 /* Look for Msg3 data so that it may be compared with later
1204 Contention Resolution body */
1205 if ((lcids[n] == 0) && (direction == DIRECTION_UPLINK) && (data_length == 6)) {
1206 if (!pinfo->fd->flags.visited) {
1207 guint key = p_mac_lte_info->rnti;
1208 Msg3Data *data = g_hash_table_lookup(mac_lte_msg3_hash, GUINT_TO_POINTER(key));
1210 /* Look for previous entry for this UE */
1212 /* Allocate space for data and add to table */
1213 data = se_alloc(sizeof(Msg3Data));
1214 g_hash_table_insert(mac_lte_msg3_hash, GUINT_TO_POINTER(key), data);
1217 /* Fill in data details */
1218 data->framenum = pinfo->fd->num;
1219 memcpy(&data->data, tvb_get_ptr(tvb, offset, data_length), data_length);
1223 /* CCCH frames can be dissected directly by LTE RRC... */
1224 if ((lcids[n] == 0) && global_mac_lte_attempt_rrc_decode) {
1225 tvbuff_t *rrc_tvb = tvb_new_subset(tvb, offset, data_length, data_length);
1227 /* Get appropriate dissector handle */
1228 volatile dissector_handle_t protocol_handle = 0;
1229 if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
1230 protocol_handle = find_dissector("lte-rrc.ul.ccch");
1233 protocol_handle = find_dissector("lte-rrc.dl.ccch");
1236 /* Hide raw view of bytes */
1237 PROTO_ITEM_SET_HIDDEN(sdu_ti);
1239 /* Call it (catch exceptions so that stats will be updated) */
1241 call_dissector_only(protocol_handle, rrc_tvb, pinfo, tree);
1248 offset += data_length;
1250 /* Update tap byte count for this channel */
1251 tap_info->bytes_for_lcid[lcids[n]] += data_length;
1252 tap_info->sdus_for_lcid[lcids[n]]++;
1255 /* See if its a control PDU type */
1256 if (direction == DIRECTION_DOWNLINK) {
1258 /****************************/
1259 /* DL-SCH Control PDUs */
1261 case UE_CONTENTION_RESOLUTION_IDENTITY_LCID:
1264 proto_tree *cr_tree;
1266 ContentionResolutionResult *crResult;
1268 /* Create CR root */
1269 cr_ti = proto_tree_add_string_format(tree,
1270 hf_mac_lte_control_ue_contention_resolution,
1273 "Contention Resolution");
1274 cr_tree = proto_item_add_subtree(cr_ti, ett_mac_lte_contention_resolution);
1277 proto_tree_add_item(cr_tree, hf_mac_lte_control_ue_contention_resolution_identity,
1278 tvb, offset, 6, FALSE);
1280 /* Get pointer to result struct for this frame */
1281 crResult = g_hash_table_lookup(mac_lte_cr_result_hash, GUINT_TO_POINTER(pinfo->fd->num));
1282 if (crResult == NULL) {
1284 /* Need to set result by looking for and comparing with Msg3 */
1286 guint msg3Key = p_mac_lte_info->rnti;
1288 /* Allocate result and add it to the table */
1289 crResult = se_alloc(sizeof(ContentionResolutionResult));
1290 g_hash_table_insert(mac_lte_cr_result_hash, GUINT_TO_POINTER(pinfo->fd->num), crResult);
1293 msg3Data = g_hash_table_lookup(mac_lte_msg3_hash, GUINT_TO_POINTER(msg3Key));
1295 /* Compare CCCH bytes */
1296 if (msg3Data != NULL) {
1297 crResult->msg3FrameNum = msg3Data->framenum;
1298 if (memcmp(&msg3Data->data, tvb_get_ptr(tvb, offset, 6), 6) == 0) {
1299 crResult->status = Msg3Match;
1302 crResult->status = Msg3NoMatch;
1306 crResult->status = NoMsg3;
1310 /* Now show CR result in tree */
1311 switch (crResult->status) {
1313 proto_item_append_text(cr_ti, " (no corresponding Msg3 found!)");
1317 ti = proto_tree_add_uint(cr_tree, hf_mac_lte_control_ue_contention_resolution_msg3,
1318 tvb, 0, 0, crResult->msg3FrameNum);
1319 PROTO_ITEM_SET_GENERATED(ti);
1320 ti = proto_tree_add_boolean(cr_tree, hf_mac_lte_control_ue_contention_resolution_msg3_matched,
1322 PROTO_ITEM_SET_GENERATED(ti);
1323 proto_item_append_text(cr_ti, " (matches Msg3 from frame %u)", crResult->msg3FrameNum);
1327 ti = proto_tree_add_uint(cr_tree, hf_mac_lte_control_ue_contention_resolution_msg3,
1328 tvb, 0, 0, crResult->msg3FrameNum);
1329 PROTO_ITEM_SET_GENERATED(ti);
1330 ti = proto_tree_add_boolean(cr_tree, hf_mac_lte_control_ue_contention_resolution_msg3_matched,
1332 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
1333 "CR body in Msg4 doesn't match Msg3 CCCH in frame %u",
1334 crResult->msg3FrameNum);
1335 PROTO_ITEM_SET_GENERATED(ti);
1336 proto_item_append_text(cr_ti, " (doesn't match Msg3 from frame %u)", crResult->msg3FrameNum);
1343 case TIMING_ADVANCE_LCID:
1345 proto_item *reserved_ti;
1348 /* Check 2 reserved bits */
1349 reserved = (tvb_get_guint8(tvb, offset) & 0xc0) >> 6;
1350 reserved_ti = proto_tree_add_item(tree, hf_mac_lte_control_timing_advance_reserved, tvb, offset, 1, FALSE);
1351 if (global_mac_lte_check_reserved_bits && (reserved != 0)) {
1352 expert_add_info_format(pinfo, reserved_ti, PI_MALFORMED, PI_ERROR,
1353 "Timing Advance Reserved bits not zero (found 0x%x)", reserved);
1355 proto_tree_add_item(tree, hf_mac_lte_control_timing_advance,
1356 tvb, offset, 1, FALSE);
1360 case DRX_COMMAND_LCID:
1364 /* No payload, unless its the last subheader, in which case
1365 it extends to the end of the PDU */
1366 if (n == (number_of_headers-1)) {
1367 if (tvb_length_remaining(tvb, offset) > 0) {
1368 proto_tree_add_item(tree, hf_mac_lte_padding_data,
1369 tvb, offset, -1, FALSE);
1371 padding_length_ti = proto_tree_add_int(tree, hf_mac_lte_padding_length,
1373 p_mac_lte_info->length - offset);
1374 PROTO_ITEM_SET_GENERATED(padding_length_ti);
1376 /* Make sure the PDU isn't bigger than reported! */
1377 if (offset > p_mac_lte_info->length) {
1378 expert_add_info_format(pinfo, padding_length_ti, PI_MALFORMED, PI_ERROR,
1379 "MAC PDU is longer than reported length (reported=%u, actual=%u)",
1380 p_mac_lte_info->length, offset);
1391 /**********************************/
1392 /* UL-SCH Control PDUs */
1394 case POWER_HEADROOM_REPORT_LCID:
1397 proto_tree *phr_tree;
1402 /* Create PHR root */
1403 phr_ti = proto_tree_add_string_format(tree,
1404 hf_mac_lte_control_power_headroom,
1408 phr_tree = proto_item_add_subtree(phr_ti, ett_mac_lte_power_headroom);
1410 /* Check 2 Reserved bits */
1411 reserved = (tvb_get_guint8(tvb, offset) & 0xc0) >> 6;
1412 ti = proto_tree_add_item(phr_tree, hf_mac_lte_control_power_headroom_reserved,
1413 tvb, offset, 1, FALSE);
1414 if (global_mac_lte_check_reserved_bits && (reserved != 0)) {
1415 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
1416 "Power Headroom Reserved bits not zero (found 0x%x)", reserved);
1420 level = tvb_get_guint8(tvb, offset) & 0x3f;
1421 proto_tree_add_item(phr_tree, hf_mac_lte_control_power_headroom_level,
1422 tvb, offset, 1, FALSE);
1424 /* Show value in root label */
1425 proto_item_append_text(phr_ti, " (POWER_HEADROOM_%u)", level);
1432 proto_tree_add_item(tree, hf_mac_lte_control_crnti,
1433 tvb, offset, 2, FALSE);
1436 case TRUNCATED_BSR_LCID:
1437 case SHORT_BSR_LCID:
1439 proto_tree *bsr_tree;
1444 bsr_ti = proto_tree_add_string_format(tree,
1445 hf_mac_lte_control_bsr,
1449 bsr_tree = proto_item_add_subtree(bsr_ti, ett_mac_lte_bsr);
1452 lcgid = (tvb_get_guint8(tvb, offset) & 0xc0) >> 6;
1453 proto_tree_add_item(bsr_tree, hf_mac_lte_control_bsr_lcg_id,
1454 tvb, offset, 1, FALSE);
1456 buffer_size = tvb_get_guint8(tvb, offset) & 0x3f;
1457 proto_tree_add_item(bsr_tree, hf_mac_lte_control_bsr_buffer_size,
1458 tvb, offset, 1, FALSE);
1461 proto_item_append_text(bsr_ti, " (lcgid=%u %s)",
1463 val_to_str(buffer_size, buffer_size_vals, "Unknown"));
1468 proto_tree *bsr_tree;
1470 bsr_ti = proto_tree_add_string_format(tree,
1471 hf_mac_lte_control_bsr,
1475 bsr_tree = proto_item_add_subtree(bsr_ti, ett_mac_lte_bsr);
1477 proto_tree_add_item(bsr_tree, hf_mac_lte_control_bsr_buffer_size_1,
1478 tvb, offset, 1, FALSE);
1479 proto_tree_add_item(bsr_tree, hf_mac_lte_control_bsr_buffer_size_2,
1480 tvb, offset, 1, FALSE);
1482 proto_tree_add_item(bsr_tree, hf_mac_lte_control_bsr_buffer_size_3,
1483 tvb, offset, 1, FALSE);
1485 proto_tree_add_item(bsr_tree, hf_mac_lte_control_bsr_buffer_size_4,
1486 tvb, offset, 1, FALSE);
1491 /* No payload, unless its the last subheader, in which case
1492 it extends to the end of the PDU */
1493 if (n == (number_of_headers-1)) {
1494 if (tvb_length_remaining(tvb, offset) > 0) {
1495 proto_tree_add_item(tree, hf_mac_lte_padding_data,
1496 tvb, offset, -1, FALSE);
1498 padding_length_ti = proto_tree_add_int(tree, hf_mac_lte_padding_length,
1500 p_mac_lte_info->length - offset);
1501 PROTO_ITEM_SET_GENERATED(padding_length_ti);
1503 /* Make sure the PDU isn't bigger than reported! */
1504 if (offset > p_mac_lte_info->length) {
1505 expert_add_info_format(pinfo, padding_length_ti, PI_MALFORMED, PI_ERROR,
1506 "MAC PDU is longer than reported length (reported=%u, actual=%u)",
1507 p_mac_lte_info->length, offset);
1523 /*****************************/
1524 /* Main dissection function. */
1525 void dissect_mac_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1527 proto_tree *mac_lte_tree;
1530 struct mac_lte_info *p_mac_lte_info = NULL;
1532 static mac_lte_tap_info tap_info;
1533 memset(&tap_info, 0, sizeof(mac_lte_tap_info));
1535 /* Set protocol name */
1536 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MAC-LTE");
1538 /* Create protocol tree. */
1539 ti = proto_tree_add_item(tree, proto_mac_lte, tvb, offset, -1, FALSE);
1540 mac_lte_tree = proto_item_add_subtree(ti, ett_mac_lte);
1543 /* Look for packet info! */
1544 p_mac_lte_info = p_get_proto_data(pinfo->fd, proto_mac_lte);
1546 /* Can't dissect anything without it... */
1547 if (p_mac_lte_info == NULL) {
1549 proto_tree_add_text(mac_lte_tree, tvb, offset, -1,
1550 "Can't dissect LTE MAC frame because no per-frame info was attached!");
1551 PROTO_ITEM_SET_GENERATED(ti);
1555 /* Clear info column */
1556 col_clear(pinfo->cinfo, COL_INFO);
1559 /*****************************************/
1560 /* Show context information */
1562 ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_context_radio_type,
1563 tvb, 0, 0, p_mac_lte_info->radioType);
1564 PROTO_ITEM_SET_GENERATED(ti);
1566 ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_context_direction,
1567 tvb, 0, 0, p_mac_lte_info->direction);
1568 PROTO_ITEM_SET_GENERATED(ti);
1570 if (p_mac_lte_info->ueid != 0) {
1571 ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_context_ueid,
1572 tvb, 0, 0, p_mac_lte_info->ueid);
1573 PROTO_ITEM_SET_GENERATED(ti);
1576 ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_context_subframe_number,
1577 tvb, 0, 0, p_mac_lte_info->subframeNumber);
1578 PROTO_ITEM_SET_GENERATED(ti);
1580 if (p_mac_lte_info->rntiType != NO_RNTI) {
1581 ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_context_rnti,
1582 tvb, 0, 0, p_mac_lte_info->rnti);
1583 PROTO_ITEM_SET_GENERATED(ti);
1586 ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_context_rnti_type,
1587 tvb, 0, 0, p_mac_lte_info->rntiType);
1588 PROTO_ITEM_SET_GENERATED(ti);
1590 ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_context_predefined_frame,
1591 tvb, 0, 0, p_mac_lte_info->isPredefinedData);
1592 if (p_mac_lte_info->isPredefinedData) {
1593 PROTO_ITEM_SET_GENERATED(ti);
1596 PROTO_ITEM_SET_HIDDEN(ti);
1599 ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_context_length,
1600 tvb, 0, 0, p_mac_lte_info->length);
1601 PROTO_ITEM_SET_GENERATED(ti);
1603 if (p_mac_lte_info->reTxCount) {
1604 ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_context_retx_count,
1605 tvb, 0, 0, p_mac_lte_info->reTxCount);
1606 PROTO_ITEM_SET_GENERATED(ti);
1608 if (p_mac_lte_info->reTxCount >= global_mac_lte_retx_counter_trigger) {
1609 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_ERROR,
1610 "Frame has now been NACK'd %u times",
1611 p_mac_lte_info->reTxCount);
1615 if (p_mac_lte_info->crcStatusValid) {
1616 ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_context_crc_status,
1617 tvb, 0, 0, p_mac_lte_info->crcStatus);
1618 PROTO_ITEM_SET_GENERATED(ti);
1619 if (p_mac_lte_info->crcStatus != TRUE) {
1620 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
1621 "Frame has CRC error");
1622 col_append_fstr(pinfo->cinfo, COL_INFO, "<CRC FAILURE> on %s %u ",
1623 val_to_str(p_mac_lte_info->rntiType, rnti_type_vals,
1624 "Unknown RNTI type"),
1625 p_mac_lte_info->rnti);
1630 /* Set context-info parts of tap struct */
1631 tap_info.rnti = p_mac_lte_info->rnti;
1632 tap_info.rntiType = p_mac_lte_info->rntiType;
1633 tap_info.isPredefinedData = p_mac_lte_info->isPredefinedData;
1634 tap_info.reTxCount = p_mac_lte_info->reTxCount;
1635 tap_info.crcStatusValid = p_mac_lte_info->crcStatusValid;
1636 tap_info.crcStatus = p_mac_lte_info->crcStatus;
1637 tap_info.direction = p_mac_lte_info->direction;
1639 /* Also set total number of bytes (won't be used for UL/DL-SCH) */
1640 tap_info.single_number_of_bytes = tvb_length_remaining(tvb, offset);
1642 /* If we know its predefined data, don't try to decode any further */
1643 if (p_mac_lte_info->isPredefinedData) {
1644 proto_tree_add_item(mac_lte_tree, hf_mac_lte_predefined_pdu, tvb, offset, -1, FALSE);
1645 col_append_fstr(pinfo->cinfo, COL_INFO, "Predefined data (%u bytes)", tvb_length_remaining(tvb, offset));
1647 /* Queue tap info */
1648 if (!pinfo->in_error_pkt) {
1649 tap_queue_packet(mac_lte_tap, pinfo, &tap_info);
1655 /* IF CRC status failed, just do decode as raw bytes */
1656 if (!global_mac_lte_dissect_crc_failures &&
1657 (p_mac_lte_info->crcStatusValid && !p_mac_lte_info->crcStatus)) {
1659 proto_tree_add_item(mac_lte_tree, hf_mac_lte_raw_pdu, tvb, offset, -1, FALSE);
1660 col_append_fstr(pinfo->cinfo, COL_INFO, "Raw data (%u bytes)", tvb_length_remaining(tvb, offset));
1662 /* Queue tap info */
1663 if (!pinfo->in_error_pkt) {
1664 tap_queue_packet(mac_lte_tap, pinfo, &tap_info);
1672 /* Dissect the MAC PDU itself. Format depends upon RNTI type. */
1673 switch (p_mac_lte_info->rntiType) {
1677 dissect_pch(tvb, pinfo, mac_lte_tree, offset, p_mac_lte_info->direction);
1682 dissect_rar(tvb, pinfo, mac_lte_tree, offset, p_mac_lte_info, &tap_info);
1686 /* Can be UL-SCH or DL-SCH */
1687 dissect_ulsch_or_dlsch(tvb, pinfo, mac_lte_tree, offset, p_mac_lte_info->direction,
1688 p_mac_lte_info, &tap_info);
1692 /* BCH over DL-SCH */
1693 dissect_bch(tvb, pinfo, mac_lte_tree, offset, p_mac_lte_info);
1697 /* Must be BCH over BCH... */
1698 dissect_bch(tvb, pinfo, mac_lte_tree, offset, p_mac_lte_info);
1706 /* Queue tap info */
1707 /* TODO: if any of above (esp RRC dissection) throws exception, this isn't reached,
1708 but if call too early, won't have details... */
1709 tap_queue_packet(mac_lte_tap, pinfo, &tap_info);
1714 /* Initializes the hash table and the mem_chunk area each time a new
1715 * file is loaded or re-loaded in wireshark */
1717 mac_lte_init_protocol(void)
1719 /* Destroy any existing tables. */
1720 if (mac_lte_msg3_hash) {
1721 g_hash_table_destroy(mac_lte_msg3_hash);
1723 if (mac_lte_cr_result_hash) {
1724 g_hash_table_destroy(mac_lte_cr_result_hash);
1727 /* Now create them over */
1728 mac_lte_msg3_hash = g_hash_table_new(mac_lte_msg3_hash_func, mac_lte_msg3_hash_equal);
1729 mac_lte_cr_result_hash = g_hash_table_new(mac_lte_cr_result_hash_func, mac_lte_cr_result_hash_equal);
1733 void proto_register_mac_lte(void)
1735 static hf_register_info hf[] =
1737 /**********************************/
1738 /* Items for decoding context */
1739 { &hf_mac_lte_context_radio_type,
1741 "mac-lte.radio-type", FT_UINT8, BASE_DEC, VALS(radio_type_vals), 0x0,
1745 { &hf_mac_lte_context_direction,
1747 "mac-lte.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
1748 "Direction of message", HFILL
1751 { &hf_mac_lte_context_rnti,
1753 "mac-lte.rnti", FT_UINT16, BASE_DEC, 0, 0x0,
1754 "RNTI associated with message", HFILL
1757 { &hf_mac_lte_context_rnti_type,
1759 "mac-lte.rnti-type", FT_UINT8, BASE_DEC, VALS(rnti_type_vals), 0x0,
1760 "Type of RNTI associated with message", HFILL
1763 { &hf_mac_lte_context_ueid,
1765 "mac-lte.ueid", FT_UINT16, BASE_DEC, 0, 0x0,
1766 "User Equipment Identifier associated with message", HFILL
1769 { &hf_mac_lte_context_subframe_number,
1771 "mac-lte.subframe", FT_UINT16, BASE_DEC, 0, 0x0,
1772 "Subframe number associate with message", HFILL
1775 { &hf_mac_lte_context_predefined_frame,
1776 { "Predefined frame",
1777 "mac-lte.is-predefined-frame", FT_UINT8, BASE_DEC, VALS(predefined_frame_vals), 0x0,
1778 "Predefined test frame (or real MAC PDU)", HFILL
1781 { &hf_mac_lte_context_length,
1782 { "Length of frame",
1783 "mac-lte.length", FT_UINT8, BASE_DEC, 0, 0x0,
1784 "Original length of frame (including SDUs and padding)", HFILL
1787 { &hf_mac_lte_context_bch_transport_channel,
1788 { "Transport channel",
1789 "mac-lte.bch-transport-channel", FT_UINT8, BASE_DEC, VALS(bch_transport_channel_vals), 0x0,
1790 "Transport channel BCH data was carried on", HFILL
1793 { &hf_mac_lte_context_retx_count,
1795 "mac-lte.retx-count", FT_UINT8, BASE_DEC, 0, 0x0,
1796 "Number of times this PDU has been retransmitted", HFILL
1799 { &hf_mac_lte_context_crc_status,
1801 "mac-lte.crc-status", FT_UINT8, BASE_DEC, VALS(crc_status_vals), 0x0,
1802 "CRC Status as reported by PHY", HFILL
1807 /*******************************************/
1808 /* MAC shared channel header fields */
1809 { &hf_mac_lte_ulsch_header,
1811 "mac-lte.ulsch.header", FT_STRING, BASE_NONE, NULL, 0x0,
1815 { &hf_mac_lte_dlsch_header,
1817 "mac-lte.dlsch.header", FT_STRING, BASE_NONE, NULL, 0x0,
1821 { &hf_mac_lte_sch_subheader,
1823 "mac-lte.sch.subheader", FT_STRING, BASE_NONE, NULL, 0x0,
1827 { &hf_mac_lte_sch_reserved,
1828 { "SCH reserved bits",
1829 "mac-lte.sch.reserved", FT_UINT8, BASE_HEX, NULL, 0xc0,
1833 { &hf_mac_lte_sch_extended,
1835 "mac-lte.sch.extended", FT_UINT8, BASE_HEX, 0, 0x20,
1836 "Extension - i.e. further headers after this one", HFILL
1839 { &hf_mac_lte_dlsch_lcid,
1841 "mac-lte.dlsch.lcid", FT_UINT8, BASE_HEX, VALS(dlsch_lcid_vals), 0x1f,
1842 "DL-SCH Logical Channel Identifier", HFILL
1845 { &hf_mac_lte_ulsch_lcid,
1847 "mac-lte.ulsch.lcid", FT_UINT8, BASE_HEX, VALS(ulsch_lcid_vals), 0x1f,
1848 "UL-SCH Logical Channel Identifier", HFILL
1851 { &hf_mac_lte_sch_format,
1853 "mac-lte.sch.format", FT_UINT8, BASE_HEX, VALS(format_vals), 0x80,
1857 { &hf_mac_lte_sch_length,
1859 "mac-lte.sch.length", FT_UINT16, BASE_DEC, 0, 0x0,
1860 "Length of MAC SDU or MAC control element", HFILL
1863 { &hf_mac_lte_sch_header_only,
1864 { "MAC PDU Header only",
1865 "mac-lte.sch.header-only", FT_UINT8, BASE_DEC, VALS(header_only_vals), 0x0,
1870 /********************************/
1872 { &hf_mac_lte_sch_sdu,
1874 "mac-lte.sch.sdu", FT_BYTES, BASE_NONE, 0, 0x0,
1875 "Shared channel SDU", HFILL
1878 { &hf_mac_lte_bch_pdu,
1880 "mac-lte.bch.pdu", FT_BYTES, BASE_NONE, 0, 0x0,
1884 { &hf_mac_lte_pch_pdu,
1886 "mac-lte.pch.pdu", FT_BYTES, BASE_NONE, 0, 0x0,
1890 { &hf_mac_lte_predefined_pdu,
1891 { "Predefined data",
1892 "mac-lte.predefined-data", FT_BYTES, BASE_NONE, 0, 0x0,
1893 "Predefined test data", HFILL
1896 { &hf_mac_lte_raw_pdu,
1898 "mac-lte.raw-data", FT_BYTES, BASE_NONE, 0, 0x0,
1899 "Raw bytes of PDU (e.g. if CRC failed)", HFILL
1902 { &hf_mac_lte_padding_data,
1904 "mac-lte.padding-data", FT_BYTES, BASE_NONE, 0, 0x0,
1908 { &hf_mac_lte_padding_length,
1910 "mac-lte.padding-length", FT_INT32, BASE_DEC, 0, 0x0,
1911 "Length of padding data not included at end of frame", HFILL
1917 /*********************************/
1921 "mac-lte.rar", FT_NONE, BASE_NONE, NULL, 0x0,
1925 { &hf_mac_lte_rar_headers,
1927 "mac-lte.rar.headers", FT_STRING, BASE_NONE, NULL, 0x0,
1931 { &hf_mac_lte_rar_header,
1933 "mac-lte.rar.header", FT_STRING, BASE_NONE, NULL, 0x0,
1937 { &hf_mac_lte_rar_extension,
1939 "mac-lte.rar.e", FT_UINT8, BASE_HEX, 0, 0x80,
1940 "Extension - i.e. further RAR headers after this one", HFILL
1943 { &hf_mac_lte_rar_t,
1945 "mac-lte.rar.t", FT_UINT8, BASE_HEX, VALS(rar_type_vals), 0x40,
1946 "Type field indicating whether the payload is RAPID or BI", HFILL
1949 { &hf_mac_lte_rar_bi,
1951 "mac-lte.rar.bi", FT_UINT8, BASE_HEX, VALS(rar_bi_vals), 0x0f,
1952 "Backoff Indicator (ms)", HFILL
1955 { &hf_mac_lte_rar_rapid,
1957 "mac-lte.rar.rapid", FT_UINT8, BASE_HEX_DEC, 0, 0x3f,
1958 "Random Access Preamble IDentifier", HFILL
1961 { &hf_mac_lte_rar_reserved,
1963 "mac-lte.rar.reserved", FT_UINT8, BASE_HEX, 0, 0x30,
1964 "Reserved bits in RAR header - should be 0", HFILL
1968 { &hf_mac_lte_rar_body,
1970 "mac-lte.rar.body", FT_STRING, BASE_NONE, NULL, 0x0,
1974 { &hf_mac_lte_rar_reserved2,
1976 "mac-lte.rar.reserved2", FT_UINT8, BASE_HEX, 0, 0x80,
1977 "Reserved bit in RAR body - should be 0", HFILL
1980 { &hf_mac_lte_rar_ta,
1982 "mac-lte.rar.ta", FT_UINT16, BASE_DEC, 0, 0x7ff0,
1983 "Required adjustment to uplink transmission timing", HFILL
1986 { &hf_mac_lte_rar_ul_grant,
1988 "mac-lte.rar.ul-grant", FT_UINT24, BASE_DEC, 0, 0x0fffff,
1989 "Size of UL Grant", HFILL
1992 { &hf_mac_lte_rar_ul_grant_hopping,
1994 "mac-lte.rar.ul-grant.hopping", FT_UINT8, BASE_DEC, 0, 0x08,
1995 "Size of UL Grant", HFILL
1998 { &hf_mac_lte_rar_ul_grant_fsrba,
1999 { "Fixed sized resource block assignment",
2000 "mac-lte.rar.ul-grant.fsrba", FT_UINT16, BASE_DEC, 0, 0x07fe,
2004 { &hf_mac_lte_rar_ul_grant_tmcs,
2005 { "Truncated Modulation and coding scheme",
2006 "mac-lte.rar.ul-grant.tmcs", FT_UINT16, BASE_DEC, 0, 0x01e0,
2010 { &hf_mac_lte_rar_ul_grant_tcsp,
2011 { "TPC command for scheduled PUSCH",
2012 "mac-lte.rar.ul-grant.tcsp", FT_UINT8, BASE_DEC, 0, 0x01c,
2016 { &hf_mac_lte_rar_ul_grant_ul_delay,
2018 "mac-lte.rar.ul-grant.ul-delay", FT_UINT8, BASE_DEC, 0, 0x02,
2022 { &hf_mac_lte_rar_ul_grant_cqi_request,
2024 "mac-lte.rar.ul-grant.cqi-request", FT_UINT8, BASE_DEC, 0, 0x01,
2028 { &hf_mac_lte_rar_temporary_crnti,
2029 { "Temporary C-RNTI",
2030 "mac-lte.rar.temporary-crnti", FT_UINT16, BASE_DEC, 0, 0x0,
2035 /**********************/
2036 /* Control PDU fields */
2037 { &hf_mac_lte_control_bsr,
2039 "mac-lte.control.bsr", FT_STRING, BASE_NONE, 0, 0x0,
2040 "Buffer Status Report", HFILL
2043 { &hf_mac_lte_control_bsr_lcg_id,
2044 { "Logical Channel Group ID",
2045 "mac-lte.control.bsr.lcg-id", FT_UINT8, BASE_DEC, 0, 0xc0,
2049 { &hf_mac_lte_control_bsr_buffer_size,
2051 "mac-lte.control.bsr.buffer-size", FT_UINT8, BASE_DEC, VALS(buffer_size_vals), 0x3f,
2052 "Buffer Size available in all channels in group", HFILL
2055 { &hf_mac_lte_control_bsr_buffer_size_1,
2057 "mac-lte.control.bsr.buffer-size-1", FT_UINT8, BASE_DEC, VALS(buffer_size_vals), 0xfc,
2058 "Buffer Size available in for 1st channel in group", HFILL
2061 { &hf_mac_lte_control_bsr_buffer_size_2,
2063 "mac-lte.control.bsr.buffer-size-2", FT_UINT16, BASE_DEC, VALS(buffer_size_vals), 0x03c0,
2064 "Buffer Size available in for 2nd channel in group", HFILL
2067 { &hf_mac_lte_control_bsr_buffer_size_3,
2069 "mac-lte.control.bsr.buffer-size-3", FT_UINT16, BASE_DEC, VALS(buffer_size_vals), 0x0fc0,
2070 "Buffer Size available in for 3rd channel in group", HFILL
2073 { &hf_mac_lte_control_bsr_buffer_size_4,
2075 "mac-lte.control.bsr.buffer-size-4", FT_UINT8, BASE_DEC, VALS(buffer_size_vals), 0x3f,
2076 "Buffer Size available in for 4th channel in group", HFILL
2079 { &hf_mac_lte_control_crnti,
2081 "mac-lte.control.crnti", FT_UINT16, BASE_DEC, 0, 0x0,
2082 "C-RNTI for the UE", HFILL
2085 { &hf_mac_lte_control_timing_advance,
2087 "mac-lte.control.timing-advance", FT_UINT8, BASE_DEC, 0, 0x3f,
2088 "Timing Advance (0-1282 - see 36.213, 4.2.3)", HFILL
2091 { &hf_mac_lte_control_timing_advance_reserved,
2093 "mac-lte.control.timing-advance.reserved", FT_UINT8, BASE_DEC, 0, 0xc0,
2094 "Reserved bits", HFILL
2097 { &hf_mac_lte_control_ue_contention_resolution,
2098 { "UE Contention Resolution",
2099 "mac-lte.control.ue-contention-resolution", FT_STRING, BASE_NONE, 0, 0x0,
2103 { &hf_mac_lte_control_ue_contention_resolution_identity,
2104 { "UE Contention Resolution Identity",
2105 "mac-lte.control.ue-contention-resolution.identity", FT_BYTES, BASE_NONE, 0, 0x0,
2109 { &hf_mac_lte_control_ue_contention_resolution_msg3,
2111 "mac-lte.control.ue-contention-resolution.msg3", FT_FRAMENUM, BASE_NONE, 0, 0x0,
2115 { &hf_mac_lte_control_ue_contention_resolution_msg3_matched,
2116 { "UE Contention Resolution Matches Msg3",
2117 "mac-lte.control.ue-contention-resolution.matches-msg3", FT_BOOLEAN, BASE_NONE, 0, 0x0,
2122 { &hf_mac_lte_control_power_headroom,
2124 "mac-lte.control.power-headroom", FT_STRING, BASE_NONE, 0, 0x0,
2128 { &hf_mac_lte_control_power_headroom_reserved,
2130 "mac-lte.control.power-headroom.reserved", FT_UINT8, BASE_DEC, 0, 0xc0,
2131 "Reserved bits, should be 0", HFILL
2134 { &hf_mac_lte_control_power_headroom_level,
2135 { "Power Headroom Level",
2136 "mac-lte.control.power-headroom.level", FT_UINT8, BASE_DEC, 0, 0x3f,
2141 { &hf_mac_lte_control_padding,
2143 "mac-lte.control.padding", FT_NONE, BASE_NONE, 0, 0x0,
2149 static gint *ett[] =
2152 &ett_mac_lte_context,
2153 &ett_mac_lte_rar_headers,
2154 &ett_mac_lte_rar_header,
2155 &ett_mac_lte_rar_body,
2156 &ett_mac_lte_rar_ul_grant,
2157 &ett_mac_lte_ulsch_header,
2158 &ett_mac_lte_dlsch_header,
2159 &ett_mac_lte_sch_subheader,
2163 &ett_mac_lte_contention_resolution,
2164 &ett_mac_lte_power_headroom
2167 module_t *mac_lte_module;
2169 /* Register protocol. */
2170 proto_mac_lte = proto_register_protocol("MAC-LTE", "MAC-LTE", "mac-lte");
2171 proto_register_field_array(proto_mac_lte, hf, array_length(hf));
2172 proto_register_subtree_array(ett, array_length(ett));
2174 /* Allow other dissectors to find this one by name. */
2175 register_dissector("mac-lte", dissect_mac_lte, proto_mac_lte);
2177 /* Register the tap name */
2178 mac_lte_tap = register_tap("mac-lte");
2181 mac_lte_module = prefs_register_protocol(proto_mac_lte, NULL);
2183 /* Obsolete this preference? (TODO: just delete since never in proper release?) */
2184 prefs_register_obsolete_preference(mac_lte_module, "single_rar");
2186 prefs_register_bool_preference(mac_lte_module, "check_reserved_bits",
2187 "Warn if reserved bits are not 0",
2188 "When set, an expert warning will indicate if reserved bits are not zero",
2189 &global_mac_lte_check_reserved_bits);
2191 prefs_register_uint_preference(mac_lte_module, "retx_count_warn",
2192 "Number of Re-Transmits before expert warning triggered",
2193 "Number of Re-Transmits before expert warning triggered",
2194 10, &global_mac_lte_retx_counter_trigger);
2196 prefs_register_bool_preference(mac_lte_module, "attempt_rrc_decode",
2197 "Attempt to decode BCH, PCH and CCCH data using LTE RRC dissector",
2198 "Attempt to decode BCH, PCH and CCCH data using LTE RRC dissector",
2199 &global_mac_lte_attempt_rrc_decode);
2201 prefs_register_bool_preference(mac_lte_module, "decode_rar_ul_grant",
2202 "Attempt to decode details of RAR UL grant field",
2203 "Attempt to decode details of RAR UL grant field",
2204 &global_mac_lte_decode_rar_ul_grant);
2206 prefs_register_bool_preference(mac_lte_module, "attempt_to_dissect_crc_failures",
2207 "Dissect frames that have failed CRC check",
2208 "Attempt to dissect frames that have failed CRC check",
2209 &global_mac_lte_dissect_crc_failures);
2211 prefs_register_bool_preference(mac_lte_module, "heuristic_mac_lte_over_udp",
2212 "Try Heuristic LTE-MAC over UDP framing",
2213 "When enabled, use heuristic dissector to find MAC-LTE frames sent with "
2215 &global_mac_lte_heur);
2217 register_init_routine(&mac_lte_init_protocol);
2221 proto_reg_handoff_mac_lte(void)
2223 static dissector_handle_t mac_lte_handle;
2224 if (!mac_lte_handle) {
2225 mac_lte_handle = find_dissector("mac-lte");
2227 /* Add as a heuristic UDP dissector */
2228 heur_dissector_add("udp", dissect_mac_lte_heur, proto_mac_lte);