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)
48 /* Initialize the protocol and registered fields. */
49 int proto_mac_lte = -1;
51 static int mac_lte_tap = -1;
53 /* Decoding context */
54 static int hf_mac_lte_context = -1;
55 static int hf_mac_lte_context_radio_type = -1;
56 static int hf_mac_lte_context_direction = -1;
57 static int hf_mac_lte_context_rnti = -1;
58 static int hf_mac_lte_context_rnti_type = -1;
59 static int hf_mac_lte_context_ueid = -1;
60 static int hf_mac_lte_context_subframe_number = -1;
61 static int hf_mac_lte_context_grant_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 /* Inferred context */
72 static int hf_mac_lte_ues_ul_per_tti = -1;
73 static int hf_mac_lte_ues_dl_per_tti = -1;
76 /* Extra PHY context */
77 static int hf_mac_lte_context_phy_ul = -1;
78 static int hf_mac_lte_context_phy_ul_modulation_type = -1;
79 static int hf_mac_lte_context_phy_ul_tbs_index = -1;
80 static int hf_mac_lte_context_phy_ul_resource_block_length = -1;
81 static int hf_mac_lte_context_phy_ul_resource_block_start = -1;
82 static int hf_mac_lte_context_phy_ul_harq_id = -1;
83 static int hf_mac_lte_context_phy_ul_ndi = -1;
85 static int hf_mac_lte_context_phy_dl = -1;
86 static int hf_mac_lte_context_phy_dl_dci_format = -1;
87 static int hf_mac_lte_context_phy_dl_resource_allocation_type = -1;
88 static int hf_mac_lte_context_phy_dl_aggregation_level = -1;
89 static int hf_mac_lte_context_phy_dl_mcs_index = -1;
90 static int hf_mac_lte_context_phy_dl_redundancy_version_index = -1;
91 static int hf_mac_lte_context_phy_dl_retx = -1;
92 static int hf_mac_lte_context_phy_dl_resource_block_length = -1;
93 static int hf_mac_lte_context_phy_dl_crc_status = -1;
94 static int hf_mac_lte_context_phy_dl_harq_id = -1;
95 static int hf_mac_lte_context_phy_dl_ndi = -1;
96 static int hf_mac_lte_context_phy_dl_tb = -1;
99 /* Out-of-band events */
100 static int hf_mac_lte_oob_send_preamble = -1;
101 static int hf_mac_lte_oob_send_sr = -1;
102 static int hf_mac_lte_oob_sr_failure = -1;
104 /* MAC SCH header fields */
105 static int hf_mac_lte_ulsch = -1;
106 static int hf_mac_lte_ulsch_header = -1;
107 static int hf_mac_lte_dlsch = -1;
108 static int hf_mac_lte_dlsch_header = -1;
109 static int hf_mac_lte_sch_subheader = -1;
111 static int hf_mac_lte_sch_reserved = -1;
112 static int hf_mac_lte_dlsch_lcid = -1;
113 static int hf_mac_lte_ulsch_lcid = -1;
114 static int hf_mac_lte_sch_extended = -1;
115 static int hf_mac_lte_sch_format = -1;
116 static int hf_mac_lte_sch_length = -1;
118 static int hf_mac_lte_sch_header_only = -1;
121 static int hf_mac_lte_sch_sdu = -1;
122 static int hf_mac_lte_bch_pdu = -1;
123 static int hf_mac_lte_pch_pdu = -1;
124 static int hf_mac_lte_predefined_pdu = -1;
125 static int hf_mac_lte_raw_pdu = -1;
126 static int hf_mac_lte_padding_data = -1;
127 static int hf_mac_lte_padding_length = -1;
131 static int hf_mac_lte_rar = -1;
132 static int hf_mac_lte_rar_headers = -1;
133 static int hf_mac_lte_rar_header = -1;
134 static int hf_mac_lte_rar_extension = -1;
135 static int hf_mac_lte_rar_t = -1;
136 static int hf_mac_lte_rar_bi = -1;
137 static int hf_mac_lte_rar_rapid = -1;
138 static int hf_mac_lte_rar_reserved = -1;
139 static int hf_mac_lte_rar_body = -1;
140 static int hf_mac_lte_rar_reserved2 = -1;
141 static int hf_mac_lte_rar_ta = -1;
142 static int hf_mac_lte_rar_ul_grant = -1;
143 static int hf_mac_lte_rar_ul_grant_hopping = -1;
144 static int hf_mac_lte_rar_ul_grant_fsrba = -1;
145 static int hf_mac_lte_rar_ul_grant_tmcs = -1;
146 static int hf_mac_lte_rar_ul_grant_tcsp = -1;
147 static int hf_mac_lte_rar_ul_grant_ul_delay = -1;
148 static int hf_mac_lte_rar_ul_grant_cqi_request = -1;
149 static int hf_mac_lte_rar_temporary_crnti = -1;
151 /* Common channel control values */
152 static int hf_mac_lte_control_bsr = -1;
153 static int hf_mac_lte_control_bsr_lcg_id = -1;
154 static int hf_mac_lte_control_short_bsr_buffer_size = -1;
155 static int hf_mac_lte_control_long_bsr_buffer_size_0 = -1;
156 static int hf_mac_lte_control_long_bsr_buffer_size_1 = -1;
157 static int hf_mac_lte_control_long_bsr_buffer_size_2 = -1;
158 static int hf_mac_lte_control_long_bsr_buffer_size_3 = -1;
159 static int hf_mac_lte_control_crnti = -1;
160 static int hf_mac_lte_control_timing_advance = -1;
161 static int hf_mac_lte_control_timing_advance_reserved = -1;
162 static int hf_mac_lte_control_ue_contention_resolution = -1;
163 static int hf_mac_lte_control_ue_contention_resolution_identity = -1;
164 static int hf_mac_lte_control_ue_contention_resolution_msg3 = -1;
165 static int hf_mac_lte_control_ue_contention_resolution_msg3_matched = -1;
166 static int hf_mac_lte_control_ue_contention_resolution_time_since_msg3 = -1;
167 static int hf_mac_lte_control_power_headroom = -1;
168 static int hf_mac_lte_control_power_headroom_reserved = -1;
169 static int hf_mac_lte_control_power_headroom_level = -1;
170 static int hf_mac_lte_control_padding = -1;
172 static int hf_mac_lte_suspected_dl_retx_original_frame = -1;
173 static int hf_mac_lte_suspected_dl_retx_time_since_previous_frame = -1;
175 static int hf_mac_lte_ul_harq_resend_original_frame = -1;
176 static int hf_mac_lte_ul_harq_resend_time_since_previous_frame = -1;
178 static int hf_mac_lte_grant_answering_sr = -1;
179 static int hf_mac_lte_failure_answering_sr = -1;
180 static int hf_mac_lte_sr_leading_to_failure = -1;
181 static int hf_mac_lte_sr_leading_to_grant = -1;
182 static int hf_mac_lte_sr_invalid_event = -1;
183 static int hf_mac_lte_sr_time_since_request = -1;
184 static int hf_mac_lte_sr_time_until_answer = -1;
188 static int ett_mac_lte = -1;
189 static int ett_mac_lte_context = -1;
190 static int ett_mac_lte_phy_context = -1;
191 static int ett_mac_lte_ulsch_header = -1;
192 static int ett_mac_lte_dlsch_header = -1;
193 static int ett_mac_lte_sch_subheader = -1;
194 static int ett_mac_lte_rar_headers = -1;
195 static int ett_mac_lte_rar_header = -1;
196 static int ett_mac_lte_rar_body = -1;
197 static int ett_mac_lte_rar_ul_grant = -1;
198 static int ett_mac_lte_bsr = -1;
199 static int ett_mac_lte_bch = -1;
200 static int ett_mac_lte_pch = -1;
201 static int ett_mac_lte_contention_resolution = -1;
202 static int ett_mac_lte_power_headroom = -1;
203 static int ett_mac_lte_oob = -1;
207 /* Constants and value strings */
209 static const value_string radio_type_vals[] =
217 static const value_string direction_vals[] =
219 { DIRECTION_UPLINK, "Uplink"},
220 { DIRECTION_DOWNLINK, "Downlink"},
225 static const value_string rnti_type_vals[] =
227 { NO_RNTI, "NO-RNTI"},
229 { RA_RNTI, "RA-RNTI"},
231 { SI_RNTI, "SI-RNTI"},
232 { SPS_RNTI, "SPS-RNTI"},
236 static const value_string bch_transport_channel_vals[] =
238 { SI_RNTI, "DL-SCH"},
243 static const value_string crc_status_vals[] =
245 { crc_success, "OK"},
246 { crc_fail, "Failed"},
247 { crc_high_code_rate, "High Code Rate"},
248 { crc_pdsch_lost, "PDSCH Lost"},
249 { crc_duplicate_nonzero_rv, "Duplicate_nonzero_rv"},
254 static const value_string dci_format_vals[] =
268 static const value_string aggregation_level_vals[] =
277 static const value_string modulation_type_vals[] =
286 #define UE_CONTENTION_RESOLUTION_IDENTITY_LCID 0x1c
287 #define TIMING_ADVANCE_LCID 0x1d
288 #define DRX_COMMAND_LCID 0x1e
289 #define PADDING_LCID 0x1f
291 static const value_string dlsch_lcid_vals[] =
304 { UE_CONTENTION_RESOLUTION_IDENTITY_LCID, "UE Contention Resolution Identity"},
305 { TIMING_ADVANCE_LCID , "Timing Advance"},
306 { DRX_COMMAND_LCID , "DRX Command"},
307 { PADDING_LCID , "Padding" },
311 #define POWER_HEADROOM_REPORT_LCID 0x1a
312 #define CRNTI_LCID 0x1b
313 #define TRUNCATED_BSR_LCID 0x1c
314 #define SHORT_BSR_LCID 0x1d
315 #define LONG_BSR_LCID 0x1e
317 static const value_string ulsch_lcid_vals[] =
330 { POWER_HEADROOM_REPORT_LCID, "Power Headroom Report"},
331 { CRNTI_LCID, "C-RNTI"},
332 { TRUNCATED_BSR_LCID, "Truncated BSR"},
333 { SHORT_BSR_LCID, "Short BSR"},
334 { LONG_BSR_LCID, "Long BSR"},
335 { PADDING_LCID, "Padding" },
340 static const value_string format_vals[] =
342 { 0, "Data length is < 128 bytes"},
343 { 1, "Data length is >= 128 bytes"},
348 static const value_string rar_type_vals[] =
350 { 0, "Backoff Indicator present"},
351 { 1, "RAPID present"},
356 static const value_string rar_bi_vals[] =
375 static const value_string buffer_size_vals[] =
378 { 1, "0 < BS <= 10"},
379 { 2, "10 < BS <= 12"},
380 { 3, "12 < BS <= 14"},
381 { 4, "14 < BS <= 17"},
382 { 5, "17 < BS <= 19"},
383 { 6, "19 < BS <= 22"},
384 { 7, "22 < BS <= 26"},
385 { 8, "26 < BS <= 31"},
386 { 9, "31 < BS <= 36"},
387 { 10, "36 < BS <= 42"},
388 { 11, "42 < BS <= 49"},
389 { 12, "49 < BS <= 57"},
390 { 13, "47 < BS <= 67"},
391 { 14, "67 < BS <= 78"},
392 { 15, "78 < BS <= 91"},
393 { 16, "91 < BS <= 107"},
394 { 17, "107 < BS <= 125"},
395 { 18, "125 < BS <= 146"},
396 { 19, "146 < BS <= 171"},
397 { 20, "171 < BS <= 200"},
398 { 21, "200 < BS <= 234"},
399 { 22, "234 < BS <= 274"},
400 { 23, "274 < BS <= 321"},
401 { 24, "321 < BS <= 376"},
402 { 25, "376 < BS <= 440"},
403 { 26, "440 < BS <= 515"},
404 { 27, "515 < BS <= 603"},
405 { 28, "603 < BS <= 706"},
406 { 29, "706 < BS <= 826"},
407 { 30, "826 < BS <= 967"},
408 { 31, "967 < BS <= 1132"},
409 { 32, "1132 < BS <= 1326"},
410 { 33, "1326 < BS <= 1552"},
411 { 34, "1552 < BS <= 1817"},
412 { 35, "1817 < BS <= 2127"},
413 { 36, "2127 < BS <= 2490"},
414 { 37, "2490 < BS <= 2915"},
415 { 38, "2915 < BS <= 3413"},
416 { 39, "3413 < BS <= 3995"},
417 { 40, "3995 < BS <= 4677"},
418 { 41, "4677 < BS <= 5476"},
419 { 42, "5476 < BS <= 6411"},
420 { 43, "6411 < BS <= 7505"},
421 { 44, "7505 < BS <= 8787"},
422 { 45, "8787 < BS <= 10276"},
423 { 46, "10287 < BS <= 12043"},
424 { 47, "12043 < BS <= 14099"},
425 { 48, "14099 < BS <= 16507"},
426 { 49, "16507 < BS <= 19325"},
427 { 50, "19325 < BS <= 22624"},
428 { 51, "22624 < BS <= 26487"},
429 { 52, "26487 < BS <= 31009"},
430 { 53, "31009 < BS <= 36304"},
431 { 54, "36304 < BS <= 42502"},
432 { 55, "42502 < BS <= 49759"},
433 { 56, "49759 < BS <= 58255"},
434 { 57, "58255 < BS <= 68201"},
435 { 58, "68201 < BS <= 79846"},
436 { 59, "79846 < BS <= 93479"},
437 { 60, "93479 < BS <= 109439"},
438 { 61, "109439 < BS <= 128125"},
439 { 62, "128125 < BS <= 150000"},
440 { 63, "BS > 150000"},
444 static const value_string power_headroom_size_vals[] =
446 { 0, "-23 <= PH < -22"},
447 { 1, "-22 <= PH < -21"},
448 { 2, "-21 <= PH < -20"},
449 { 3, "-20 <= PH < -19"},
450 { 4, "-19 <= PH < -18"},
451 { 5, "-18 <= PH < -17"},
452 { 6, "-17 <= PH < -16"},
453 { 7, "-16 <= PH < -15"},
454 { 8, "-15 <= PH < -14"},
455 { 9, "-14 <= PH < -13"},
456 { 10, "-13 <= PH < -12"},
457 { 11, "-12 <= PH < -11"},
458 { 12, "-11 <= PH < -10"},
459 { 13, "-10 <= PH < -9"},
460 { 14, "-9 <= PH < -8"},
461 { 15, "-8 <= PH < -7"},
462 { 16, "-7 <= PH < -6"},
463 { 17, "-6 <= PH < -5"},
464 { 18, "-5 <= PH < -4"},
465 { 19, "-4 <= PH < -3"},
466 { 20, "-3 <= PH < -2"},
467 { 21, "-2 <= PH < -1"},
468 { 22, "-1 <= PH < 0"},
469 { 23, "0 <= PH < 1"},
470 { 24, "1 <= PH < 2"},
471 { 25, "2 <= PH < 3"},
472 { 26, "3 <= PH < 4"},
473 { 27, "4 <= PH < 5"},
474 { 28, "5 <= PH < 6"},
475 { 29, "6 <= PH < 7"},
476 { 30, "7 <= PH < 8"},
477 { 31, "8 <= PH < 9"},
478 { 32, "9 <= PH < 10"},
479 { 33, "10 <= PH < 11"},
480 { 34, "11 <= PH < 12"},
481 { 35, "12 <= PH < 13"},
482 { 36, "13 <= PH < 14"},
483 { 37, "14 <= PH < 15"},
484 { 38, "15 <= PH < 16"},
485 { 39, "16 <= PH < 17"},
486 { 40, "17 <= PH < 18"},
487 { 41, "18 <= PH < 19"},
488 { 42, "19 <= PH < 20"},
489 { 43, "20 <= PH < 21"},
490 { 44, "21 <= PH < 22"},
491 { 45, "22 <= PH < 23"},
492 { 46, "23 <= PH < 24"},
493 { 47, "24 <= PH < 25"},
494 { 48, "25 <= PH < 26"},
495 { 49, "26 <= PH < 27"},
496 { 50, "27 <= PH < 28"},
497 { 51, "28 <= PH < 29"},
498 { 52, "29 <= PH < 30"},
499 { 53, "30 <= PH < 31"},
500 { 54, "31 <= PH < 32"},
501 { 55, "32 <= PH < 33"},
502 { 56, "33 <= PH < 34"},
503 { 57, "34 <= PH < 35"},
504 { 58, "34 <= PH < 36"},
505 { 59, "36 <= PH < 37"},
506 { 60, "37 <= PH < 38"},
507 { 61, "38 <= PH < 39"},
508 { 62, "39 <= PH < 40"},
513 static const value_string header_only_vals[] =
515 { 0, "MAC PDU Headers and body present"},
516 { 1, "MAC PDU Headers only"},
520 static const value_string predefined_frame_vals[] =
522 { 0, "Real MAC PDU present - will dissect"},
523 { 1, "Predefined frame present - will not dissect"},
529 /**************************************************************************/
530 /* Preferences state */
531 /**************************************************************************/
533 /* If this PDU has been NACK'd (by HARQ) more than a certain number of times,
534 we trigger an expert warning. */
535 static gint global_mac_lte_retx_counter_trigger = 3;
537 /* By default try to decode transparent data (BCH, PCH and CCCH) data using LTE RRC dissector */
538 static gboolean global_mac_lte_attempt_rrc_decode = TRUE;
540 /* Whether should attempt to dissect frames failing CRC check */
541 static gboolean global_mac_lte_dissect_crc_failures = FALSE;
543 /* Whether should attempt to decode lcid 1&2 SDUs as srb1/2 (i.e. AM RLC) */
544 static gboolean global_mac_lte_attempt_srb_decode = TRUE;
546 /* Where to take LCID -> DRB mappings from */
547 enum lcid_drb_source {
548 FromStaticTable, FromConfigurationProtocol
550 static gint global_mac_lte_lcid_drb_source = (gint)FromStaticTable;
552 /* Threshold for warning in expert info about high BSR values */
553 static gint global_mac_lte_bsr_warn_threshold = 50; /* default is 19325 -> 22624 */
555 /* Whether or not to track SRs and related frames */
556 static gboolean global_mac_lte_track_sr = TRUE;
558 /* Which layer info to show in the info column */
560 ShowPHYLayer, ShowMACLayer, ShowRLCLayer
563 /* Which layer's details to show in Info column */
564 static gint global_mac_lte_layer_to_show = (gint)ShowRLCLayer;
566 /* When showing RLC info, count PDUs so can append info column properly */
567 static guint8 s_number_of_rlc_pdus_shown = 0;
569 /***********************************************************************/
570 /* How to dissect lcid 3-10 (presume drb logical channels) */
572 static const value_string drb_lcid_vals[] = {
584 typedef enum rlc_channel_type_t {
590 } rlc_channel_type_t;
592 static const value_string rlc_channel_type_vals[] = {
594 { rlcUM5 , "UM, SN Len=5"},
595 { rlcUM10, "UM, SN Len=10"},
602 typedef struct lcid_drb_mapping_t {
605 rlc_channel_type_t channel_type;
606 } lcid_drb_mapping_t;
609 static lcid_drb_mapping_t *lcid_drb_mappings = NULL;
610 static guint num_lcid_drb_mappings = 0;
612 UAT_VS_DEF(lcid_drb_mappings, lcid, lcid_drb_mapping_t, 3, "LCID 3")
613 UAT_DEC_CB_DEF(lcid_drb_mappings, drbid, lcid_drb_mapping_t)
614 UAT_VS_DEF(lcid_drb_mappings, channel_type, lcid_drb_mapping_t, 2, "AM")
617 static uat_t* lcid_drb_mappings_uat;
619 /* Dynamic mappings (set by configuration protocol)
620 LCID is the index into the array of these */
621 typedef struct dynamic_lcid_drb_mapping_t {
624 rlc_channel_type_t channel_type;
625 } dynamic_lcid_drb_mapping_t;
627 static dynamic_lcid_drb_mapping_t dynamic_lcid_drb_mapping[11];
630 extern int proto_rlc_lte;
632 /***************************************************************/
636 /***************************************************************/
637 /* Keeping track of Msg3 bodies so they can be compared with */
638 /* Contention Resolution bodies. */
640 typedef struct Msg3Data {
647 /* This table stores (RNTI -> Msg3Data*). Will be populated when
648 Msg3 frames are first read. */
649 static GHashTable *mac_lte_msg3_hash = NULL;
651 /* Hash table functions for mac_lte_msg3_hash. Hash is just the (RNTI) key */
652 static gint mac_lte_rnti_hash_equal(gconstpointer v, gconstpointer v2)
657 static guint mac_lte_rnti_hash_func(gconstpointer v)
659 return GPOINTER_TO_UINT(v);
663 typedef enum ContentionResolutionStatus {
667 } ContentionResolutionStatus;
669 typedef struct ContentionResolutionResult {
670 ContentionResolutionStatus status;
673 } ContentionResolutionResult;
676 /* This table stores (CRFrameNum -> CRResult). It is assigned during the first
677 pass and used thereafter */
678 static GHashTable *mac_lte_cr_result_hash = NULL;
680 /* Hash table functions for mac_lte_cr_result_hash. Hash is just the (framenum) key */
681 static gint mac_lte_framenum_hash_equal(gconstpointer v, gconstpointer v2)
686 static guint mac_lte_framenum_hash_func(gconstpointer v)
688 return GPOINTER_TO_UINT(v);
691 /**************************************************************************/
695 /****************************************************************/
696 /* Keeping track of last DL frames per C-RNTI so can guess when */
697 /* there has been a HARQ retransmission */
698 /* TODO: this should be simplified now that harq-id & ndi are */
701 /* Could be bigger, but more than enough to flag suspected resends */
702 #define MAX_EXPECTED_PDU_LENGTH 2048
704 typedef struct LastFrameData {
708 nstime_t received_time;
710 guint8 data[MAX_EXPECTED_PDU_LENGTH];
713 typedef struct DLHarqBuffers {
714 LastFrameData harqid[2][15]; /* 2 blocks (1 for each antenna) needed for DL */
718 /* This table stores (RNTI -> DLHARQBuffers*). Will be populated when
719 DL frames are first read. */
720 static GHashTable *mac_lte_dl_harq_hash = NULL;
722 typedef struct DLHARQResult {
723 guint previousFrameNum;
724 guint timeSincePreviousFrame;
728 /* This table stores (FrameNumber -> *DLHARQResult). It is assigned during the first
729 pass and used thereafter */
730 static GHashTable *mac_lte_dl_harq_result_hash = NULL;
732 /**************************************************************************/
735 /*****************************************************************/
736 /* Keeping track of last UL frames per C-RNTI so can verify when */
737 /* told that a frame is a retx */
739 typedef struct ULHarqBuffers {
740 LastFrameData harqid[8];
744 /* This table stores (RNTI -> ULHarqBuffers*). Will be populated when
745 UL frames are first read. */
746 static GHashTable *mac_lte_ul_harq_hash = NULL;
748 typedef struct ULHARQResult {
749 guint previousFrameNum;
750 guint timeSincePreviousFrame;
754 /* This table stores (CRFrameNum -> ULHARQResult). It is assigned during the first
755 pass and used thereafter */
756 static GHashTable *mac_lte_ul_harq_result_hash = NULL;
758 /**************************************************************************/
761 /**************************************************************************/
762 /* Tracking of Scheduling Requests (SRs). */
764 /* - last grant before SR */
765 /* - SR failures following request */
766 /* - grant following SR */
768 typedef enum SREvent {
774 static const value_string sr_event_vals[] =
776 { SR_Grant, "Grant"},
777 { SR_Request, "SR Request"},
778 { SR_Failure, "SR Failure"},
782 typedef enum SRStatus {
788 static const value_string sr_status_vals[] =
790 { None, "Receiving grants"},
791 { SR_Outstanding, "SR Request outstanding"},
792 { SR_Failed, "SR has Failed"},
797 typedef struct SRState {
799 guint32 lastSRFramenum;
800 guint32 lastGrantFramenum;
801 nstime_t requestTime;
805 /* This table keeps track of the SR state for each UE.
807 static GHashTable *mac_lte_ue_sr_state = NULL;
810 typedef enum SRResultType {
819 typedef struct SRResult {
822 guint32 timeDifference;
824 /* These 2 are only used with InvalidSREvent */
829 /* Entries in this table are created during the first pass
830 It maps (SRFrameNum -> SRResult) */
831 static GHashTable *mac_lte_sr_request_hash = NULL;
834 /**************************************************************************/
838 /* Forward declarations */
839 void proto_reg_handoff_mac_lte(void);
840 void dissect_mac_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
843 /* Heuristic dissection */
844 static gboolean global_mac_lte_heur = FALSE;
846 static void call_with_catch_all(dissector_handle_t handle, tvbuff_t* tvb, packet_info *pinfo, proto_tree *tree)
848 /* Call it (catch exceptions so that stats will be updated) */
850 call_dissector_only(handle, tvb, pinfo, tree);
857 /* Heuristic dissector looks for supported framing protocol (see wiki page) */
858 static gboolean dissect_mac_lte_heur(tvbuff_t *tvb, packet_info *pinfo,
862 struct mac_lte_info *p_mac_lte_info;
865 gboolean infoAlreadySet = FALSE;
867 /* This is a heuristic dissector, which means we get all the UDP
868 * traffic not sent to a known dissector and not claimed by
869 * a heuristic dissector called before us!
872 if (!global_mac_lte_heur) {
876 /* Do this again on re-dissection to re-discover offset of actual PDU */
878 /* Needs to be at least as long as:
879 - the signature string
882 - at least one byte of MAC PDU payload */
883 if ((size_t)tvb_length_remaining(tvb, offset) < (strlen(MAC_LTE_START_STRING)+3+2)) {
887 /* OK, compare with signature string */
888 if (tvb_strneql(tvb, offset, MAC_LTE_START_STRING, strlen(MAC_LTE_START_STRING)) != 0) {
891 offset += (gint)strlen(MAC_LTE_START_STRING);
893 /* If redissecting, use previous info struct (if available) */
894 p_mac_lte_info = p_get_proto_data(pinfo->fd, proto_mac_lte);
895 if (p_mac_lte_info == NULL) {
896 /* Allocate new info struct for this frame */
897 p_mac_lte_info = se_alloc0(sizeof(struct mac_lte_info));
898 infoAlreadySet = FALSE;
901 infoAlreadySet = TRUE;
905 /* Read fixed fields */
906 p_mac_lte_info->radioType = tvb_get_guint8(tvb, offset++);
907 p_mac_lte_info->direction = tvb_get_guint8(tvb, offset++);
909 /* TODO: add this info to framing protocol */
910 if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
911 p_mac_lte_info->detailed_phy_info.ul_info.present = FALSE;
914 p_mac_lte_info->detailed_phy_info.dl_info.present = FALSE;
917 p_mac_lte_info->rntiType = tvb_get_guint8(tvb, offset++);
919 /* Initialize RNTI with a default value in case optional field is not present */
920 switch (p_mac_lte_info->rntiType) {
922 p_mac_lte_info->rnti = 0xFFFE;
925 p_mac_lte_info->rnti = 0xFFFF;
930 p_mac_lte_info->rnti = 0x0001;
936 /* Read optional fields */
937 while (tag != MAC_LTE_PAYLOAD_TAG) {
938 /* Process next tag */
939 tag = tvb_get_guint8(tvb, offset++);
941 case MAC_LTE_RNTI_TAG:
942 p_mac_lte_info->rnti = tvb_get_ntohs(tvb, offset);
945 case MAC_LTE_UEID_TAG:
946 p_mac_lte_info->ueid = tvb_get_ntohs(tvb, offset);
949 case MAC_LTE_SUBFRAME_TAG:
950 p_mac_lte_info->subframeNumber = tvb_get_ntohs(tvb, offset);
953 case MAC_LTE_PREDFINED_DATA_TAG:
954 p_mac_lte_info->isPredefinedData = tvb_get_guint8(tvb, offset);
957 case MAC_LTE_RETX_TAG:
958 p_mac_lte_info->reTxCount = tvb_get_guint8(tvb, offset);
961 case MAC_LTE_CRC_STATUS_TAG:
962 p_mac_lte_info->crcStatusValid = TRUE;
963 p_mac_lte_info->detailed_phy_info.dl_info.crc_status = tvb_get_guint8(tvb, offset);
967 case MAC_LTE_PAYLOAD_TAG:
968 /* Have reached data, so set payload length and get out of loop */
969 p_mac_lte_info->length= tvb_length_remaining(tvb, offset);
973 /* It must be a recognised tag */
978 if (!infoAlreadySet) {
979 /* Store info in packet */
980 p_add_proto_data(pinfo->fd, proto_mac_lte, p_mac_lte_info);
983 /**************************************/
984 /* OK, now dissect as MAC LTE */
986 /* Create tvb that starts at actual MAC PDU */
987 mac_tvb = tvb_new_subset(tvb, offset, -1, tvb_reported_length(tvb)-offset);
988 dissect_mac_lte(mac_tvb, pinfo, tree);
994 /* Write the given formatted text to:
995 - the info column (if pinfo != NULL)
996 - 1 or 2 other labels (optional)
998 static void write_pdu_label_and_info(proto_item *ti1, proto_item *ti2,
999 packet_info *pinfo, const char *format, ...)
1001 #define MAX_INFO_BUFFER 256
1002 static char info_buffer[MAX_INFO_BUFFER];
1006 va_start(ap, format);
1007 g_vsnprintf(info_buffer, MAX_INFO_BUFFER, format, ap);
1010 /* Add to indicated places */
1011 if (pinfo != NULL) {
1012 col_append_str(pinfo->cinfo, COL_INFO, info_buffer);
1015 proto_item_append_text(ti1, "%s", info_buffer);
1018 proto_item_append_text(ti2, "%s", info_buffer);
1022 /* Show extra PHY parameters (if present) */
1023 static void show_extra_phy_parameters(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree,
1024 struct mac_lte_info *p_mac_lte_info)
1027 proto_tree *phy_tree;
1030 if (global_mac_lte_layer_to_show == ShowPHYLayer) {
1031 /* Clear the info column */
1032 col_clear(pinfo->cinfo, COL_INFO);
1035 if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
1036 if (p_mac_lte_info->detailed_phy_info.ul_info.present) {
1039 phy_ti = proto_tree_add_string_format(tree, hf_mac_lte_context_phy_ul,
1040 tvb, 0, 0, "", "UL PHY Context");
1041 phy_tree = proto_item_add_subtree(phy_ti, ett_mac_lte_phy_context);
1042 PROTO_ITEM_SET_GENERATED(phy_ti);
1045 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_modulation_type,
1047 p_mac_lte_info->detailed_phy_info.ul_info.modulation_type);
1048 PROTO_ITEM_SET_GENERATED(ti);
1050 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_tbs_index,
1052 p_mac_lte_info->detailed_phy_info.ul_info.tbs_index);
1053 PROTO_ITEM_SET_GENERATED(ti);
1055 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_resource_block_length,
1057 p_mac_lte_info->detailed_phy_info.ul_info.resource_block_length);
1058 PROTO_ITEM_SET_GENERATED(ti);
1060 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_resource_block_start,
1062 p_mac_lte_info->detailed_phy_info.ul_info.resource_block_start);
1063 PROTO_ITEM_SET_GENERATED(ti);
1065 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_harq_id,
1067 p_mac_lte_info->detailed_phy_info.ul_info.harq_id);
1068 PROTO_ITEM_SET_GENERATED(ti);
1070 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_ndi,
1072 p_mac_lte_info->detailed_phy_info.ul_info.ndi);
1073 PROTO_ITEM_SET_GENERATED(ti);
1076 proto_item_append_text(phy_ti, " (");
1078 write_pdu_label_and_info(phy_ti, NULL,
1079 (global_mac_lte_layer_to_show == ShowPHYLayer) ? pinfo : NULL,
1080 "UL: UEId=%u RNTI=%u %s Tbs_Index=%u RB_len=%u RB_start=%u",
1081 p_mac_lte_info->ueid,
1082 p_mac_lte_info->rnti,
1083 val_to_str_const(p_mac_lte_info->detailed_phy_info.ul_info.modulation_type,
1084 modulation_type_vals, "Unknown"),
1085 p_mac_lte_info->detailed_phy_info.ul_info.tbs_index,
1086 p_mac_lte_info->detailed_phy_info.ul_info.resource_block_length,
1087 p_mac_lte_info->detailed_phy_info.ul_info.resource_block_start);
1089 proto_item_append_text(phy_ti, ")");
1091 /* Don't want columns to be replaced now */
1092 if (global_mac_lte_layer_to_show == ShowPHYLayer) {
1093 col_set_writable(pinfo->cinfo, FALSE);
1098 if (p_mac_lte_info->detailed_phy_info.dl_info.present) {
1101 phy_ti = proto_tree_add_string_format(tree, hf_mac_lte_context_phy_dl,
1102 tvb, 0, 0, "", "DL PHY Context");
1103 phy_tree = proto_item_add_subtree(phy_ti, ett_mac_lte_phy_context);
1104 PROTO_ITEM_SET_GENERATED(phy_ti);
1107 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_dci_format,
1109 p_mac_lte_info->detailed_phy_info.dl_info.dci_format);
1110 PROTO_ITEM_SET_GENERATED(ti);
1112 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_resource_allocation_type,
1114 p_mac_lte_info->detailed_phy_info.dl_info.resource_allocation_type);
1115 PROTO_ITEM_SET_GENERATED(ti);
1117 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_aggregation_level,
1119 p_mac_lte_info->detailed_phy_info.dl_info.aggregation_level);
1120 PROTO_ITEM_SET_GENERATED(ti);
1122 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_mcs_index,
1124 p_mac_lte_info->detailed_phy_info.dl_info.mcs_index);
1125 PROTO_ITEM_SET_GENERATED(ti);
1127 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_redundancy_version_index,
1129 p_mac_lte_info->detailed_phy_info.dl_info.redundancy_version_index);
1130 PROTO_ITEM_SET_GENERATED(ti);
1132 ti = proto_tree_add_boolean(phy_tree, hf_mac_lte_context_phy_dl_retx,
1134 p_mac_lte_info->dl_retx);
1135 PROTO_ITEM_SET_GENERATED(ti);
1137 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_resource_block_length,
1139 p_mac_lte_info->detailed_phy_info.dl_info.resource_block_length);
1140 PROTO_ITEM_SET_GENERATED(ti);
1142 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_crc_status,
1144 p_mac_lte_info->detailed_phy_info.dl_info.crc_status);
1145 PROTO_ITEM_SET_GENERATED(ti);
1147 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_harq_id,
1149 p_mac_lte_info->detailed_phy_info.dl_info.harq_id);
1150 PROTO_ITEM_SET_GENERATED(ti);
1152 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_ndi,
1154 p_mac_lte_info->detailed_phy_info.dl_info.ndi);
1155 PROTO_ITEM_SET_GENERATED(ti);
1157 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_tb,
1159 p_mac_lte_info->detailed_phy_info.dl_info.transport_block);
1160 PROTO_ITEM_SET_GENERATED(ti);
1163 proto_item_append_text(phy_ti, " (");
1165 write_pdu_label_and_info(phy_ti, NULL,
1166 (global_mac_lte_layer_to_show == ShowPHYLayer) ? pinfo : NULL,
1167 "DL: UEId=%u RNTI=%u DCI_Format=%s Res_Alloc=%u Aggr_Level=%s MCS=%u RV=%u "
1168 "Res_Block_len=%u CRC_status=%s HARQ_id=%u NDI=%u",
1169 p_mac_lte_info->ueid,
1170 p_mac_lte_info->rnti,
1171 val_to_str_const(p_mac_lte_info->detailed_phy_info.dl_info.dci_format,
1172 dci_format_vals, "Unknown"),
1173 p_mac_lte_info->detailed_phy_info.dl_info.resource_allocation_type,
1174 val_to_str_const(p_mac_lte_info->detailed_phy_info.dl_info.aggregation_level,
1175 aggregation_level_vals, "Unknown"),
1176 p_mac_lte_info->detailed_phy_info.dl_info.mcs_index,
1177 p_mac_lte_info->detailed_phy_info.dl_info.redundancy_version_index,
1178 p_mac_lte_info->detailed_phy_info.dl_info.resource_block_length,
1179 val_to_str_const(p_mac_lte_info->detailed_phy_info.dl_info.crc_status,
1180 crc_status_vals, "Unknown"),
1181 p_mac_lte_info->detailed_phy_info.dl_info.harq_id,
1182 p_mac_lte_info->detailed_phy_info.dl_info.ndi);
1183 proto_item_append_text(phy_ti, ")");
1185 /* Don't want columns to be replaced now */
1186 if (global_mac_lte_layer_to_show == ShowPHYLayer) {
1187 col_set_writable(pinfo->cinfo, FALSE);
1194 /* Dissect a single Random Access Reponse body */
1195 static gint dissect_rar_entry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1197 gint offset, guint8 rapid)
1200 guint start_body_offset = offset;
1202 proto_item *rar_body_ti;
1203 proto_tree *rar_body_tree;
1204 proto_tree *ul_grant_tree;
1205 proto_item *ul_grant_ti;
1206 guint16 timing_advance;
1210 /* Create tree for this Body */
1211 rar_body_ti = proto_tree_add_item(tree,
1212 hf_mac_lte_rar_body,
1213 tvb, offset, 0, FALSE);
1214 rar_body_tree = proto_item_add_subtree(rar_body_ti, ett_mac_lte_rar_body);
1216 /* Dissect an RAR entry */
1218 /* Check reserved bit */
1219 reserved = (tvb_get_guint8(tvb, offset) & 0x80) >> 7;
1220 ti = proto_tree_add_item(rar_body_tree, hf_mac_lte_rar_reserved2, tvb, offset, 1, FALSE);
1221 if (reserved != 0) {
1222 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
1223 "RAR body Reserved bit not zero (found 0x%x)", reserved);
1226 /* Timing Advance */
1227 timing_advance = (tvb_get_ntohs(tvb, offset) & 0x7ff0) >> 4;
1228 ti = proto_tree_add_item(rar_body_tree, hf_mac_lte_rar_ta, tvb, offset, 2, FALSE);
1229 if (timing_advance != 0) {
1230 expert_add_info_format(pinfo, ti, PI_SEQUENCE, (timing_advance <= 31) ? PI_NOTE : PI_WARN,
1231 "RAR Timing advance not zero (%u)", timing_advance);
1236 ul_grant = (tvb_get_ntohl(tvb, offset) & 0x0fffff00) >> 8;
1237 ul_grant_ti = proto_tree_add_item(rar_body_tree, hf_mac_lte_rar_ul_grant, tvb, offset, 3, FALSE);
1239 /* Break these 20 bits down as described in 36.213, section 6.2 */
1240 /* Create subtree for UL grant break-down */
1241 ul_grant_tree = proto_item_add_subtree(ul_grant_ti, ett_mac_lte_rar_ul_grant);
1243 /* Hopping flag (1 bit) */
1244 proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_hopping,
1245 tvb, offset, 1, FALSE);
1247 /* Fixed sized resource block assignment (10 bits) */
1248 proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_fsrba,
1249 tvb, offset, 2, FALSE);
1251 /* Truncated Modulation and coding scheme (4 bits) */
1252 proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_tmcs,
1253 tvb, offset+1, 2, FALSE);
1255 /* TPC command for scheduled PUSCH (3 bits) */
1256 proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_tcsp,
1257 tvb, offset+2, 1, FALSE);
1259 /* UL delay (1 bit) */
1260 proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_ul_delay,
1261 tvb, offset+2, 1, FALSE);
1263 /* CQI request (1 bit) */
1264 proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_cqi_request,
1265 tvb, offset+2, 1, FALSE);
1269 /* Temporary C-RNTI */
1270 temp_crnti = tvb_get_ntohs(tvb, offset);
1271 proto_tree_add_item(rar_body_tree, hf_mac_lte_rar_temporary_crnti, tvb, offset, 2, FALSE);
1274 write_pdu_label_and_info(pdu_ti, rar_body_ti, pinfo,
1275 "(RAPID=%u: TA=%u, UL-Grant=%u, Temp C-RNTI=%u) ",
1276 rapid, timing_advance, ul_grant, temp_crnti);
1278 proto_item_set_len(rar_body_ti, offset-start_body_offset);
1284 #define MAX_RAR_PDUS 64
1285 /* Dissect Random Access Reponse (RAR) PDU */
1286 static void dissect_rar(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *pdu_ti,
1287 gint offset, mac_lte_info *p_mac_lte_info, mac_lte_tap_info *tap_info)
1289 gint number_of_rars = 0; /* No of RAR bodies expected following headers */
1290 guint8 *rapids = ep_alloc(MAX_RAR_PDUS * sizeof(guint8));
1291 gboolean backoff_indicator_seen = FALSE;
1292 guint8 backoff_indicator = 0;
1295 proto_tree *rar_headers_tree;
1297 proto_item *rar_headers_ti;
1298 proto_item *padding_length_ti;
1299 int start_headers_offset = offset;
1301 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
1302 "RAR (RA-RNTI=%u, SF=%u) ",
1303 p_mac_lte_info->rnti, p_mac_lte_info->subframeNumber);
1305 /* Create hidden 'virtual root' so can filter on mac-lte.rar */
1306 ti = proto_tree_add_item(tree, hf_mac_lte_rar, tvb, offset, -1, FALSE);
1307 PROTO_ITEM_SET_HIDDEN(ti);
1309 /* Create headers tree */
1310 rar_headers_ti = proto_tree_add_item(tree,
1311 hf_mac_lte_rar_headers,
1312 tvb, offset, 0, FALSE);
1313 rar_headers_tree = proto_item_add_subtree(rar_headers_ti, ett_mac_lte_rar_headers);
1316 /***************************/
1317 /* Read the header entries */
1319 int start_header_offset = offset;
1320 proto_tree *rar_header_tree;
1321 proto_item *rar_header_ti;
1323 guint8 first_byte = tvb_get_guint8(tvb, offset);
1325 /* Create tree for this header */
1326 rar_header_ti = proto_tree_add_item(rar_headers_tree,
1327 hf_mac_lte_rar_header,
1328 tvb, offset, 0, FALSE);
1329 rar_header_tree = proto_item_add_subtree(rar_header_ti, ett_mac_lte_rar_header);
1332 extension = (first_byte & 0x80) >> 7;
1333 proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_extension, tvb, offset, 1, FALSE);
1336 type_value = (first_byte & 0x40) >> 6;
1337 proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_t, tvb, offset, 1, FALSE);
1339 if (type_value == 0) {
1340 /* Backoff Indicator (BI) case */
1346 /* 2 Reserved bits */
1347 reserved = (tvb_get_guint8(tvb, offset) & 0x30) >> 4;
1348 tii = proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_reserved, tvb, offset, 1, FALSE);
1349 if (reserved != 0) {
1350 expert_add_info_format(pinfo, tii, PI_MALFORMED, PI_ERROR,
1351 "RAR header Reserved bits not zero (found 0x%x)", reserved);
1354 /* Backoff Indicator */
1355 backoff_indicator = tvb_get_guint8(tvb, offset) & 0x0f;
1356 bi_ti = proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_bi, tvb, offset, 1, FALSE);
1358 /* As of March 2009 spec, it must be first, and may only appear once */
1359 if (backoff_indicator_seen) {
1360 expert_add_info_format(pinfo, bi_ti, PI_MALFORMED, PI_ERROR,
1361 "MAC RAR PDU has > 1 Backoff Indicator subheader present");
1363 backoff_indicator_seen = TRUE;
1365 write_pdu_label_and_info(pdu_ti, rar_header_ti, pinfo,
1366 "(Backoff Indicator=%sms)",
1367 val_to_str_const(backoff_indicator, rar_bi_vals, "Illegal-value "));
1369 /* If present, it must be the first subheader */
1370 if (number_of_rars > 0) {
1371 expert_add_info_format(pinfo, bi_ti, PI_MALFORMED, PI_WARN,
1372 "Backoff Indicator must appear as first subheader");
1378 /* TODO: complain if the same RAPID appears twice in same frame? */
1379 rapids[number_of_rars] = tvb_get_guint8(tvb, offset) & 0x3f;
1380 proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_rapid, tvb, offset, 1, FALSE);
1382 proto_item_append_text(rar_header_ti, "(RAPID=%u)", rapids[number_of_rars]);
1389 /* Finalise length of header tree selection */
1390 proto_item_set_len(rar_header_ti, offset - start_header_offset);
1392 } while (extension && number_of_rars < MAX_RAR_PDUS);
1394 /* Append summary to headers root */
1395 proto_item_append_text(rar_headers_ti, " (%u RARs", number_of_rars);
1396 if (backoff_indicator_seen) {
1397 proto_item_append_text(rar_headers_ti, ", BI=%sms)",
1398 val_to_str_const(backoff_indicator, rar_bi_vals, "Illegal-value "));
1401 proto_item_append_text(rar_headers_ti, ")");
1404 /* Set length for headers root */
1405 proto_item_set_len(rar_headers_ti, offset-start_headers_offset);
1408 /***************************/
1409 /* Read any indicated RARs */
1410 for (n=0; n < number_of_rars; n++) {
1411 offset = dissect_rar_entry(tvb, pinfo, tree, pdu_ti, offset, rapids[n]);
1414 /* Update TAP info */
1415 tap_info->number_of_rars += number_of_rars;
1417 /* Padding may follow */
1418 if (tvb_length_remaining(tvb, offset) > 0) {
1419 proto_tree_add_item(tree, hf_mac_lte_padding_data,
1420 tvb, offset, -1, FALSE);
1422 padding_length_ti = proto_tree_add_int(tree, hf_mac_lte_padding_length,
1424 p_mac_lte_info->length - offset);
1425 PROTO_ITEM_SET_GENERATED(padding_length_ti);
1427 /* Update padding bytes in stats */
1428 tap_info->padding_bytes += (p_mac_lte_info->length - offset);
1432 /* Dissect BCH PDU */
1433 static void dissect_bch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1435 int offset, mac_lte_info *p_mac_lte_info)
1439 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
1440 "BCH PDU (%u bytes, on %s transport) ",
1441 tvb_length_remaining(tvb, offset),
1442 val_to_str_const(p_mac_lte_info->rntiType,
1443 bch_transport_channel_vals,
1446 /* Show which transport layer it came in on (inferred from RNTI type) */
1447 ti = proto_tree_add_uint(tree, hf_mac_lte_context_bch_transport_channel,
1448 tvb, offset, 0, p_mac_lte_info->rntiType);
1449 PROTO_ITEM_SET_GENERATED(ti);
1451 /****************************************/
1452 /* Whole frame is BCH data */
1455 ti = proto_tree_add_item(tree, hf_mac_lte_bch_pdu,
1456 tvb, offset, -1, FALSE);
1458 if (global_mac_lte_attempt_rrc_decode) {
1459 /* Attempt to decode payload using LTE RRC dissector */
1460 tvbuff_t *rrc_tvb = tvb_new_subset(tvb, offset, -1, tvb_length_remaining(tvb, offset));
1462 /* Get appropriate dissector handle */
1463 dissector_handle_t protocol_handle = 0;
1464 if (p_mac_lte_info->rntiType == SI_RNTI) {
1465 protocol_handle = find_dissector("lte-rrc.bcch.dl.sch");
1468 protocol_handle = find_dissector("lte-rrc.bcch.bch");
1471 /* Hide raw view of bytes */
1472 PROTO_ITEM_SET_HIDDEN(ti);
1474 call_with_catch_all(protocol_handle, rrc_tvb, pinfo, tree);
1477 /* Check that this *is* downlink! */
1478 if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
1479 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
1480 "BCH data should not be received in Uplink!");
1485 /* Dissect PCH PDU */
1486 static void dissect_pch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1487 proto_item *pdu_ti, int offset, guint8 direction)
1491 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
1492 "PCH PDU (%u bytes) ",
1493 tvb_length_remaining(tvb, offset));
1495 /****************************************/
1496 /* Whole frame is PCH data */
1498 /* Always show as raw data */
1499 ti = proto_tree_add_item(tree, hf_mac_lte_pch_pdu,
1500 tvb, offset, -1, FALSE);
1502 if (global_mac_lte_attempt_rrc_decode) {
1504 /* Attempt to decode payload using LTE RRC dissector */
1505 tvbuff_t *rrc_tvb = tvb_new_subset(tvb, offset, -1, tvb_length_remaining(tvb, offset));
1507 /* Get appropriate dissector handle */
1508 dissector_handle_t protocol_handle = find_dissector("lte-rrc.pcch");
1510 /* Hide raw view of bytes */
1511 PROTO_ITEM_SET_HIDDEN(ti);
1513 /* Call it (catch exceptions so that stats will be updated) */
1515 call_dissector_only(protocol_handle, rrc_tvb, pinfo, tree);
1522 /* Check that this *is* downlink! */
1523 if (direction == DIRECTION_UPLINK) {
1524 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
1525 "PCH data should not be received in Uplink!");
1530 /* Does this header entry correspond to a fixed-sized control element? */
1531 static int is_fixed_sized_control_element(guint8 lcid, guint8 direction)
1533 if (direction == DIRECTION_UPLINK) {
1536 case POWER_HEADROOM_REPORT_LCID:
1538 case TRUNCATED_BSR_LCID:
1539 case SHORT_BSR_LCID:
1548 /* Assume Downlink */
1550 case UE_CONTENTION_RESOLUTION_IDENTITY_LCID:
1551 case TIMING_ADVANCE_LCID:
1552 case DRX_COMMAND_LCID:
1562 /* Is this a BSR report header? */
1563 static int is_bsr_lcid(guint8 lcid)
1565 return ((lcid == TRUNCATED_BSR_LCID) ||
1566 (lcid == SHORT_BSR_LCID) ||
1567 (lcid == LONG_BSR_LCID));
1571 /* Helper function to call RLC dissector for SDUs (where channel params are known) */
1572 static void call_rlc_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1574 int offset, guint16 data_length,
1575 guint8 mode, guint8 direction, guint16 ueid,
1576 guint16 channelType, guint16 channelId,
1577 guint8 UMSequenceNumberLength)
1579 tvbuff_t *srb_tvb = tvb_new_subset(tvb, offset, data_length, data_length);
1580 struct rlc_lte_info *p_rlc_lte_info;
1582 /* Get RLC dissector handle */
1583 volatile dissector_handle_t protocol_handle = find_dissector("rlc-lte");
1585 /* Resuse or create RLC info */
1586 p_rlc_lte_info = p_get_proto_data(pinfo->fd, proto_rlc_lte);
1587 if (p_rlc_lte_info == NULL) {
1588 p_rlc_lte_info = se_alloc0(sizeof(struct rlc_lte_info));
1591 /* Fill in struct details for srb channels */
1592 p_rlc_lte_info->rlcMode = mode;
1593 p_rlc_lte_info->direction = direction;
1594 p_rlc_lte_info->priority = 0; /* ?? */
1595 p_rlc_lte_info->ueid = ueid;
1596 p_rlc_lte_info->channelType = channelType;
1597 p_rlc_lte_info->channelId = channelId;
1598 p_rlc_lte_info->pduLength = data_length;
1599 p_rlc_lte_info->UMSequenceNumberLength = UMSequenceNumberLength;
1601 /* Store info in packet */
1602 p_add_proto_data(pinfo->fd, proto_rlc_lte, p_rlc_lte_info);
1604 if (global_mac_lte_layer_to_show != ShowRLCLayer) {
1605 /* Don't want these columns replaced */
1606 col_set_writable(pinfo->cinfo, FALSE);
1609 /* Clear info column before first RLC PDU */
1610 if (s_number_of_rlc_pdus_shown == 0) {
1611 col_clear(pinfo->cinfo, COL_INFO);
1614 /* Add a separator and protect column contents here */
1615 write_pdu_label_and_info(pdu_ti, NULL, pinfo, " || ");
1616 col_set_fence(pinfo->cinfo, COL_INFO);
1619 s_number_of_rlc_pdus_shown++;
1621 /* Call it (catch exceptions so that stats will be updated) */
1623 call_dissector_only(protocol_handle, srb_tvb, pinfo, tree);
1629 col_set_writable(pinfo->cinfo, TRUE);
1633 /* For DL frames, look for previous Tx. Add link back if found */
1634 static void TrackReportedDLHARQResend(packet_info *pinfo, tvbuff_t *tvb, volatile int length,
1635 proto_tree *tree, mac_lte_info *p_mac_lte_info)
1637 DLHARQResult *result = NULL;
1639 /* If don't have detailed DL PHy info, just give up */
1640 if (!p_mac_lte_info->detailed_phy_info.dl_info.present) {
1644 /* TDD may not work... */
1646 if (!pinfo->fd->flags.visited) {
1647 /* First time, so set result and update DL harq table */
1648 LastFrameData *lastData = NULL;
1649 LastFrameData *thisData = NULL;
1651 DLHarqBuffers *ueData;
1653 /* Read these for convenience */
1654 guint8 harq_id = p_mac_lte_info->detailed_phy_info.dl_info.harq_id;
1655 guint8 transport_block = p_mac_lte_info->detailed_phy_info.dl_info.transport_block;
1657 /* Check harq-id bounds, give up if invalid */
1658 if ((harq_id >= 15) || (transport_block+1 > 2)) {
1662 /* Look up entry for this UE/RNTI */
1663 ueData = g_hash_table_lookup(mac_lte_dl_harq_hash, GUINT_TO_POINTER((guint)p_mac_lte_info->rnti));
1665 if (ueData != NULL) {
1666 /* Get previous info for this harq-id */
1667 lastData = &(ueData->harqid[transport_block][harq_id]);
1668 if (lastData->inUse) {
1669 /* Compare time difference, ndi, data to see if this looks like a retx */
1670 if ((length == lastData->length) &&
1671 (p_mac_lte_info->detailed_phy_info.dl_info.ndi == lastData->ndi) &&
1672 tvb_memeql(tvb, 0, lastData->data, MIN(lastData->length, MAX_EXPECTED_PDU_LENGTH)) == 0) {
1674 /* Work out gap between frames */
1675 gint seconds_between_packets = (gint)
1676 (pinfo->fd->abs_ts.secs - lastData->received_time.secs);
1677 gint nseconds_between_packets =
1678 pinfo->fd->abs_ts.nsecs - lastData->received_time.nsecs;
1680 /* Round difference to nearest millisecond */
1681 gint total_gap = (seconds_between_packets*1000) +
1682 ((nseconds_between_packets+500000) / 1000000);
1684 /* Expect to be within (say) 8-13 subframes since previous */
1685 if ((total_gap >= 8) && (total_gap <= 13)) {
1686 /* Resend detected! Store result */
1687 result = se_alloc(sizeof(DLHARQResult));
1688 result->previousFrameNum = lastData->framenum;
1689 result->timeSincePreviousFrame = total_gap;
1690 g_hash_table_insert(mac_lte_dl_harq_result_hash, GUINT_TO_POINTER(pinfo->fd->num), result);
1696 /* Allocate entry in table for this UE/RNTI */
1697 ueData = se_alloc0(sizeof(DLHarqBuffers));
1698 g_hash_table_insert(mac_lte_dl_harq_hash, GUINT_TO_POINTER((guint)p_mac_lte_info->rnti), ueData);
1701 /* Store this frame's details in table */
1702 thisData = &(ueData->harqid[transport_block][harq_id]);
1703 thisData->inUse = TRUE;
1704 thisData->length = length;
1705 tvb_memcpy(tvb, thisData->data, 0, MIN(thisData->length, MAX_EXPECTED_PDU_LENGTH));
1706 thisData->ndi = p_mac_lte_info->detailed_phy_info.dl_info.ndi;
1707 thisData->framenum = pinfo->fd->num;
1708 thisData->received_time = pinfo->fd->abs_ts;
1711 /* Not first time, so just set whats already stored in result */
1712 result = g_hash_table_lookup(mac_lte_dl_harq_result_hash, GUINT_TO_POINTER(pinfo->fd->num));
1716 /***************************************************/
1717 /* Show link back to original frame (if available) */
1718 if (result != NULL) {
1720 proto_item *original_ti = proto_tree_add_uint(tree, hf_mac_lte_suspected_dl_retx_original_frame,
1721 tvb, 0, 0, result->previousFrameNum);
1722 PROTO_ITEM_SET_GENERATED(original_ti);
1724 gap_ti = proto_tree_add_uint(tree, hf_mac_lte_suspected_dl_retx_time_since_previous_frame,
1725 tvb, 0, 0, result->timeSincePreviousFrame);
1726 PROTO_ITEM_SET_GENERATED(gap_ti);
1732 /* Return TRUE if the given packet is thought to be a retx */
1733 int is_mac_lte_frame_retx(packet_info *pinfo, guint8 direction)
1735 if (direction == DIRECTION_UPLINK) {
1736 /* For UL, retx count is stored in per-packet struct */
1737 struct mac_lte_info *p_mac_lte_info = p_get_proto_data(pinfo->fd, proto_mac_lte);
1738 return ((p_mac_lte_info != NULL) && (p_mac_lte_info->reTxCount > 0));
1741 /* For DL, must consult result table */
1742 return (g_hash_table_lookup(mac_lte_dl_harq_result_hash, GUINT_TO_POINTER(pinfo->fd->num)) != NULL);
1747 /* Track UL frames, so that when a retx is indicated, we can search for
1748 the original tx. We will either find it, and provide a link back to it,
1749 or flag that we couldn't find as an expert error */
1750 static void TrackReportedULHARQResend(packet_info *pinfo, tvbuff_t *tvb, volatile int offset,
1751 proto_tree *tree, mac_lte_info *p_mac_lte_info,
1752 proto_item *retx_ti)
1754 ULHARQResult *result = NULL;
1756 /* If don't have detailed DL PHY info, just give up */
1757 if (!p_mac_lte_info->detailed_phy_info.ul_info.present) {
1761 /* Give up if harqid is out of range */
1762 if (p_mac_lte_info->detailed_phy_info.ul_info.harq_id >= 8) {
1766 if (!pinfo->fd->flags.visited) {
1767 /* First time, so set result and update UL harq table */
1768 LastFrameData *lastData = NULL;
1769 LastFrameData *thisData = NULL;
1771 /* Look up entry for this UE/RNTI */
1772 ULHarqBuffers *ueData =
1773 g_hash_table_lookup(mac_lte_ul_harq_hash, GUINT_TO_POINTER((guint)p_mac_lte_info->rnti));
1774 if (ueData != NULL) {
1775 if (p_mac_lte_info->reTxCount >= 1) {
1776 /* Looking for frame previously on this harq-id */
1777 lastData = &(ueData->harqid[p_mac_lte_info->detailed_phy_info.ul_info.harq_id]);
1778 if (lastData->inUse) {
1779 /* Compare time, sf, data to see if this looks like a retx */
1780 if ((tvb_length_remaining(tvb, offset) == lastData->length) &&
1781 (p_mac_lte_info->detailed_phy_info.ul_info.ndi == lastData->ndi) &&
1782 tvb_memeql(tvb, offset, lastData->data, MIN(lastData->length, MAX_EXPECTED_PDU_LENGTH)) == 0) {
1784 /* Work out gap between frames */
1785 gint seconds_between_packets = (gint)
1786 (pinfo->fd->abs_ts.secs - lastData->received_time.secs);
1787 gint nseconds_between_packets =
1788 pinfo->fd->abs_ts.nsecs - lastData->received_time.nsecs;
1790 /* Round to nearest ms */
1791 gint total_gap = (seconds_between_packets*1000) +
1792 ((nseconds_between_packets+500000) / 1000000);
1794 /* Could be as many as max-tx (which we don't know) * 8ms ago.
1795 32 is the most I've seen... */
1796 if (total_gap <= 33) {
1798 /* Original detected!!! Store result */
1799 result = se_alloc(sizeof(ULHARQResult));
1800 result->previousFrameNum = lastData->framenum;
1801 result->timeSincePreviousFrame = total_gap;
1802 g_hash_table_insert(mac_lte_ul_harq_result_hash, GUINT_TO_POINTER(pinfo->fd->num), result);
1809 /* Allocate entry in table for this UE/RNTI */
1810 ueData = se_alloc0(sizeof(ULHarqBuffers));
1811 g_hash_table_insert(mac_lte_ul_harq_hash, GUINT_TO_POINTER((guint)p_mac_lte_info->rnti), ueData);
1814 /* Store this frame's details in table */
1815 thisData = &(ueData->harqid[p_mac_lte_info->detailed_phy_info.ul_info.harq_id]);
1816 thisData->inUse = TRUE;
1817 thisData->length = tvb_length_remaining(tvb, offset);
1818 tvb_memcpy(tvb, thisData->data, offset, MIN(thisData->length, MAX_EXPECTED_PDU_LENGTH));
1819 thisData->ndi = p_mac_lte_info->detailed_phy_info.ul_info.ndi;
1820 thisData->framenum = pinfo->fd->num;
1821 thisData->received_time = pinfo->fd->abs_ts;
1824 /* Not first time, so just set whats already stored in result */
1825 result = g_hash_table_lookup(mac_lte_ul_harq_result_hash, GUINT_TO_POINTER(pinfo->fd->num));
1828 if (retx_ti != NULL) {
1829 if (result != NULL) {
1830 proto_item *original_ti, *gap_ti;
1832 original_ti = proto_tree_add_uint(tree, hf_mac_lte_ul_harq_resend_original_frame,
1833 tvb, 0, 0, result->previousFrameNum);
1834 PROTO_ITEM_SET_GENERATED(original_ti);
1836 gap_ti = proto_tree_add_uint(tree, hf_mac_lte_ul_harq_resend_time_since_previous_frame,
1837 tvb, 0, 0, result->timeSincePreviousFrame);
1838 PROTO_ITEM_SET_GENERATED(gap_ti);
1841 expert_add_info_format(pinfo, retx_ti, PI_SEQUENCE, PI_ERROR,
1842 "Original Tx of UL frame not found (UE %u) !!", p_mac_lte_info->ueid);
1848 /* Look up SRResult associated with a given frame. Will create one if necessary
1849 if can_create is set */
1850 static SRResult *GetSRResult(guint32 frameNum, gboolean can_create)
1853 result = g_hash_table_lookup(mac_lte_sr_request_hash, GUINT_TO_POINTER(frameNum));
1855 if ((result == NULL) && can_create) {
1856 result = se_alloc0(sizeof(SRResult));
1857 g_hash_table_insert(mac_lte_sr_request_hash, GUINT_TO_POINTER((guint)frameNum), result);
1863 /* Keep track of SR requests, failures and related grants, in order to show them
1864 as generated fields in these frames */
1865 static void TrackSRInfo(SREvent event, packet_info *pinfo, proto_tree *tree,
1866 tvbuff_t *tvb, mac_lte_info *p_mac_lte_info, gint idx, proto_item *event_ti)
1868 SRResult *result = NULL;
1870 SRResult *resultForSRFrame = NULL;
1876 /* Get appropriate identifiers */
1877 if (event == SR_Grant) {
1878 rnti = p_mac_lte_info->rnti;
1879 ueid = p_mac_lte_info->ueid;
1882 rnti = p_mac_lte_info->oob_rnti[idx];
1883 ueid = p_mac_lte_info->oob_ueid[idx];
1886 /* Create state for this RNTI if necessary */
1887 state = g_hash_table_lookup(mac_lte_ue_sr_state, GUINT_TO_POINTER((guint)rnti));
1888 if (state == NULL) {
1889 /* Allocate status for this RNTI */
1890 state = se_alloc(sizeof(SRState));
1891 state->status = None;
1892 g_hash_table_insert(mac_lte_ue_sr_state, GUINT_TO_POINTER((guint)rnti), state);
1895 /* First time through - update state with new info */
1896 if (!pinfo->fd->flags.visited) {
1897 guint32 timeSinceRequest;
1899 /* Store time of request */
1900 if (event == SR_Request) {
1901 state->requestTime = pinfo->fd->abs_ts;
1904 switch (state->status) {
1908 /* Got another grant - fine */
1911 state->lastGrantFramenum = pinfo->fd->num;
1915 /* Sent an SR - fine */
1918 state->status = SR_Outstanding;
1919 state->lastSRFramenum = pinfo->fd->num;
1923 /* This is an error, since we hadn't send an SR... */
1924 result = GetSRResult(pinfo->fd->num, TRUE);
1925 result->type = InvalidSREvent;
1926 result->status = None;
1927 result->event = SR_Failure;
1932 case SR_Outstanding:
1933 timeSinceRequest = (guint32)(((pinfo->fd->abs_ts.secs - state->requestTime.secs) * 1000) +
1934 ((pinfo->fd->abs_ts.nsecs - state->requestTime.nsecs) / 1000000));
1938 /* Got grant we were waiting for, so state goes to None */
1941 state->status = None;
1943 /* Set result info */
1944 result = GetSRResult(pinfo->fd->num, TRUE);
1945 result->type = GrantAnsweringSR;
1946 result->frameNum = state->lastSRFramenum;
1947 result->timeDifference = timeSinceRequest;
1949 /* Also set forward link for SR */
1950 resultForSRFrame = GetSRResult(state->lastSRFramenum, TRUE);
1951 resultForSRFrame->type = SRLeadingToGrant;
1952 resultForSRFrame->frameNum = pinfo->fd->num;
1953 resultForSRFrame->timeDifference = timeSinceRequest;
1957 /* Another request when already have one pending */
1958 result = GetSRResult(pinfo->fd->num, TRUE);
1959 result->type = InvalidSREvent;
1960 result->status = SR_Outstanding;
1961 result->event = SR_Grant;
1965 /* We sent an SR but it failed */
1968 state->status = SR_Failed;
1970 /* Set result info for failure frame */
1971 result = GetSRResult(pinfo->fd->num, TRUE);
1972 result->type = FailureAnsweringSR;
1973 result->frameNum = state->lastSRFramenum;
1974 result->timeDifference = timeSinceRequest;
1976 /* Also set forward link for SR */
1977 resultForSRFrame = GetSRResult(state->lastSRFramenum, TRUE);
1978 resultForSRFrame->type = SRLeadingToFailure;
1979 resultForSRFrame->frameNum = pinfo->fd->num;
1980 resultForSRFrame->timeDifference = timeSinceRequest;
1988 /* Got a grant, presumably after a subsequent RACH - fine */
1991 state->status = None;
1995 /* Tried another SR after previous one failed.
1996 Presumably a subsequent RACH was tried in-between... */
1998 state->status = SR_Outstanding;
2000 result = GetSRResult(pinfo->fd->num, TRUE);
2001 result->status = SR_Outstanding;
2002 result->event = SR_Request;
2006 /* 2 failures in a row.... */
2007 result = GetSRResult(pinfo->fd->num, TRUE);
2008 result->type = InvalidSREvent;
2009 result->status = SR_Failed;
2010 result->event = SR_Failure;
2017 /* Get stored result for this frame */
2018 result = GetSRResult(pinfo->fd->num, FALSE);
2019 if (result == NULL) {
2020 /* For an SR frame, there should always be either a PDCCH grant or indication
2021 that the SR has failed */
2022 if (event == SR_Request) {
2023 expert_add_info_format(pinfo, event_ti, PI_SEQUENCE, PI_ERROR,
2024 "UE %u: SR results in neither a grant nor a failure indication",
2031 /* Show result info */
2032 switch (result->type) {
2033 case GrantAnsweringSR:
2034 ti = proto_tree_add_uint(tree, hf_mac_lte_grant_answering_sr,
2035 tvb, 0, 0, result->frameNum);
2036 PROTO_ITEM_SET_GENERATED(ti);
2037 ti = proto_tree_add_uint(tree, hf_mac_lte_sr_time_since_request,
2038 tvb, 0, 0, result->timeDifference);
2039 PROTO_ITEM_SET_GENERATED(ti);
2042 case FailureAnsweringSR:
2043 ti = proto_tree_add_uint(tree, hf_mac_lte_failure_answering_sr,
2044 tvb, 0, 0, result->frameNum);
2045 PROTO_ITEM_SET_GENERATED(ti);
2046 ti = proto_tree_add_uint(tree, hf_mac_lte_sr_time_since_request,
2047 tvb, 0, 0, result->timeDifference);
2048 PROTO_ITEM_SET_GENERATED(ti);
2051 case SRLeadingToGrant:
2052 ti = proto_tree_add_uint(tree, hf_mac_lte_sr_leading_to_grant,
2053 tvb, 0, 0, result->frameNum);
2054 PROTO_ITEM_SET_GENERATED(ti);
2055 ti = proto_tree_add_uint(tree, hf_mac_lte_sr_time_until_answer,
2056 tvb, 0, 0, result->timeDifference);
2057 PROTO_ITEM_SET_GENERATED(ti);
2061 case SRLeadingToFailure:
2062 ti = proto_tree_add_uint(tree, hf_mac_lte_sr_leading_to_failure,
2063 tvb, 0, 0, result->frameNum);
2064 PROTO_ITEM_SET_GENERATED(ti);
2065 ti = proto_tree_add_uint(tree, hf_mac_lte_sr_time_until_answer,
2066 tvb, 0, 0, result->timeDifference);
2067 PROTO_ITEM_SET_GENERATED(ti);
2070 case InvalidSREvent:
2071 ti = proto_tree_add_none_format(tree, hf_mac_lte_sr_invalid_event,
2072 tvb, 0, 0, "UE %u: Invalid SR event - state=%s, event=%s",
2074 val_to_str_const(result->status, sr_status_vals, "Unknown"),
2075 val_to_str_const(result->event, sr_event_vals, "Unknown"));
2076 PROTO_ITEM_SET_GENERATED(ti);
2077 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_ERROR,
2078 "Invalid SR event for UE %u (C-RNTI %u) - state=%s, event=%s",
2080 val_to_str_const(result->status, sr_status_vals, "Unknown"),
2081 val_to_str_const(result->event, sr_event_vals, "Unknown"));
2087 /********************************************************/
2088 /* Count number of UEs/TTI (in both directions) */
2089 /********************************************************/
2091 /* For keeping track during first pass */
2092 typedef struct tti_info_t {
2094 nstime_t ttiStartTime;
2098 static tti_info_t UL_tti_info;
2099 static tti_info_t DL_tti_info;
2101 /* For associating with frame and displaying */
2102 typedef struct TTIInfoResult_t {
2106 /* This table stores (FrameNumber -> *TTIInfoResult_t). It is assigned during the first
2107 pass and used thereafter */
2108 static GHashTable *mac_lte_tti_info_result_hash = NULL;
2111 /* Work out which UE this is within TTI (within direction). Return answer */
2112 static guint16 count_ues_tti(mac_lte_info *p_mac_lte_info, packet_info *pinfo)
2114 gboolean same_tti = FALSE;
2115 tti_info_t *tti_info;
2117 /* Just return any previous result */
2118 TTIInfoResult_t *result = g_hash_table_lookup(mac_lte_tti_info_result_hash, GUINT_TO_POINTER(pinfo->fd->num));
2119 if (result != NULL) {
2120 return result->ues_in_tti;
2123 /* Set tti_info based upon direction */
2124 if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
2125 tti_info = &UL_tti_info;
2128 tti_info = &DL_tti_info;
2131 /* Work out if we are still in the same tti as before */
2132 if (tti_info->subframe == p_mac_lte_info->subframeNumber) {
2133 gint seconds_between_packets = (gint)
2134 (pinfo->fd->abs_ts.secs - tti_info->ttiStartTime.secs);
2135 gint nseconds_between_packets =
2136 pinfo->fd->abs_ts.nsecs - tti_info->ttiStartTime.nsecs;
2138 /* Round difference to nearest microsecond */
2139 gint total_us_gap = (seconds_between_packets*1000000) +
2140 ((nseconds_between_packets+500) / 1000);
2142 if (total_us_gap < 1000) {
2147 /* Update global state */
2149 tti_info->subframe = p_mac_lte_info->subframeNumber;
2150 tti_info->ttiStartTime = pinfo->fd->abs_ts;
2151 tti_info->ues_in_tti = 1;
2154 tti_info->ues_in_tti++;
2157 /* Set result state for this frame */
2158 result = se_alloc(sizeof(TTIInfoResult_t));
2159 result->ues_in_tti = tti_info->ues_in_tti;
2160 g_hash_table_insert(mac_lte_tti_info_result_hash,
2161 GUINT_TO_POINTER(pinfo->fd->num), result);
2163 return tti_info->ues_in_tti;
2167 /* Show which UE this is (within direction) for this TTI */
2168 static void show_ues_tti(packet_info *pinfo, mac_lte_info *p_mac_lte_info, tvbuff_t *tvb, proto_tree *context_tree)
2170 /* Look up result */
2171 TTIInfoResult_t *result = g_hash_table_lookup(mac_lte_tti_info_result_hash, GUINT_TO_POINTER(pinfo->fd->num));
2172 if (result != NULL) {
2173 proto_item *ti = proto_tree_add_uint(context_tree,
2174 (p_mac_lte_info->direction == DIRECTION_UPLINK) ?
2175 hf_mac_lte_ues_ul_per_tti :
2176 hf_mac_lte_ues_dl_per_tti,
2177 tvb, 0, 0, result->ues_in_tti);
2178 PROTO_ITEM_SET_GENERATED(ti);
2184 /* Lookup channel details for lcid */
2185 static void lookup_rlc_channel_from_lcid(guint8 lcid,
2186 rlc_channel_type_t *rlc_channel_type,
2187 guint8 *UM_seqnum_length,
2190 /* Zero params (in case no match is found) */
2191 *rlc_channel_type = rlcRaw;
2192 *UM_seqnum_length = 0;
2195 if (global_mac_lte_lcid_drb_source == (int)FromStaticTable) {
2197 /* Look up in static (UAT) table */
2199 for (m=0; m < num_lcid_drb_mappings; m++) {
2200 if (lcid == lcid_drb_mappings[m].lcid) {
2202 *rlc_channel_type = lcid_drb_mappings[m].channel_type;
2204 /* Set UM_seqnum_length */
2205 switch (*rlc_channel_type) {
2207 *UM_seqnum_length = 5;
2210 *UM_seqnum_length = 10;
2217 *drb_id = lcid_drb_mappings[m].drbid;
2223 /* Look up setting gleaned from configuration protocol */
2224 if (!dynamic_lcid_drb_mapping[lcid].valid) {
2228 *rlc_channel_type = dynamic_lcid_drb_mapping[lcid].channel_type;
2230 /* Set UM_seqnum_length */
2231 switch (*rlc_channel_type) {
2233 *UM_seqnum_length = 5;
2236 *UM_seqnum_length = 10;
2243 *drb_id = dynamic_lcid_drb_mapping[lcid].drbid;
2249 #define MAX_HEADERS_IN_PDU 1024
2251 /* UL-SCH and DL-SCH formats have much in common, so handle them in a common
2253 static void dissect_ulsch_or_dlsch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2255 volatile guint32 offset, guint8 direction,
2256 mac_lte_info *p_mac_lte_info, mac_lte_tap_info *tap_info,
2257 proto_item *retx_ti,
2258 proto_tree *context_tree)
2262 proto_item *truncated_ti;
2263 proto_item *padding_length_ti;
2264 proto_item *hidden_root_ti;
2266 /* Keep track of LCIDs and lengths as we dissect the header */
2267 volatile guint8 number_of_headers = 0;
2268 guint8 lcids[MAX_HEADERS_IN_PDU];
2269 gint16 pdu_lengths[MAX_HEADERS_IN_PDU];
2271 proto_item *pdu_header_ti;
2272 proto_tree *pdu_header_tree;
2274 gboolean have_seen_data_header = FALSE;
2275 guint8 number_of_padding_subheaders = 0;
2276 gboolean have_seen_non_padding_control = FALSE;
2277 gboolean have_seen_bsr = FALSE;
2278 gboolean expecting_body_data = FALSE;
2279 volatile guint32 is_truncated = FALSE;
2281 /* Maintain/show UEs/TTI count */
2282 tap_info->ueInTTI = count_ues_tti(p_mac_lte_info, pinfo);
2283 show_ues_tti(pinfo, p_mac_lte_info, tvb, context_tree);
2285 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
2286 "%s: (SF=%u) UEId=%-3u ",
2287 (direction == DIRECTION_UPLINK) ? "UL-SCH" : "DL-SCH",
2288 p_mac_lte_info->subframeNumber,
2289 p_mac_lte_info->ueid);
2291 tap_info->raw_length = p_mac_lte_info->length;
2293 /* For uplink frames, if this is logged as a resend, look for original tx */
2294 if (direction == DIRECTION_UPLINK) {
2295 TrackReportedULHARQResend(pinfo, tvb, offset, tree, p_mac_lte_info, retx_ti);
2298 /* For uplink grants, update SR status. N.B. only newTx grant should stop SR */
2299 if ((direction == DIRECTION_UPLINK) && (p_mac_lte_info->reTxCount == 0) &&
2300 global_mac_lte_track_sr) {
2302 TrackSRInfo(SR_Grant, pinfo, tree, tvb, p_mac_lte_info, 0, NULL);
2305 /* Add hidden item to filter on */
2306 hidden_root_ti = proto_tree_add_string_format(tree,
2307 (direction == DIRECTION_UPLINK) ?
2313 PROTO_ITEM_SET_HIDDEN(hidden_root_ti);
2315 /* Add PDU block header subtree */
2316 pdu_header_ti = proto_tree_add_string_format(tree,
2317 (direction == DIRECTION_UPLINK) ?
2318 hf_mac_lte_ulsch_header :
2319 hf_mac_lte_dlsch_header,
2323 pdu_header_tree = proto_item_add_subtree(pdu_header_ti,
2324 (direction == DIRECTION_UPLINK) ?
2325 ett_mac_lte_ulsch_header :
2326 ett_mac_lte_dlsch_header);
2329 /************************************************************************/
2330 /* Dissect each sub-header. */
2334 proto_item *pdu_subheader_ti;
2335 proto_tree *pdu_subheader_tree;
2336 proto_item *lcid_ti;
2338 gint offset_start_subheader = offset;
2339 guint8 first_byte = tvb_get_guint8(tvb, offset);
2341 /* Add PDU block header subtree.
2342 Default with length of 1 byte. */
2343 pdu_subheader_ti = proto_tree_add_string_format(pdu_header_tree,
2344 hf_mac_lte_sch_subheader,
2348 pdu_subheader_tree = proto_item_add_subtree(pdu_subheader_ti,
2349 ett_mac_lte_sch_subheader);
2351 /* Check 1st 2 reserved bits */
2352 reserved = (first_byte & 0xc0) >> 6;
2353 ti = proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_sch_reserved,
2354 tvb, offset, 1, FALSE);
2355 if (reserved != 0) {
2356 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
2357 "%cL-SCH header Reserved bits not zero",
2358 (p_mac_lte_info->direction == DIRECTION_UPLINK) ? 'U' : 'D');
2362 extension = (first_byte & 0x20) >> 5;
2363 proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_sch_extended,
2364 tvb, offset, 1, FALSE);
2366 /* LCID. Has different meaning depending upon direction. */
2367 lcids[number_of_headers] = first_byte & 0x1f;
2368 if (direction == DIRECTION_UPLINK) {
2370 lcid_ti = proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_ulsch_lcid,
2371 tvb, offset, 1, FALSE);
2372 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
2374 val_to_str_const(lcids[number_of_headers],
2375 ulsch_lcid_vals, "(Unknown LCID)"));
2379 lcid_ti = proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_dlsch_lcid,
2380 tvb, offset, 1, FALSE);
2381 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
2383 val_to_str_const(lcids[number_of_headers],
2384 dlsch_lcid_vals, "(Unknown LCID)"));
2386 if (lcids[number_of_headers] == DRX_COMMAND_LCID) {
2387 expert_add_info_format(pinfo, lcid_ti, PI_SEQUENCE, PI_NOTE,
2388 "DRX command received for UE %u (RNTI %u)",
2389 p_mac_lte_info->ueid, p_mac_lte_info->rnti);
2394 /* Remember if we've seen a data subheader */
2395 if (lcids[number_of_headers] <= 10) {
2396 have_seen_data_header = TRUE;
2397 expecting_body_data = TRUE;
2400 /* Show an expert item if a contol subheader (except Padding) appears
2401 *after* a data PDU */
2402 if (have_seen_data_header &&
2403 (lcids[number_of_headers] > 10) && (lcids[number_of_headers] != PADDING_LCID)) {
2404 expert_add_info_format(pinfo, lcid_ti, PI_MALFORMED, PI_ERROR,
2405 "%cL-SCH Control subheaders should not appear after data subheaders",
2406 (p_mac_lte_info->direction == DIRECTION_UPLINK) ? 'U' : 'D');
2410 /* Show an expert item if we're seeing more then one BSR in a frame */
2411 if ((direction == DIRECTION_UPLINK) && is_bsr_lcid(lcids[number_of_headers])) {
2412 if (have_seen_bsr) {
2413 expert_add_info_format(pinfo, lcid_ti, PI_MALFORMED, PI_ERROR,
2414 "There shouldn't be > 1 BSR in a frame");
2417 have_seen_bsr = TRUE;
2420 /* Should not see padding after non-padding control... */
2421 if ((lcids[number_of_headers] > 10) &&
2422 (lcids[number_of_headers] == PADDING_LCID) &&
2425 number_of_padding_subheaders++;
2426 if (number_of_padding_subheaders > 2) {
2427 expert_add_info_format(pinfo, lcid_ti, PI_MALFORMED, PI_WARN,
2428 "Should not see more than 2 padding subheaders in one frame");
2431 if (have_seen_non_padding_control) {
2432 expert_add_info_format(pinfo, lcid_ti, PI_MALFORMED, PI_ERROR,
2433 "Padding should come before other control subheaders!");
2437 /* Remember that we've seen non-padding control */
2438 if ((lcids[number_of_headers] > 10) &&
2439 (lcids[number_of_headers] != PADDING_LCID)) {
2440 have_seen_non_padding_control = TRUE;
2445 /********************************************************************/
2446 /* Length field follows if not the last header or for a fixed-sized
2450 if (is_fixed_sized_control_element(lcids[number_of_headers], direction)) {
2451 pdu_lengths[number_of_headers] = 0;
2454 pdu_lengths[number_of_headers] = -1;
2458 /* Not the last one */
2459 if (!is_fixed_sized_control_element(lcids[number_of_headers], direction) &&
2460 (lcids[number_of_headers] != PADDING_LCID)) {
2464 /* F(ormat) bit tells us how long the length field is */
2465 format = (tvb_get_guint8(tvb, offset) & 0x80) >> 7;
2466 proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_sch_format,
2467 tvb, offset, 1, FALSE);
2469 /* Now read length field itself */
2471 /* >= 128 - use 15 bits */
2472 proto_tree_add_bits_ret_val(pdu_subheader_tree, hf_mac_lte_sch_length,
2473 tvb, offset*8 + 1, 15, &length, FALSE);
2478 /* Less than 128 - only 7 bits */
2479 proto_tree_add_bits_ret_val(pdu_subheader_tree, hf_mac_lte_sch_length,
2480 tvb, offset*8 + 1, 7, &length, FALSE);
2483 pdu_lengths[number_of_headers] = (gint16)length;
2486 pdu_lengths[number_of_headers] = 0;
2491 /* Close off description in info column */
2492 switch (pdu_lengths[number_of_headers]) {
2494 write_pdu_label_and_info(pdu_ti, NULL, pinfo, ") ");
2497 write_pdu_label_and_info(pdu_ti, NULL, pinfo, ":remainder) ");
2500 write_pdu_label_and_info(pdu_ti, NULL, pinfo, ":%u bytes) ",
2501 pdu_lengths[number_of_headers]);
2505 /* Append summary to subheader root */
2506 proto_item_append_text(pdu_subheader_ti, " (lcid=%s",
2507 val_to_str_const(lcids[number_of_headers],
2508 (direction == DIRECTION_UPLINK) ?
2513 switch (pdu_lengths[number_of_headers]) {
2515 proto_item_append_text(pdu_subheader_ti, ", length is remainder)");
2516 proto_item_append_text(pdu_header_ti, " (%s:remainder)",
2517 val_to_str_const(lcids[number_of_headers],
2518 (direction == DIRECTION_UPLINK) ? ulsch_lcid_vals : dlsch_lcid_vals,
2522 proto_item_append_text(pdu_subheader_ti, ")");
2523 proto_item_append_text(pdu_header_ti, " (%s)",
2524 val_to_str_const(lcids[number_of_headers],
2525 (direction == DIRECTION_UPLINK) ? ulsch_lcid_vals : dlsch_lcid_vals,
2529 proto_item_append_text(pdu_subheader_ti, ", length=%u)",
2530 pdu_lengths[number_of_headers]);
2531 proto_item_append_text(pdu_header_ti, " (%s:%u)",
2532 val_to_str_const(lcids[number_of_headers],
2533 (direction == DIRECTION_UPLINK) ? ulsch_lcid_vals : dlsch_lcid_vals,
2535 pdu_lengths[number_of_headers]);
2540 /* Flag unknown lcid values in expert info */
2541 if (match_strval(lcids[number_of_headers],
2542 (direction == DIRECTION_UPLINK) ? ulsch_lcid_vals : dlsch_lcid_vals) == NULL) {
2543 expert_add_info_format(pinfo, pdu_subheader_ti, PI_MALFORMED, PI_ERROR,
2544 "%cL-SCH: Unexpected LCID received (%u)",
2545 (p_mac_lte_info->direction == DIRECTION_UPLINK) ? 'U' : 'D',
2546 lcids[number_of_headers]);
2549 /* Set length of this subheader */
2550 proto_item_set_len(pdu_subheader_ti, offset - offset_start_subheader);
2552 number_of_headers++;
2553 } while (extension);
2555 /* Append summary to overall PDU header root */
2556 proto_item_append_text(pdu_header_ti, " (%u subheaders)",
2559 /* And set its length to offset */
2560 proto_item_set_len(pdu_header_ti, offset);
2565 /************************************************************************/
2566 /* Dissect SDUs / control elements / padding. */
2567 /************************************************************************/
2569 /* Dissect control element bodies first */
2571 for (n=0; n < number_of_headers; n++) {
2572 /* Get out of loop once see any data SDU subheaders */
2573 if (lcids[n] <= 10) {
2577 /* Process what should be a valid control PDU type */
2578 if (direction == DIRECTION_DOWNLINK) {
2580 /****************************/
2581 /* DL-SCH Control PDUs */
2583 case UE_CONTENTION_RESOLUTION_IDENTITY_LCID:
2586 proto_tree *cr_tree;
2588 ContentionResolutionResult *crResult;
2590 /* Create CR root */
2591 cr_ti = proto_tree_add_string_format(tree,
2592 hf_mac_lte_control_ue_contention_resolution,
2595 "Contention Resolution");
2596 cr_tree = proto_item_add_subtree(cr_ti, ett_mac_lte_contention_resolution);
2599 proto_tree_add_item(cr_tree, hf_mac_lte_control_ue_contention_resolution_identity,
2600 tvb, offset, 6, FALSE);
2602 /* Get pointer to result struct for this frame */
2603 crResult = g_hash_table_lookup(mac_lte_cr_result_hash, GUINT_TO_POINTER(pinfo->fd->num));
2604 if (crResult == NULL) {
2606 /* Need to set result by looking for and comparing with Msg3 */
2608 guint msg3Key = p_mac_lte_info->rnti;
2610 /* Allocate result and add it to the table */
2611 crResult = se_alloc(sizeof(ContentionResolutionResult));
2612 g_hash_table_insert(mac_lte_cr_result_hash, GUINT_TO_POINTER(pinfo->fd->num), crResult);
2615 msg3Data = g_hash_table_lookup(mac_lte_msg3_hash, GUINT_TO_POINTER(msg3Key));
2617 /* Compare CCCH bytes */
2618 if (msg3Data != NULL) {
2619 crResult->msSinceMsg3 = (guint32)(((pinfo->fd->abs_ts.secs - msg3Data->msg3Time.secs) * 1000) +
2620 ((pinfo->fd->abs_ts.nsecs - msg3Data->msg3Time.nsecs) / 1000000));
2621 crResult->msg3FrameNum = msg3Data->framenum;
2623 /* Compare the 6 bytes */
2624 if (tvb_memeql(tvb, offset, msg3Data->data, 6) == 0) {
2625 crResult->status = Msg3Match;
2628 crResult->status = Msg3NoMatch;
2632 crResult->status = NoMsg3;
2636 /* Now show CR result in tree */
2637 switch (crResult->status) {
2639 proto_item_append_text(cr_ti, " (no corresponding Msg3 found!)");
2643 ti = proto_tree_add_uint(cr_tree, hf_mac_lte_control_ue_contention_resolution_msg3,
2644 tvb, 0, 0, crResult->msg3FrameNum);
2645 PROTO_ITEM_SET_GENERATED(ti);
2646 ti = proto_tree_add_uint(cr_tree, hf_mac_lte_control_ue_contention_resolution_time_since_msg3,
2647 tvb, 0, 0, crResult->msSinceMsg3);
2648 PROTO_ITEM_SET_GENERATED(ti);
2650 ti = proto_tree_add_boolean(cr_tree, hf_mac_lte_control_ue_contention_resolution_msg3_matched,
2652 PROTO_ITEM_SET_GENERATED(ti);
2653 proto_item_append_text(cr_ti, " (matches Msg3 from frame %u, %ums ago)",
2654 crResult->msg3FrameNum, crResult->msSinceMsg3);
2658 ti = proto_tree_add_uint(cr_tree, hf_mac_lte_control_ue_contention_resolution_msg3,
2659 tvb, 0, 0, crResult->msg3FrameNum);
2660 PROTO_ITEM_SET_GENERATED(ti);
2661 ti = proto_tree_add_uint(cr_tree, hf_mac_lte_control_ue_contention_resolution_time_since_msg3,
2662 tvb, 0, 0, crResult->msSinceMsg3);
2663 PROTO_ITEM_SET_GENERATED(ti);
2665 ti = proto_tree_add_boolean(cr_tree, hf_mac_lte_control_ue_contention_resolution_msg3_matched,
2667 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
2668 "CR body in Msg4 doesn't match Msg3 CCCH in frame %u",
2669 crResult->msg3FrameNum);
2670 PROTO_ITEM_SET_GENERATED(ti);
2671 proto_item_append_text(cr_ti, " (doesn't match Msg3 from frame %u, %u ago)",
2672 crResult->msg3FrameNum, crResult->msSinceMsg3);
2679 case TIMING_ADVANCE_LCID:
2682 proto_item *reserved_ti;
2686 /* Check 2 reserved bits */
2687 reserved = (tvb_get_guint8(tvb, offset) & 0xc0) >> 6;
2688 reserved_ti = proto_tree_add_item(tree, hf_mac_lte_control_timing_advance_reserved, tvb, offset, 1, FALSE);
2689 if (reserved != 0) {
2690 expert_add_info_format(pinfo, reserved_ti, PI_MALFORMED, PI_ERROR,
2691 "Timing Advance Reserved bits not zero (found 0x%x)", reserved);
2695 ta_value = tvb_get_guint8(tvb, offset) & 0x3f;
2696 ta_ti = proto_tree_add_item(tree, hf_mac_lte_control_timing_advance,
2697 tvb, offset, 1, FALSE);
2699 if (ta_value == 31) {
2700 expert_add_info_format(pinfo, ta_ti, PI_SEQUENCE,
2702 "Timing Advance control element received (no correction needed)");
2705 expert_add_info_format(pinfo, ta_ti, PI_SEQUENCE,
2707 "Timing Advance control element received (%u) %s correction needed",
2709 (ta_value < 31) ? "-ve" : "+ve");
2714 case DRX_COMMAND_LCID:
2718 /* No payload (in this position) */
2719 tap_info->padding_bytes++;
2728 /**********************************/
2729 /* UL-SCH Control PDUs */
2731 case POWER_HEADROOM_REPORT_LCID:
2734 proto_tree *phr_tree;
2739 /* Create PHR root */
2740 phr_ti = proto_tree_add_string_format(tree,
2741 hf_mac_lte_control_power_headroom,
2745 phr_tree = proto_item_add_subtree(phr_ti, ett_mac_lte_power_headroom);
2747 /* Check 2 Reserved bits */
2748 reserved = (tvb_get_guint8(tvb, offset) & 0xc0) >> 6;
2749 ti = proto_tree_add_item(phr_tree, hf_mac_lte_control_power_headroom_reserved,
2750 tvb, offset, 1, FALSE);
2751 if (reserved != 0) {
2752 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
2753 "Power Headroom Reserved bits not zero (found 0x%x)", reserved);
2757 level = tvb_get_guint8(tvb, offset) & 0x3f;
2758 proto_tree_add_item(phr_tree, hf_mac_lte_control_power_headroom_level,
2759 tvb, offset, 1, FALSE);
2761 /* Show value in root label */
2762 proto_item_append_text(phr_ti, " (%s)",
2763 val_to_str_const(level, power_headroom_size_vals, "Unknown"));
2770 proto_tree_add_item(tree, hf_mac_lte_control_crnti,
2771 tvb, offset, 2, FALSE);
2774 case TRUNCATED_BSR_LCID:
2775 case SHORT_BSR_LCID:
2777 proto_tree *bsr_tree;
2779 proto_item *buffer_size_ti;
2783 bsr_ti = proto_tree_add_string_format(tree,
2784 hf_mac_lte_control_bsr,
2788 bsr_tree = proto_item_add_subtree(bsr_ti, ett_mac_lte_bsr);
2791 lcgid = (tvb_get_guint8(tvb, offset) & 0xc0) >> 6;
2792 proto_tree_add_item(bsr_tree, hf_mac_lte_control_bsr_lcg_id,
2793 tvb, offset, 1, FALSE);
2795 buffer_size = tvb_get_guint8(tvb, offset) & 0x3f;
2796 buffer_size_ti = proto_tree_add_item(bsr_tree, hf_mac_lte_control_short_bsr_buffer_size,
2797 tvb, offset, 1, FALSE);
2799 if (buffer_size >= global_mac_lte_bsr_warn_threshold) {
2800 expert_add_info_format(pinfo, buffer_size_ti, PI_SEQUENCE, PI_WARN,
2801 "UE %u - BSR for LCG %u exceeds threshold: %u (%s)",
2802 p_mac_lte_info->ueid,
2804 buffer_size, val_to_str_const(buffer_size, buffer_size_vals, "Unknown"));
2808 proto_item_append_text(bsr_ti, " (lcgid=%u %s)",
2810 val_to_str_const(buffer_size, buffer_size_vals, "Unknown"));
2815 proto_tree *bsr_tree;
2817 proto_item *buffer_size_ti;
2818 guint8 buffer_size[4];
2819 bsr_ti = proto_tree_add_string_format(tree,
2820 hf_mac_lte_control_bsr,
2824 bsr_tree = proto_item_add_subtree(bsr_ti, ett_mac_lte_bsr);
2827 buffer_size_ti = proto_tree_add_item(bsr_tree, hf_mac_lte_control_long_bsr_buffer_size_0,
2828 tvb, offset, 1, FALSE);
2829 buffer_size[0] = (tvb_get_guint8(tvb, offset) & 0xfc) >> 2;
2830 if (buffer_size[0] >= global_mac_lte_bsr_warn_threshold) {
2831 expert_add_info_format(pinfo, buffer_size_ti, PI_SEQUENCE, PI_WARN,
2832 "UE %u - BSR for LCG 0 exceeds threshold: %u (%s)",
2833 p_mac_lte_info->ueid,
2834 buffer_size[0], val_to_str_const(buffer_size[0], buffer_size_vals, "Unknown"));
2838 buffer_size_ti = proto_tree_add_item(bsr_tree, hf_mac_lte_control_long_bsr_buffer_size_1,
2839 tvb, offset, 2, FALSE);
2840 buffer_size[1] = ((tvb_get_guint8(tvb, offset) & 0x03) << 4) | ((tvb_get_guint8(tvb, offset+1) & 0xf0) >> 4);
2842 if (buffer_size[1] >= global_mac_lte_bsr_warn_threshold) {
2843 expert_add_info_format(pinfo, buffer_size_ti, PI_SEQUENCE, PI_WARN,
2844 "UE %u - BSR for LCG 1 exceeds threshold: %u (%s)",
2845 p_mac_lte_info->ueid,
2846 buffer_size[1], val_to_str_const(buffer_size[1], buffer_size_vals, "Unknown"));
2850 buffer_size_ti = proto_tree_add_item(bsr_tree, hf_mac_lte_control_long_bsr_buffer_size_2,
2851 tvb, offset, 2, FALSE);
2853 buffer_size[2] = ((tvb_get_guint8(tvb, offset) & 0x0f) << 2) | ((tvb_get_guint8(tvb, offset+1) & 0xc0) >> 6);
2855 if (buffer_size[2] >= global_mac_lte_bsr_warn_threshold) {
2856 expert_add_info_format(pinfo, buffer_size_ti, PI_SEQUENCE, PI_WARN,
2857 "UE %u - BSR for LCG 2 exceeds threshold: %u (%s)",
2858 p_mac_lte_info->ueid,
2859 buffer_size[2], val_to_str_const(buffer_size[2], buffer_size_vals, "Unknown"));
2863 buffer_size_ti = proto_tree_add_item(bsr_tree, hf_mac_lte_control_long_bsr_buffer_size_3,
2864 tvb, offset, 1, FALSE);
2865 buffer_size[3] = tvb_get_guint8(tvb, offset) & 0x3f;
2867 if (buffer_size[3] >= global_mac_lte_bsr_warn_threshold) {
2868 expert_add_info_format(pinfo, buffer_size_ti, PI_SEQUENCE, PI_WARN,
2869 "UE %u - BSR for LCG 3 exceeds threshold: %u (%s)",
2870 p_mac_lte_info->ueid,
2871 buffer_size[3], val_to_str_const(buffer_size[3], buffer_size_vals, "Unknown"));
2874 /* Append summary to parent */
2875 proto_item_append_text(bsr_ti, " 0:(%s) 1:(%s) 2:(%s) 3:(%s)",
2876 val_to_str_const(buffer_size[0], buffer_size_vals, "Unknown"),
2877 val_to_str_const(buffer_size[1], buffer_size_vals, "Unknown"),
2878 val_to_str_const(buffer_size[2], buffer_size_vals, "Unknown"),
2879 val_to_str_const(buffer_size[3], buffer_size_vals, "Unknown"));
2883 /* No payload, in this position */
2884 tap_info->padding_bytes++;
2894 /* There might not be any data, if only headers (plus control data) were logged */
2895 is_truncated = ((tvb_length_remaining(tvb, offset) == 0) && expecting_body_data);
2896 truncated_ti = proto_tree_add_uint(tree, hf_mac_lte_sch_header_only, tvb, 0, 0,
2899 PROTO_ITEM_SET_GENERATED(truncated_ti);
2900 expert_add_info_format(pinfo, truncated_ti, PI_SEQUENCE, PI_NOTE,
2901 "MAC PDU SDUs have been omitted");
2905 PROTO_ITEM_SET_HIDDEN(truncated_ti);
2909 /* Now process remaining bodies, which should all be data */
2910 for (; n < number_of_headers; n++) {
2912 /* Data SDUs treated identically for Uplink or downlink channels */
2914 const guint8 *pdu_data;
2915 volatile guint16 data_length;
2919 /* Break out if meet padding */
2920 if (lcids[n] == PADDING_LCID) {
2924 /* Work out length */
2925 data_length = (pdu_lengths[n] == -1) ?
2926 tvb_length_remaining(tvb, offset) :
2929 /* Dissect SDU as raw bytes */
2930 sdu_ti = proto_tree_add_bytes_format(tree, hf_mac_lte_sch_sdu, tvb, offset, pdu_lengths[n],
2931 NULL, "SDU (%s, length=%u bytes): ",
2932 val_to_str_const(lcids[n],
2933 (direction == DIRECTION_UPLINK) ?
2938 /* Show bytes too. There must be a nicer way of doing this! */
2939 pdu_data = tvb_get_ptr(tvb, offset, pdu_lengths[n]);
2940 for (i=0; i < data_length; i++) {
2941 g_snprintf(buff+(i*2), 3, "%02x", pdu_data[i]);
2943 g_snprintf(buff+(i*2), 4, "...");
2947 proto_item_append_text(sdu_ti, "%s", buff);
2950 /* Look for Msg3 data so that it may be compared with later
2951 Contention Resolution body */
2952 if ((lcids[n] == 0) && (direction == DIRECTION_UPLINK) && (data_length == 6)) {
2953 if (!pinfo->fd->flags.visited) {
2954 guint key = p_mac_lte_info->rnti;
2955 Msg3Data *data = g_hash_table_lookup(mac_lte_msg3_hash, GUINT_TO_POINTER(key));
2957 /* Look for previous entry for this UE */
2959 /* Allocate space for data and add to table */
2960 data = se_alloc(sizeof(Msg3Data));
2961 g_hash_table_insert(mac_lte_msg3_hash, GUINT_TO_POINTER(key), data);
2964 /* Fill in data details */
2965 data->framenum = pinfo->fd->num;
2966 tvb_memcpy(tvb, data->data, offset, data_length);
2967 data->msg3Time = pinfo->fd->abs_ts;
2971 /* CCCH frames can be dissected directly by LTE RRC... */
2972 if ((lcids[n] == 0) && global_mac_lte_attempt_rrc_decode) {
2973 tvbuff_t *rrc_tvb = tvb_new_subset(tvb, offset, data_length, data_length);
2975 /* Get appropriate dissector handle */
2976 volatile dissector_handle_t protocol_handle = 0;
2977 if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
2978 protocol_handle = find_dissector("lte_rrc.ul_ccch");
2981 protocol_handle = find_dissector("lte_rrc.dl_ccch");
2984 /* Hide raw view of bytes */
2985 PROTO_ITEM_SET_HIDDEN(sdu_ti);
2987 call_with_catch_all(protocol_handle, rrc_tvb, pinfo, tree);
2990 /* LCID 1 and 2 can be assumed to be srb1&2, so can dissect as RLC AM */
2991 else if ((lcids[n] == 1) || (lcids[n] == 2)) {
2992 if (global_mac_lte_attempt_srb_decode) {
2993 /* Call RLC dissector */
2994 call_rlc_dissector(tvb, pinfo, tree, pdu_ti, offset, data_length,
2995 RLC_AM_MODE, direction, p_mac_lte_info->ueid,
2996 CHANNEL_TYPE_SRB, lcids[n], 0);
2998 /* Hide raw view of bytes */
2999 PROTO_ITEM_SET_HIDDEN(sdu_ti);
3003 else if ((lcids[n] >= 2) && (lcids[n] <= 10)) {
3005 /* Look for mapping for this LCID to drb channel set by UAT table */
3006 rlc_channel_type_t rlc_channel_type;
3007 guint8 UM_seqnum_length;
3010 lookup_rlc_channel_from_lcid(lcids[n],
3015 /* Dissect according to channel type */
3016 switch (rlc_channel_type) {
3018 call_rlc_dissector(tvb, pinfo, tree, pdu_ti, offset, data_length,
3019 RLC_UM_MODE, direction, p_mac_lte_info->ueid,
3020 CHANNEL_TYPE_DRB, (guint16)drb_id, UM_seqnum_length);
3023 call_rlc_dissector(tvb, pinfo, tree, pdu_ti, offset, data_length,
3024 RLC_UM_MODE, direction, p_mac_lte_info->ueid,
3025 CHANNEL_TYPE_DRB, (guint16)drb_id, UM_seqnum_length);
3028 call_rlc_dissector(tvb, pinfo, tree, pdu_ti, offset, data_length,
3029 RLC_AM_MODE, direction, p_mac_lte_info->ueid,
3030 CHANNEL_TYPE_DRB, (guint16)drb_id, 0);
3033 call_rlc_dissector(tvb, pinfo, tree, pdu_ti, offset, data_length,
3034 RLC_TM_MODE, direction, p_mac_lte_info->ueid,
3035 CHANNEL_TYPE_DRB, (guint16)drb_id, 0);
3038 /* Nothing to do! */
3042 if (rlc_channel_type != rlcRaw) {
3043 /* Hide raw view of bytes */
3044 PROTO_ITEM_SET_HIDDEN(sdu_ti);
3049 offset += data_length;
3051 /* Update tap byte count for this channel */
3052 tap_info->bytes_for_lcid[lcids[n]] += data_length;
3053 tap_info->sdus_for_lcid[lcids[n]]++;
3056 /* Now know the length of the PDU without any padding (which may or may not be logged) */
3057 /* For downlink frames marked as a resend, look for link back to previous tx */
3058 if (direction == DIRECTION_DOWNLINK) {
3059 /* Result will be added to context tree */
3060 TrackReportedDLHARQResend(pinfo, tvb, offset, context_tree, p_mac_lte_info);
3062 tap_info->isPHYRetx = (p_mac_lte_info->dl_retx == dl_retx_yes);
3067 /* Now padding, if present, extends to the end of the PDU */
3068 if (lcids[number_of_headers-1] == PADDING_LCID) {
3069 if (tvb_length_remaining(tvb, offset) > 0) {
3070 proto_tree_add_item(tree, hf_mac_lte_padding_data,
3071 tvb, offset, -1, FALSE);
3073 padding_length_ti = proto_tree_add_int(tree, hf_mac_lte_padding_length,
3075 p_mac_lte_info->length - offset);
3076 PROTO_ITEM_SET_GENERATED(padding_length_ti);
3078 /* Update padding bytes in stats */
3079 tap_info->padding_bytes += (p_mac_lte_info->length - offset);
3081 /* Make sure the PDU isn't bigger than reported! */
3082 if (offset > p_mac_lte_info->length) {
3083 expert_add_info_format(pinfo, padding_length_ti, PI_MALFORMED, PI_ERROR,
3084 "MAC PDU is longer than reported length (reported=%u, actual=%u)",
3085 p_mac_lte_info->length, offset);
3089 /* There is no padding at the end of the frame */
3090 if (!is_truncated && (offset < p_mac_lte_info->length)) {
3091 /* There is a problem if we haven't used all of the PDU */
3092 expert_add_info_format(pinfo, pdu_ti, PI_MALFORMED, PI_ERROR,
3093 "PDU for UE %u is shorter than reported length (reported=%u, actual=%u)",
3094 p_mac_lte_info->ueid, p_mac_lte_info->length, offset);
3097 if (!is_truncated && (offset > p_mac_lte_info->length)) {
3098 /* There is a problem if the PDU is longer than rpeported */
3099 expert_add_info_format(pinfo, pdu_ti, PI_MALFORMED, PI_ERROR,
3100 "PDU for UE %u is longer than reported length (reported=%u, actual=%u)",
3101 p_mac_lte_info->ueid, p_mac_lte_info->length, offset);
3108 /*****************************/
3109 /* Main dissection function. */
3110 void dissect_mac_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
3112 proto_tree *mac_lte_tree;
3114 proto_tree *context_tree;
3115 proto_item *context_ti;
3116 proto_item *retx_ti = NULL;
3119 struct mac_lte_info *p_mac_lte_info = NULL;
3122 /* Allocate and zero tap struct */
3123 mac_lte_tap_info *tap_info = ep_alloc0(sizeof(mac_lte_tap_info));
3125 /* Set protocol name */
3126 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MAC-LTE");
3128 /* Create protocol tree. */
3129 pdu_ti = proto_tree_add_item(tree, proto_mac_lte, tvb, offset, -1, FALSE);
3130 proto_item_append_text(pdu_ti, " ");
3131 mac_lte_tree = proto_item_add_subtree(pdu_ti, ett_mac_lte);
3134 /* Look for packet info! */
3135 p_mac_lte_info = p_get_proto_data(pinfo->fd, proto_mac_lte);
3137 /* Can't dissect anything without it... */
3138 if (p_mac_lte_info == NULL) {
3140 proto_tree_add_text(mac_lte_tree, tvb, offset, -1,
3141 "Can't dissect LTE MAC frame because no per-frame info was attached!");
3142 PROTO_ITEM_SET_GENERATED(tii);
3146 /* Clear info column */
3147 col_clear(pinfo->cinfo, COL_INFO);
3150 /*****************************************/
3151 /* Show context information */
3153 /* Create context root */
3154 context_ti = proto_tree_add_string_format(mac_lte_tree, hf_mac_lte_context,
3155 tvb, offset, 0, "", "Context");
3156 context_tree = proto_item_add_subtree(context_ti, ett_mac_lte_context);
3157 PROTO_ITEM_SET_GENERATED(context_ti);
3159 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_radio_type,
3160 tvb, 0, 0, p_mac_lte_info->radioType);
3161 PROTO_ITEM_SET_GENERATED(ti);
3163 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_direction,
3164 tvb, 0, 0, p_mac_lte_info->direction);
3165 PROTO_ITEM_SET_GENERATED(ti);
3167 if (p_mac_lte_info->ueid != 0) {
3168 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_ueid,
3169 tvb, 0, 0, p_mac_lte_info->ueid);
3170 PROTO_ITEM_SET_GENERATED(ti);
3173 /* There are several out-of-band MAC events that may be indicated in the context info. */
3174 /* Handle them here */
3175 if (p_mac_lte_info->length == 0) {
3176 proto_item *preamble_ti;
3177 proto_tree *preamble_tree;
3179 switch (p_mac_lte_info->oob_event) {
3180 case ltemac_send_preamble:
3181 preamble_ti = proto_tree_add_item(mac_lte_tree, hf_mac_lte_oob_send_preamble,
3183 preamble_tree = proto_item_add_subtree(preamble_ti, ett_mac_lte_oob);
3184 PROTO_ITEM_SET_GENERATED(ti);
3186 ti = proto_tree_add_uint(preamble_tree, hf_mac_lte_context_rapid,
3187 tvb, 0, 0, p_mac_lte_info->rapid);
3188 PROTO_ITEM_SET_GENERATED(ti);
3190 ti = proto_tree_add_uint(preamble_tree, hf_mac_lte_context_rach_attempt_number,
3191 tvb, 0, 0, p_mac_lte_info->rach_attempt_number);
3192 PROTO_ITEM_SET_GENERATED(ti);
3195 write_pdu_label_and_info(pdu_ti, preamble_ti, pinfo,
3196 "RACH Preamble sent for UE %u (RAPID=%u, attempt=%u)",
3197 p_mac_lte_info->ueid, p_mac_lte_info->rapid, p_mac_lte_info->rach_attempt_number);
3199 /* Add expert info (a note, unless attempt > 1) */
3200 expert_add_info_format(pinfo, ti, PI_SEQUENCE,
3201 (p_mac_lte_info->rach_attempt_number > 1) ? PI_WARN : PI_NOTE,
3202 "RACH Preamble sent for UE %u (RAPID=%u, attempt=%u)",
3203 p_mac_lte_info->ueid, p_mac_lte_info->rapid,
3204 p_mac_lte_info->rach_attempt_number);
3206 case ltemac_send_sr:
3207 for (n=0; n < p_mac_lte_info->number_of_srs; n++) {
3209 proto_tree *sr_tree;
3211 /* SR event is subtree */
3212 sr_ti = proto_tree_add_item(mac_lte_tree, hf_mac_lte_oob_send_sr,
3214 sr_tree = proto_item_add_subtree(sr_ti, ett_mac_lte_oob);
3215 PROTO_ITEM_SET_GENERATED(sr_ti);
3219 ti = proto_tree_add_uint(sr_tree, hf_mac_lte_context_rnti,
3220 tvb, 0, 0, p_mac_lte_info->oob_rnti[n]);
3221 PROTO_ITEM_SET_GENERATED(ti);
3224 ti = proto_tree_add_uint(sr_tree, hf_mac_lte_context_ueid,
3225 tvb, 0, 0, p_mac_lte_info->oob_ueid[n]);
3226 PROTO_ITEM_SET_GENERATED(ti);
3228 /* Add summary to root. */
3229 proto_item_append_text(sr_ti, " (UE=%u C-RNTI=%u)",
3230 p_mac_lte_info->oob_ueid[n],
3231 p_mac_lte_info->oob_rnti[n]);
3235 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
3236 "Scheduling Requests (%u) sent: (UE=%u C-RNTI=%u)",
3237 p_mac_lte_info->number_of_srs,
3238 p_mac_lte_info->oob_ueid[n],
3239 p_mac_lte_info->oob_rnti[n]);
3242 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
3243 " (UE=%u C-RNTI=%u)",
3244 p_mac_lte_info->oob_ueid[n],
3245 p_mac_lte_info->oob_rnti[n]);
3248 /* Add expert info (a note) */
3249 expert_add_info_format(pinfo, sr_ti, PI_SEQUENCE, PI_NOTE,
3250 "Scheduling Request sent for UE %u (RNTI %u)",
3251 p_mac_lte_info->oob_ueid[n],
3252 p_mac_lte_info->oob_rnti[n]);
3254 /* Update SR status for this UE */
3255 if (global_mac_lte_track_sr) {
3256 TrackSRInfo(SR_Request, pinfo, mac_lte_tree, tvb, p_mac_lte_info, n, sr_ti);
3260 case ltemac_sr_failure:
3261 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_rnti,
3262 tvb, 0, 0, p_mac_lte_info->rnti);
3263 PROTO_ITEM_SET_GENERATED(ti);
3265 ti = proto_tree_add_item(mac_lte_tree, hf_mac_lte_oob_sr_failure,
3267 PROTO_ITEM_SET_GENERATED(ti);
3270 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
3271 "Scheduling Request FAILED for UE %u (C-RNTI=%u)",
3272 p_mac_lte_info->ueid,
3273 p_mac_lte_info->rnti);
3275 /* Add expert info (an error) */
3276 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_ERROR,
3277 "Scheduling Request failed for UE %u (RNTI %u)",
3278 p_mac_lte_info->ueid,
3279 p_mac_lte_info->rnti);
3281 /* Update SR status */
3282 if (global_mac_lte_track_sr) {
3283 TrackSRInfo(SR_Failure, pinfo, mac_lte_tree, tvb, p_mac_lte_info, 0, ti);
3289 /* Our work here is done */
3294 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_subframe_number,
3295 tvb, 0, 0, p_mac_lte_info->subframeNumber);
3296 PROTO_ITEM_SET_GENERATED(ti);
3297 if (p_mac_lte_info->subframeNumber > 9) {
3298 /* N.B. if we set it to avlid value, it won't trigger when we rescan
3299 (at least with DCT2000 files where the context struct isn't re-read). */
3300 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
3301 "Subframe number (%u) was out of range - valid range is 0-9",
3302 p_mac_lte_info->subframeNumber);
3305 if (p_mac_lte_info->subframeNumberOfGrantPresent) {
3306 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_grant_subframe_number,
3307 tvb, 0, 0, p_mac_lte_info->subframeNumberOfGrant);
3308 PROTO_ITEM_SET_GENERATED(ti);
3311 if (p_mac_lte_info->rntiType != NO_RNTI) {
3312 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_rnti,
3313 tvb, 0, 0, p_mac_lte_info->rnti);
3314 PROTO_ITEM_SET_GENERATED(ti);
3317 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_rnti_type,
3318 tvb, 0, 0, p_mac_lte_info->rntiType);
3319 PROTO_ITEM_SET_GENERATED(ti);
3321 /* Check that RNTI value is consistent with given RNTI type */
3322 switch (p_mac_lte_info->rntiType) {
3324 if (p_mac_lte_info->rnti != 0xFFFE) {
3325 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
3326 "P-RNTI indicated, but value is %u (0x%x) (must be 0x%x)",
3327 p_mac_lte_info->rnti, p_mac_lte_info->rnti, 0xFFFE);
3332 if (p_mac_lte_info->rnti != 0xFFFF) {
3333 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
3334 "SI-RNTI indicated, but value is %u (0x%x) (must be 0x%x)",
3335 p_mac_lte_info->rnti, p_mac_lte_info->rnti, 0xFFFE);
3340 if ((p_mac_lte_info->rnti < 0x0001) || (p_mac_lte_info->rnti > 0x003C)) {
3341 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
3342 "RA_RNTI indicated, but given value %u (0x%x)is out of range",
3343 p_mac_lte_info->rnti, p_mac_lte_info->rnti);
3349 if ((p_mac_lte_info->rnti < 0x0001) || (p_mac_lte_info->rnti > 0xFFF3)) {
3350 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
3351 "%s indicated, but given value %u (0x%x)is out of range",
3352 val_to_str_const(p_mac_lte_info->rntiType, rnti_type_vals, "Unknown"),
3353 p_mac_lte_info->rnti, p_mac_lte_info->rnti);
3362 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_predefined_frame,
3363 tvb, 0, 0, p_mac_lte_info->isPredefinedData);
3364 if (p_mac_lte_info->isPredefinedData) {
3365 PROTO_ITEM_SET_GENERATED(ti);
3368 PROTO_ITEM_SET_HIDDEN(ti);
3371 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_length,
3372 tvb, 0, 0, p_mac_lte_info->length);
3373 PROTO_ITEM_SET_GENERATED(ti);
3374 /* Infer uplink grant size */
3375 if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
3376 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_ul_grant_size,
3377 tvb, 0, 0, p_mac_lte_info->length);
3378 PROTO_ITEM_SET_GENERATED(ti);
3381 /* Retx count goes in top-level tree to make it more visible */
3382 if (p_mac_lte_info->reTxCount) {
3383 retx_ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_context_retx_count,
3384 tvb, 0, 0, p_mac_lte_info->reTxCount);
3385 PROTO_ITEM_SET_GENERATED(retx_ti);
3387 if (p_mac_lte_info->reTxCount >= global_mac_lte_retx_counter_trigger) {
3388 expert_add_info_format(pinfo, retx_ti, PI_SEQUENCE, PI_WARN,
3389 "UE %u: UL MAC frame ReTX no. %u",
3390 p_mac_lte_info->ueid, p_mac_lte_info->reTxCount);
3394 if (p_mac_lte_info->crcStatusValid) {
3396 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_crc_status,
3397 tvb, 0, 0, p_mac_lte_info->detailed_phy_info.dl_info.crc_status);
3398 PROTO_ITEM_SET_GENERATED(ti);
3400 /* Report non-success */
3401 if (p_mac_lte_info->detailed_phy_info.dl_info.crc_status != crc_success) {
3402 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
3403 "%s Frame has CRC error problem (%s)",
3404 (p_mac_lte_info->direction == DIRECTION_UPLINK) ? "UL" : "DL",
3405 val_to_str_const(p_mac_lte_info->detailed_phy_info.dl_info.crc_status,
3408 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
3409 "%s: <CRC %s> UEId=%u %s=%u ",
3410 (p_mac_lte_info->direction == DIRECTION_UPLINK) ? "UL" : "DL",
3411 val_to_str_const(p_mac_lte_info->detailed_phy_info.dl_info.crc_status,
3414 p_mac_lte_info->ueid,
3415 val_to_str_const(p_mac_lte_info->rntiType, rnti_type_vals,
3416 "Unknown RNTI type"),
3417 p_mac_lte_info->rnti);
3421 /* May also have extra Physical layer attributes set for this frame */
3422 show_extra_phy_parameters(pinfo, tvb, mac_lte_tree, p_mac_lte_info);
3424 /* Set context-info parts of tap struct */
3425 tap_info->rnti = p_mac_lte_info->rnti;
3426 tap_info->ueid = p_mac_lte_info->ueid;
3427 tap_info->rntiType = p_mac_lte_info->rntiType;
3428 tap_info->isPredefinedData = p_mac_lte_info->isPredefinedData;
3429 tap_info->isPHYRetx = (p_mac_lte_info->reTxCount >= 1);
3430 tap_info->crcStatusValid = p_mac_lte_info->crcStatusValid;
3431 tap_info->crcStatus = p_mac_lte_info->detailed_phy_info.dl_info.crc_status;
3432 tap_info->direction = p_mac_lte_info->direction;
3434 tap_info->time = pinfo->fd->abs_ts;
3436 /* Also set total number of bytes (won't be used for UL/DL-SCH) */
3437 tap_info->single_number_of_bytes = tvb_length_remaining(tvb, offset);
3439 /* If we know its predefined data, don't try to decode any further */
3440 if (p_mac_lte_info->isPredefinedData) {
3441 proto_tree_add_item(mac_lte_tree, hf_mac_lte_predefined_pdu, tvb, offset, -1, FALSE);
3442 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
3443 "Predefined data (%u bytes)",
3444 tvb_length_remaining(tvb, offset));
3446 /* Queue tap info */
3447 if (!pinfo->in_error_pkt) {
3448 tap_queue_packet(mac_lte_tap, pinfo, tap_info);
3454 /* IF CRC status failed, just do decode as raw bytes */
3455 if (!global_mac_lte_dissect_crc_failures &&
3456 (p_mac_lte_info->crcStatusValid &&
3457 (p_mac_lte_info->detailed_phy_info.dl_info.crc_status != crc_success))) {
3459 proto_tree_add_item(mac_lte_tree, hf_mac_lte_raw_pdu, tvb, offset, -1, FALSE);
3460 write_pdu_label_and_info(pdu_ti, NULL, pinfo, "Raw data (%u bytes)", tvb_length_remaining(tvb, offset));
3463 TODO: unfortunately DL retx detection won't get done if we return here... */
3464 if (!pinfo->in_error_pkt) {
3465 tap_queue_packet(mac_lte_tap, pinfo, tap_info);
3471 /* Reset this counter */
3472 s_number_of_rlc_pdus_shown = 0;
3474 /* Dissect the MAC PDU itself. Format depends upon RNTI type. */
3475 switch (p_mac_lte_info->rntiType) {
3479 dissect_pch(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info->direction);
3484 dissect_rar(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info, tap_info);
3489 /* Can be UL-SCH or DL-SCH */
3490 dissect_ulsch_or_dlsch(tvb, pinfo, mac_lte_tree, pdu_ti, offset,
3491 p_mac_lte_info->direction, p_mac_lte_info, tap_info,
3492 retx_ti, context_tree);
3496 /* BCH over DL-SCH */
3497 dissect_bch(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info);
3501 /* Must be BCH over BCH... */
3502 dissect_bch(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info);
3510 /* Queue tap info */
3511 tap_queue_packet(mac_lte_tap, pinfo, tap_info);
3517 /* Initializes the hash table and the mem_chunk area each time a new
3518 * file is loaded or re-loaded in wireshark */
3520 mac_lte_init_protocol(void)
3522 /* Destroy any existing tables. */
3523 if (mac_lte_msg3_hash) {
3524 g_hash_table_destroy(mac_lte_msg3_hash);
3526 if (mac_lte_cr_result_hash) {
3527 g_hash_table_destroy(mac_lte_cr_result_hash);
3530 if (mac_lte_dl_harq_hash) {
3531 g_hash_table_destroy(mac_lte_dl_harq_hash);
3533 if (mac_lte_dl_harq_result_hash) {
3534 g_hash_table_destroy(mac_lte_dl_harq_result_hash);
3536 if (mac_lte_ul_harq_hash) {
3537 g_hash_table_destroy(mac_lte_ul_harq_hash);
3539 if (mac_lte_ul_harq_result_hash) {
3540 g_hash_table_destroy(mac_lte_ul_harq_result_hash);
3542 if (mac_lte_ue_sr_state) {
3543 g_hash_table_destroy(mac_lte_ue_sr_state);
3545 if (mac_lte_sr_request_hash) {
3546 g_hash_table_destroy(mac_lte_sr_request_hash);
3548 if (mac_lte_tti_info_result_hash) {
3549 g_hash_table_destroy(mac_lte_tti_info_result_hash);
3553 memset(&UL_tti_info, 0, sizeof(UL_tti_info));
3554 UL_tti_info.subframe = 0xff; /* Invalid value */
3555 memset(&DL_tti_info, 0, sizeof(DL_tti_info));
3556 DL_tti_info.subframe = 0xff; /* Invalid value */
3558 /* Now create them over */
3559 mac_lte_msg3_hash = g_hash_table_new(mac_lte_rnti_hash_func, mac_lte_rnti_hash_equal);
3560 mac_lte_cr_result_hash = g_hash_table_new(mac_lte_framenum_hash_func, mac_lte_framenum_hash_equal);
3562 mac_lte_dl_harq_hash = g_hash_table_new(mac_lte_rnti_hash_func, mac_lte_rnti_hash_equal);
3563 mac_lte_dl_harq_result_hash = g_hash_table_new(mac_lte_framenum_hash_func, mac_lte_framenum_hash_equal);
3565 mac_lte_ul_harq_hash = g_hash_table_new(mac_lte_rnti_hash_func, mac_lte_rnti_hash_equal);
3566 mac_lte_ul_harq_result_hash = g_hash_table_new(mac_lte_framenum_hash_func, mac_lte_framenum_hash_equal);
3568 mac_lte_ue_sr_state = g_hash_table_new(mac_lte_rnti_hash_func, mac_lte_rnti_hash_equal);
3569 mac_lte_sr_request_hash = g_hash_table_new(mac_lte_framenum_hash_func, mac_lte_framenum_hash_equal);
3571 mac_lte_tti_info_result_hash = g_hash_table_new(mac_lte_framenum_hash_func, mac_lte_framenum_hash_equal);
3575 static void* lcid_drb_mapping_copy_cb(void* dest, const void* orig, size_t len _U_)
3577 const lcid_drb_mapping_t *o = orig;
3578 lcid_drb_mapping_t *d = dest;
3580 /* Copy all items over */
3582 d->drbid = o->drbid;
3583 d->channel_type = o->channel_type;
3590 void proto_register_mac_lte(void)
3592 static hf_register_info hf[] =
3594 /**********************************/
3595 /* Items for decoding context */
3596 { &hf_mac_lte_context,
3598 "mac-lte.context", FT_STRING, BASE_NONE, NULL, 0x0,
3602 { &hf_mac_lte_context_radio_type,
3604 "mac-lte.radio-type", FT_UINT8, BASE_DEC, VALS(radio_type_vals), 0x0,
3608 { &hf_mac_lte_context_direction,
3610 "mac-lte.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
3611 "Direction of message", HFILL
3614 { &hf_mac_lte_context_rnti,
3616 "mac-lte.rnti", FT_UINT16, BASE_DEC, 0, 0x0,
3617 "RNTI associated with message", HFILL
3620 { &hf_mac_lte_context_rnti_type,
3622 "mac-lte.rnti-type", FT_UINT8, BASE_DEC, VALS(rnti_type_vals), 0x0,
3623 "Type of RNTI associated with message", HFILL
3626 { &hf_mac_lte_context_ueid,
3628 "mac-lte.ueid", FT_UINT16, BASE_DEC, 0, 0x0,
3629 "User Equipment Identifier associated with message", HFILL
3632 { &hf_mac_lte_context_subframe_number,
3634 "mac-lte.subframe", FT_UINT16, BASE_DEC, 0, 0x0,
3635 "Subframe number associated with message", HFILL
3638 { &hf_mac_lte_context_grant_subframe_number,
3640 "mac-lte.grant-subframe", FT_UINT16, BASE_DEC, 0, 0x0,
3641 "Subframe grant for this PDU was received", HFILL
3644 { &hf_mac_lte_context_predefined_frame,
3645 { "Predefined frame",
3646 "mac-lte.is-predefined-frame", FT_UINT8, BASE_DEC, VALS(predefined_frame_vals), 0x0,
3647 "Predefined test frame (or real MAC PDU)", HFILL
3650 { &hf_mac_lte_context_length,
3651 { "Length of frame",
3652 "mac-lte.length", FT_UINT8, BASE_DEC, 0, 0x0,
3653 "Original length of frame (including SDUs and padding)", HFILL
3656 { &hf_mac_lte_context_ul_grant_size,
3657 { "Uplink grant size",
3658 "mac-lte.ul-grant-size", FT_UINT8, BASE_DEC, 0, 0x0,
3659 "Uplink grant size (in bytes)", HFILL
3662 { &hf_mac_lte_context_bch_transport_channel,
3663 { "Transport channel",
3664 "mac-lte.bch-transport-channel", FT_UINT8, BASE_DEC, VALS(bch_transport_channel_vals), 0x0,
3665 "Transport channel BCH data was carried on", HFILL
3668 { &hf_mac_lte_context_retx_count,
3670 "mac-lte.retx-count", FT_UINT8, BASE_DEC, 0, 0x0,
3671 "Number of times this PDU has been retransmitted", HFILL
3674 { &hf_mac_lte_context_crc_status,
3676 "mac-lte.crc-status", FT_UINT8, BASE_DEC, VALS(crc_status_vals), 0x0,
3677 "CRC Status as reported by PHY", HFILL
3680 { &hf_mac_lte_context_rapid,
3682 "mac-lte.preamble-sent.rapid", FT_UINT8, BASE_DEC, 0, 0x0,
3683 "RAPID sent in RACH preamble", HFILL
3686 { &hf_mac_lte_context_rach_attempt_number,
3687 { "RACH Attempt Number",
3688 "mac-lte.preamble-sent.attempt", FT_UINT8, BASE_DEC, 0, 0x0,
3693 { &hf_mac_lte_ues_ul_per_tti,
3695 "mac-lte.ul-tti-count", FT_UINT8, BASE_DEC, 0, 0x0,
3696 "In this TTI, this is the nth UL grant", HFILL
3699 { &hf_mac_lte_ues_dl_per_tti,
3701 "mac-lte.dl-tti-count", FT_UINT8, BASE_DEC, 0, 0x0,
3702 "In this TTI, this is the nth DL PDU", HFILL
3707 /* Extra PHY context */
3708 { &hf_mac_lte_context_phy_ul,
3709 { "UL PHY attributes",
3710 "mac-lte.ul-phy", FT_STRING, BASE_NONE, 0, 0x0,
3714 { &hf_mac_lte_context_phy_ul_modulation_type,
3715 { "Modulation type",
3716 "mac-lte.ul-phy.modulation-type", FT_UINT8, BASE_DEC, VALS(modulation_type_vals), 0x0,
3720 { &hf_mac_lte_context_phy_ul_tbs_index,
3722 "mac-lte.ul-phy.tbs-index", FT_UINT8, BASE_DEC, 0, 0x0,
3726 { &hf_mac_lte_context_phy_ul_resource_block_length,
3727 { "Resource Block Length",
3728 "mac-lte.ul-phy.resource-block-length", FT_UINT8, BASE_DEC, 0, 0x0,
3732 { &hf_mac_lte_context_phy_ul_resource_block_start,
3733 { "Resource Block Start",
3734 "mac-lte.ul-phy.resource-block-start", FT_UINT8, BASE_DEC, 0, 0x0,
3738 { &hf_mac_lte_context_phy_ul_harq_id,
3740 "mac-lte.ul-phy.harq-id", FT_UINT8, BASE_DEC, 0, 0x0,
3744 { &hf_mac_lte_context_phy_ul_ndi,
3746 "mac-lte.ul-phy.ndi", FT_UINT8, BASE_DEC, 0, 0x0,
3747 "UL New Data Indicator", HFILL
3751 { &hf_mac_lte_context_phy_dl,
3752 { "DL PHY attributes",
3753 "mac-lte.dl-phy", FT_STRING, BASE_NONE, 0, 0x0,
3757 { &hf_mac_lte_context_phy_dl_dci_format,
3759 "mac-lte.dl-phy.dci-format", FT_UINT8, BASE_DEC, VALS(dci_format_vals), 0x0,
3763 { &hf_mac_lte_context_phy_dl_resource_allocation_type,
3764 { "Resource Allocation Type",
3765 "mac-lte.dl-phy.resource-allocation-type", FT_UINT8, BASE_DEC, 0, 0x0,
3769 { &hf_mac_lte_context_phy_dl_aggregation_level,
3770 { "Aggregation Level",
3771 "mac-lte.dl-phy.aggregation-level", FT_UINT8, BASE_DEC, VALS(aggregation_level_vals), 0x0,
3775 { &hf_mac_lte_context_phy_dl_mcs_index,
3777 "mac-lte.dl-phy.mcs-index", FT_UINT8, BASE_DEC, 0, 0x0,
3781 { &hf_mac_lte_context_phy_dl_redundancy_version_index,
3783 "mac-lte.dl-phy.rv-index", FT_UINT8, BASE_DEC, 0, 0x0,
3787 { &hf_mac_lte_context_phy_dl_retx,
3789 "mac-lte.dl-phy.dl-retx", FT_BOOLEAN, BASE_DEC, NULL, 0x0,
3793 { &hf_mac_lte_context_phy_dl_resource_block_length,
3795 "mac-lte.dl-phy.rb-length", FT_UINT8, BASE_DEC, 0, 0x0,
3799 { &hf_mac_lte_context_phy_dl_crc_status,
3801 "mac-lte.dl-phy.crc-status", FT_UINT8, BASE_DEC, VALS(crc_status_vals), 0x0,
3805 { &hf_mac_lte_context_phy_dl_harq_id,
3807 "mac-lte.dl-phy.harq-id", FT_UINT8, BASE_DEC, 0, 0x0,
3811 { &hf_mac_lte_context_phy_dl_ndi,
3813 "mac-lte.dl-phy.ndi", FT_UINT8, BASE_DEC, 0, 0x0,
3814 "New Data Indicator", HFILL
3817 { &hf_mac_lte_context_phy_dl_tb,
3819 "mac-lte.dl-phy.tb", FT_UINT8, BASE_DEC, 0, 0x0,
3820 "Transport Block (antenna #)", HFILL
3824 /* Out-of-band events */
3825 { &hf_mac_lte_oob_send_preamble,
3827 "mac-lte.preamble-sent", FT_STRING, BASE_NONE, NULL, 0x0,
3831 { &hf_mac_lte_oob_send_sr,
3832 { "Scheduling Request sent",
3833 "mac-lte.sr-req", FT_NONE, BASE_NONE, NULL, 0x0,
3837 { &hf_mac_lte_oob_sr_failure,
3838 { "Scheduling Request failure",
3839 "mac-lte.sr-failure", FT_NONE, BASE_NONE, NULL, 0x0,
3844 /*******************************************/
3845 /* MAC shared channel header fields */
3846 { &hf_mac_lte_ulsch,
3848 "mac-lte.ulsch", FT_STRING, BASE_NONE, NULL, 0x0,
3852 { &hf_mac_lte_ulsch_header,
3854 "mac-lte.ulsch.header", FT_STRING, BASE_NONE, NULL, 0x0,
3858 { &hf_mac_lte_dlsch_header,
3860 "mac-lte.dlsch.header", FT_STRING, BASE_NONE, NULL, 0x0,
3864 { &hf_mac_lte_dlsch,
3866 "mac-lte.dlsch", FT_STRING, BASE_NONE, NULL, 0x0,
3870 { &hf_mac_lte_sch_subheader,
3872 "mac-lte.sch.subheader", FT_STRING, BASE_NONE, NULL, 0x0,
3876 { &hf_mac_lte_sch_reserved,
3877 { "SCH reserved bits",
3878 "mac-lte.sch.reserved", FT_UINT8, BASE_HEX, NULL, 0xc0,
3882 { &hf_mac_lte_sch_extended,
3884 "mac-lte.sch.extended", FT_UINT8, BASE_HEX, 0, 0x20,
3885 "Extension - i.e. further headers after this one", HFILL
3888 { &hf_mac_lte_dlsch_lcid,
3890 "mac-lte.dlsch.lcid", FT_UINT8, BASE_HEX, VALS(dlsch_lcid_vals), 0x1f,
3891 "DL-SCH Logical Channel Identifier", HFILL
3894 { &hf_mac_lte_ulsch_lcid,
3896 "mac-lte.ulsch.lcid", FT_UINT8, BASE_HEX, VALS(ulsch_lcid_vals), 0x1f,
3897 "UL-SCH Logical Channel Identifier", HFILL
3900 { &hf_mac_lte_sch_format,
3902 "mac-lte.sch.format", FT_UINT8, BASE_HEX, VALS(format_vals), 0x80,
3906 { &hf_mac_lte_sch_length,
3908 "mac-lte.sch.length", FT_UINT16, BASE_DEC, 0, 0x0,
3909 "Length of MAC SDU or MAC control element", HFILL
3912 { &hf_mac_lte_sch_header_only,
3913 { "MAC PDU Header only",
3914 "mac-lte.sch.header-only", FT_UINT8, BASE_DEC, VALS(header_only_vals), 0x0,
3919 /********************************/
3921 { &hf_mac_lte_sch_sdu,
3923 "mac-lte.sch.sdu", FT_BYTES, BASE_NONE, 0, 0x0,
3924 "Shared channel SDU", HFILL
3927 { &hf_mac_lte_bch_pdu,
3929 "mac-lte.bch.pdu", FT_BYTES, BASE_NONE, 0, 0x0,
3933 { &hf_mac_lte_pch_pdu,
3935 "mac-lte.pch.pdu", FT_BYTES, BASE_NONE, 0, 0x0,
3939 { &hf_mac_lte_predefined_pdu,
3940 { "Predefined data",
3941 "mac-lte.predefined-data", FT_BYTES, BASE_NONE, 0, 0x0,
3942 "Predefined test data", HFILL
3945 { &hf_mac_lte_raw_pdu,
3947 "mac-lte.raw-data", FT_BYTES, BASE_NONE, 0, 0x0,
3948 "Raw bytes of PDU (e.g. if CRC error)", HFILL
3951 { &hf_mac_lte_padding_data,
3953 "mac-lte.padding-data", FT_BYTES, BASE_NONE, 0, 0x0,
3957 { &hf_mac_lte_padding_length,
3959 "mac-lte.padding-length", FT_INT32, BASE_DEC, 0, 0x0,
3960 "Length of padding data not included at end of frame", HFILL
3966 /*********************************/
3970 "mac-lte.rar", FT_NONE, BASE_NONE, NULL, 0x0,
3974 { &hf_mac_lte_rar_headers,
3976 "mac-lte.rar.headers", FT_STRING, BASE_NONE, NULL, 0x0,
3980 { &hf_mac_lte_rar_header,
3982 "mac-lte.rar.header", FT_STRING, BASE_NONE, NULL, 0x0,
3986 { &hf_mac_lte_rar_extension,
3988 "mac-lte.rar.e", FT_UINT8, BASE_HEX, 0, 0x80,
3989 "Extension - i.e. further RAR headers after this one", HFILL
3992 { &hf_mac_lte_rar_t,
3994 "mac-lte.rar.t", FT_UINT8, BASE_HEX, VALS(rar_type_vals), 0x40,
3995 "Type field indicating whether the payload is RAPID or BI", HFILL
3998 { &hf_mac_lte_rar_bi,
4000 "mac-lte.rar.bi", FT_UINT8, BASE_HEX, VALS(rar_bi_vals), 0x0f,
4001 "Backoff Indicator (ms)", HFILL
4004 { &hf_mac_lte_rar_rapid,
4006 "mac-lte.rar.rapid", FT_UINT8, BASE_HEX_DEC, 0, 0x3f,
4007 "Random Access Preamble IDentifier", HFILL
4010 { &hf_mac_lte_rar_reserved,
4012 "mac-lte.rar.reserved", FT_UINT8, BASE_HEX, 0, 0x30,
4013 "Reserved bits in RAR header - should be 0", HFILL
4017 { &hf_mac_lte_rar_body,
4019 "mac-lte.rar.body", FT_STRING, BASE_NONE, NULL, 0x0,
4023 { &hf_mac_lte_rar_reserved2,
4025 "mac-lte.rar.reserved2", FT_UINT8, BASE_HEX, 0, 0x80,
4026 "Reserved bit in RAR body - should be 0", HFILL
4029 { &hf_mac_lte_rar_ta,
4031 "mac-lte.rar.ta", FT_UINT16, BASE_DEC, 0, 0x7ff0,
4032 "Required adjustment to uplink transmission timing", HFILL
4035 { &hf_mac_lte_rar_ul_grant,
4037 "mac-lte.rar.ul-grant", FT_UINT24, BASE_DEC, 0, 0x0fffff,
4038 "Size of UL Grant", HFILL
4041 { &hf_mac_lte_rar_ul_grant_hopping,
4043 "mac-lte.rar.ul-grant.hopping", FT_UINT8, BASE_DEC, 0, 0x08,
4047 { &hf_mac_lte_rar_ul_grant_fsrba,
4048 { "Fixed sized resource block assignment",
4049 "mac-lte.rar.ul-grant.fsrba", FT_UINT16, BASE_DEC, 0, 0x07fe,
4053 { &hf_mac_lte_rar_ul_grant_tmcs,
4054 { "Truncated Modulation and coding scheme",
4055 "mac-lte.rar.ul-grant.tmcs", FT_UINT16, BASE_DEC, 0, 0x01e0,
4059 { &hf_mac_lte_rar_ul_grant_tcsp,
4060 { "TPC command for scheduled PUSCH",
4061 "mac-lte.rar.ul-grant.tcsp", FT_UINT8, BASE_DEC, 0, 0x01c,
4065 { &hf_mac_lte_rar_ul_grant_ul_delay,
4067 "mac-lte.rar.ul-grant.ul-delay", FT_UINT8, BASE_DEC, 0, 0x02,
4071 { &hf_mac_lte_rar_ul_grant_cqi_request,
4073 "mac-lte.rar.ul-grant.cqi-request", FT_UINT8, BASE_DEC, 0, 0x01,
4077 { &hf_mac_lte_rar_temporary_crnti,
4078 { "Temporary C-RNTI",
4079 "mac-lte.rar.temporary-crnti", FT_UINT16, BASE_DEC, 0, 0x0,
4084 /**********************/
4085 /* Control PDU fields */
4086 { &hf_mac_lte_control_bsr,
4088 "mac-lte.control.bsr", FT_STRING, BASE_NONE, 0, 0x0,
4089 "Buffer Status Report", HFILL
4092 { &hf_mac_lte_control_bsr_lcg_id,
4093 { "Logical Channel Group ID",
4094 "mac-lte.control.bsr.lcg-id", FT_UINT8, BASE_DEC, 0, 0xc0,
4098 { &hf_mac_lte_control_short_bsr_buffer_size,
4100 "mac-lte.control.bsr.buffer-size", FT_UINT8, BASE_DEC, VALS(buffer_size_vals), 0x3f,
4101 "Buffer Size available in all channels in group", HFILL
4104 { &hf_mac_lte_control_long_bsr_buffer_size_0,
4106 "mac-lte.control.bsr.buffer-size-0", FT_UINT8, BASE_DEC, VALS(buffer_size_vals), 0xfc,
4107 "Buffer Size available in logical channel group 0", HFILL
4110 { &hf_mac_lte_control_long_bsr_buffer_size_1,
4112 "mac-lte.control.bsr.buffer-size-1", FT_UINT16, BASE_DEC, VALS(buffer_size_vals), 0x03f0,
4113 "Buffer Size available in logical channel group 1", HFILL
4116 { &hf_mac_lte_control_long_bsr_buffer_size_2,
4118 "mac-lte.control.bsr.buffer-size-2", FT_UINT16, BASE_DEC, VALS(buffer_size_vals), 0x0fc0,
4119 "Buffer Size available in logical channel group 2", HFILL
4122 { &hf_mac_lte_control_long_bsr_buffer_size_3,
4124 "mac-lte.control.bsr.buffer-size-3", FT_UINT8, BASE_DEC, VALS(buffer_size_vals), 0x3f,
4125 "Buffer Size available in logical channel group 3", HFILL
4128 { &hf_mac_lte_control_crnti,
4130 "mac-lte.control.crnti", FT_UINT16, BASE_DEC, 0, 0x0,
4131 "C-RNTI for the UE", HFILL
4134 { &hf_mac_lte_control_timing_advance,
4136 "mac-lte.control.timing-advance", FT_UINT8, BASE_DEC, 0, 0x3f,
4137 "Timing Advance (0-1282 - see 36.213, 4.2.3)", HFILL
4140 { &hf_mac_lte_control_timing_advance_reserved,
4142 "mac-lte.control.timing-advance.reserved", FT_UINT8, BASE_HEX, 0, 0xc0,
4143 "Reserved bits", HFILL
4146 { &hf_mac_lte_control_ue_contention_resolution,
4147 { "UE Contention Resolution",
4148 "mac-lte.control.ue-contention-resolution", FT_STRING, BASE_NONE, 0, 0x0,
4152 { &hf_mac_lte_control_ue_contention_resolution_identity,
4153 { "UE Contention Resolution Identity",
4154 "mac-lte.control.ue-contention-resolution.identity", FT_BYTES, BASE_NONE, 0, 0x0,
4158 { &hf_mac_lte_control_ue_contention_resolution_msg3,
4160 "mac-lte.control.ue-contention-resolution.msg3", FT_FRAMENUM, BASE_NONE, 0, 0x0,
4164 { &hf_mac_lte_control_ue_contention_resolution_msg3_matched,
4165 { "UE Contention Resolution Matches Msg3",
4166 "mac-lte.control.ue-contention-resolution.matches-msg3", FT_BOOLEAN, BASE_NONE, 0, 0x0,
4170 { &hf_mac_lte_control_ue_contention_resolution_time_since_msg3,
4171 { "Time since Msg3",
4172 "mac-lte.control.ue-contention-resolution.time-since-msg3", FT_UINT32, BASE_DEC, 0, 0x0,
4173 "Time in ms since corresponding Msg3", HFILL
4177 { &hf_mac_lte_control_power_headroom,
4179 "mac-lte.control.power-headroom", FT_STRING, BASE_NONE, 0, 0x0,
4183 { &hf_mac_lte_control_power_headroom_reserved,
4185 "mac-lte.control.power-headroom.reserved", FT_UINT8, BASE_DEC, 0, 0xc0,
4186 "Reserved bits, should be 0", HFILL
4189 { &hf_mac_lte_control_power_headroom_level,
4190 { "Power Headroom Level",
4191 "mac-lte.control.power-headroom.level", FT_UINT8, BASE_DEC,
4192 VALS(power_headroom_size_vals), 0x3f, "Power Headroom Level in dB", HFILL
4196 { &hf_mac_lte_control_padding,
4198 "mac-lte.control.padding", FT_NONE, BASE_NONE, 0, 0x0,
4203 /* Generated fields */
4204 { &hf_mac_lte_suspected_dl_retx_original_frame,
4205 { "Frame with previous tx",
4206 "mac-lte.dlsch.retx.original-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
4210 { &hf_mac_lte_suspected_dl_retx_time_since_previous_frame,
4211 { "Time since previous tx (ms)",
4212 "mac-lte.dlsch.retx.time-since-previous", FT_UINT16, BASE_DEC, 0, 0x0,
4218 { &hf_mac_lte_ul_harq_resend_original_frame,
4219 { "Frame with previous tx",
4220 "mac-lte.ulsch.retx.original-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
4224 { &hf_mac_lte_ul_harq_resend_time_since_previous_frame,
4225 { "Time since previous tx (ms)",
4226 "mac-lte.ulsch.retx.time-since-previous", FT_UINT16, BASE_DEC, 0, 0x0,
4232 { &hf_mac_lte_grant_answering_sr,
4233 { "First Grant Following SR from",
4234 "mac-lte.ulsch.grant-answering-sr", FT_FRAMENUM, BASE_NONE, 0, 0x0,
4238 { &hf_mac_lte_failure_answering_sr,
4239 { "SR which failed",
4240 "mac-lte.ulsch.failure-answering-sr", FT_FRAMENUM, BASE_NONE, 0, 0x0,
4244 { &hf_mac_lte_sr_leading_to_failure,
4246 "mac-lte.ulsch.failure-answering-sr-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
4250 { &hf_mac_lte_sr_leading_to_grant,
4251 { "This SR results in a grant here",
4252 "mac-lte.ulsch.grant-answering-sr-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
4256 { &hf_mac_lte_sr_invalid_event,
4258 "mac-lte.ulsch.sr-invalid-event", FT_NONE, BASE_NONE, 0, 0x0,
4262 { &hf_mac_lte_sr_time_since_request,
4263 { "Time since SR (ms)",
4264 "mac-lte.ulsch.time-since-sr", FT_UINT32, BASE_DEC, 0, 0x0,
4268 { &hf_mac_lte_sr_time_until_answer,
4269 { "Time until answer (ms)",
4270 "mac-lte.ulsch.time-until-sr-answer", FT_UINT32, BASE_DEC, 0, 0x0,
4277 static gint *ett[] =
4280 &ett_mac_lte_context,
4281 &ett_mac_lte_phy_context,
4282 &ett_mac_lte_rar_headers,
4283 &ett_mac_lte_rar_header,
4284 &ett_mac_lte_rar_body,
4285 &ett_mac_lte_rar_ul_grant,
4286 &ett_mac_lte_ulsch_header,
4287 &ett_mac_lte_dlsch_header,
4288 &ett_mac_lte_sch_subheader,
4292 &ett_mac_lte_contention_resolution,
4293 &ett_mac_lte_power_headroom,
4297 static enum_val_t show_info_col_vals[] = {
4298 {"show-phy", "PHY Info", ShowPHYLayer},
4299 {"show-mac", "MAC Info", ShowMACLayer},
4300 {"show-rlc", "RLC Info", ShowRLCLayer},
4304 static enum_val_t lcid_drb_source_vals[] = {
4305 {"from-static-stable", "From static table", FromStaticTable},
4306 {"from-configuration-protocol", "From configuration protocol", FromConfigurationProtocol},
4311 module_t *mac_lte_module;
4313 static uat_field_t lcid_drb_mapping_flds[] = {
4314 UAT_FLD_VS(lcid_drb_mappings, lcid, "lcid", drb_lcid_vals, "The MAC LCID"),
4315 UAT_FLD_DEC(lcid_drb_mappings, drbid,"drb id (1-32)", "Identifier of logical data channel"),
4316 UAT_FLD_VS(lcid_drb_mappings, channel_type, "RLC Channel Type", rlc_channel_type_vals, "The MAC LCID"),
4320 /* Register protocol. */
4321 proto_mac_lte = proto_register_protocol("MAC-LTE", "MAC-LTE", "mac-lte");
4322 proto_register_field_array(proto_mac_lte, hf, array_length(hf));
4323 proto_register_subtree_array(ett, array_length(ett));
4325 /* Allow other dissectors to find this one by name. */
4326 register_dissector("mac-lte", dissect_mac_lte, proto_mac_lte);
4328 /* Register the tap name */
4329 mac_lte_tap = register_tap("mac-lte");
4332 mac_lte_module = prefs_register_protocol(proto_mac_lte, NULL);
4334 /* Obsolete preferences */
4335 prefs_register_obsolete_preference(mac_lte_module, "single_rar");
4336 prefs_register_obsolete_preference(mac_lte_module, "check_reserved_bits");
4337 prefs_register_obsolete_preference(mac_lte_module, "decode_rar_ul_grant");
4338 prefs_register_obsolete_preference(mac_lte_module, "show_rlc_info_column");
4339 prefs_register_obsolete_preference(mac_lte_module, "attempt_to_detect_dl_harq_resend");
4340 prefs_register_obsolete_preference(mac_lte_module, "attempt_to_track_ul_harq_resend");
4342 prefs_register_uint_preference(mac_lte_module, "retx_count_warn",
4343 "Number of Re-Transmits before expert warning triggered",
4344 "Number of Re-Transmits before expert warning triggered",
4345 10, &global_mac_lte_retx_counter_trigger);
4347 prefs_register_bool_preference(mac_lte_module, "attempt_rrc_decode",
4348 "Attempt to decode BCH, PCH and CCCH data using LTE RRC dissector",
4349 "Attempt to decode BCH, PCH and CCCH data using LTE RRC dissector",
4350 &global_mac_lte_attempt_rrc_decode);
4352 prefs_register_bool_preference(mac_lte_module, "attempt_to_dissect_crc_failures",
4353 "Dissect frames that have failed CRC check",
4354 "Attempt to dissect frames that have failed CRC check",
4355 &global_mac_lte_dissect_crc_failures);
4357 prefs_register_bool_preference(mac_lte_module, "heuristic_mac_lte_over_udp",
4358 "Try Heuristic LTE-MAC over UDP framing",
4359 "When enabled, use heuristic dissector to find MAC-LTE frames sent with "
4361 &global_mac_lte_heur);
4363 prefs_register_bool_preference(mac_lte_module, "attempt_to_dissect_srb_sdus",
4364 "Attempt to dissect LCID 1&2 as srb1&2",
4365 "Will call LTE RLC dissector with standard settings as per RRC spec",
4366 &global_mac_lte_attempt_srb_decode);
4368 prefs_register_enum_preference(mac_lte_module, "lcid_to_drb_mapping_source",
4369 "Source of LCID -> drb channel settings",
4370 "Set whether LCID -> drb Table is taken from static table (below) or from "
4371 "info learned from control protocol (e.g. RRC)",
4372 &global_mac_lte_lcid_drb_source, lcid_drb_source_vals, FALSE);
4374 lcid_drb_mappings_uat = uat_new("Static LCID -> drb Table",
4375 sizeof(lcid_drb_mapping_t),
4378 (void*) &lcid_drb_mappings,
4379 &num_lcid_drb_mappings,
4381 "", /* TODO: is this ref to help manual? */
4382 lcid_drb_mapping_copy_cb,
4386 lcid_drb_mapping_flds );
4388 prefs_register_uat_preference(mac_lte_module,
4390 "LCID -> DRB Mappings Table",
4391 "A table that maps from configurable lcids -> RLC logical channels",
4392 lcid_drb_mappings_uat);
4394 prefs_register_uint_preference(mac_lte_module, "bsr_warn_threshold",
4395 "BSR size when warning should be issued (0 - 63)",
4396 "If any BSR report is >= this number, an expert warning will be added",
4397 10, &global_mac_lte_bsr_warn_threshold);
4399 prefs_register_bool_preference(mac_lte_module, "track_sr",
4400 "Track status of SRs within UEs",
4401 "Track status of SRs, providing links between requests, failure indications and grants",
4402 &global_mac_lte_track_sr);
4404 prefs_register_enum_preference(mac_lte_module, "layer_to_show",
4405 "Which layer info to show in Info column",
4406 "Can show PHY, MAC or RLC layer info in Info column",
4407 &global_mac_lte_layer_to_show, show_info_col_vals, FALSE);
4409 register_init_routine(&mac_lte_init_protocol);
4413 /* Set LCID -> RLC channel mappings from signalling protocol (i.e. RRC or similar).
4414 TODO: not using UEID yet - assume all UEs configured identically... */
4415 void set_mac_lte_channel_mapping(guint16 ueid _U_, guint8 lcid,
4416 guint8 srbid, guint8 drbid,
4417 guint8 rlcMode, guint8 um_sn_length)
4419 /* Don't bother setting srb details - we just assume AM */
4424 /* Ignore if LCID is out of range */
4425 if ((lcid < 3) || (lcid > 10)) {
4429 /* Set array entry */
4430 dynamic_lcid_drb_mapping[lcid].valid = TRUE;
4431 dynamic_lcid_drb_mapping[lcid].drbid = drbid;
4434 dynamic_lcid_drb_mapping[lcid].channel_type = rlcAM;
4437 if (um_sn_length == 5) {
4438 dynamic_lcid_drb_mapping[lcid].channel_type = rlcUM5;
4441 dynamic_lcid_drb_mapping[lcid].channel_type = rlcUM10;
4450 /* Function to be called from outside this module (e.g. in a plugin) to get per-packet data */
4451 mac_lte_info *get_mac_lte_proto_data(packet_info *pinfo)
4453 return p_get_proto_data(pinfo->fd, proto_mac_lte);
4456 /* Function to be called from outside this module (e.g. in a plugin) to set per-packet data */
4457 void set_mac_lte_proto_data(packet_info *pinfo, mac_lte_info *p_mac_lte_info)
4459 p_add_proto_data(pinfo->fd, proto_mac_lte, p_mac_lte_info);
4463 proto_reg_handoff_mac_lte(void)
4465 static dissector_handle_t mac_lte_handle;
4466 if (!mac_lte_handle) {
4467 mac_lte_handle = find_dissector("mac-lte");
4469 /* Add as a heuristic UDP dissector */
4470 heur_dissector_add("udp", dissect_mac_lte_heur, proto_mac_lte);