de8d2d76e1449489854f58da156e46100da979f9
[metze/wireshark/wip.git] / epan / dissectors / packet-mac-lte.c
1 /* Routines for LTE MAC disassembly
2  *
3  * Martin Mathieson
4  *
5  * $Id$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
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.
15  *
16
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #include "config.h"
23
24 #include <string.h>
25
26 #include <epan/packet.h>
27 #include <epan/exceptions.h>
28 #include <epan/expert.h>
29 #include <epan/prefs.h>
30 #include <epan/tap.h>
31 #include <epan/uat.h>
32 #include <epan/wmem/wmem.h>
33
34 #include "packet-mac-lte.h"
35 #include "packet-rlc-lte.h"
36
37 void proto_register_mac_lte(void);
38 void proto_reg_handoff_mac_lte(void);
39
40 /* Described in:
41  * 3GPP TS 36.321 Evolved Universal Terrestrial Radio Access (E-UTRA)
42  *                Medium Access Control (MAC) protocol specification v11.0.0
43  */
44
45
46 /* Initialize the protocol and registered fields. */
47 int proto_mac_lte = -1;
48
49 static int mac_lte_tap = -1;
50
51 static dissector_handle_t rlc_lte_handle;
52
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_sysframe_number = -1;
61 static int hf_mac_lte_context_subframe_number = -1;
62 static int hf_mac_lte_context_grant_subframe_number = -1;
63 static int hf_mac_lte_context_predefined_frame = -1;
64 static int hf_mac_lte_context_length = -1;
65 static int hf_mac_lte_context_ul_grant_size = -1;
66 static int hf_mac_lte_context_bch_transport_channel = -1;
67 static int hf_mac_lte_context_retx_count = -1;
68 static int hf_mac_lte_context_retx_reason = -1;
69 static int hf_mac_lte_context_crc_status = -1;
70 static int hf_mac_lte_context_carrier_id = -1;
71
72 static int hf_mac_lte_context_rapid = -1;
73 static int hf_mac_lte_context_rach_attempt_number = -1;
74
75 /* Inferred context */
76 static int hf_mac_lte_ues_ul_per_tti = -1;
77 static int hf_mac_lte_ues_dl_per_tti = -1;
78
79
80 /* Extra PHY context */
81 static int hf_mac_lte_context_phy_ul = -1;
82 static int hf_mac_lte_context_phy_ul_modulation_type = -1;
83 static int hf_mac_lte_context_phy_ul_tbs_index = -1;
84 static int hf_mac_lte_context_phy_ul_resource_block_length = -1;
85 static int hf_mac_lte_context_phy_ul_resource_block_start = -1;
86 static int hf_mac_lte_context_phy_ul_harq_id = -1;
87 static int hf_mac_lte_context_phy_ul_ndi = -1;
88
89 static int hf_mac_lte_context_phy_dl = -1;
90 static int hf_mac_lte_context_phy_dl_dci_format = -1;
91 static int hf_mac_lte_context_phy_dl_resource_allocation_type = -1;
92 static int hf_mac_lte_context_phy_dl_aggregation_level = -1;
93 static int hf_mac_lte_context_phy_dl_mcs_index = -1;
94 static int hf_mac_lte_context_phy_dl_redundancy_version_index = -1;
95 static int hf_mac_lte_context_phy_dl_retx = -1;
96 static int hf_mac_lte_context_phy_dl_resource_block_length = -1;
97 static int hf_mac_lte_context_phy_dl_harq_id = -1;
98 static int hf_mac_lte_context_phy_dl_ndi = -1;
99 static int hf_mac_lte_context_phy_dl_tb = -1;
100
101
102 /* Out-of-band events */
103 static int hf_mac_lte_oob_send_preamble = -1;
104 static int hf_mac_lte_number_of_srs = -1;
105
106 /* MAC SCH/MCH header fields */
107 static int hf_mac_lte_ulsch = -1;
108 static int hf_mac_lte_ulsch_header = -1;
109 static int hf_mac_lte_dlsch = -1;
110 static int hf_mac_lte_dlsch_header = -1;
111 static int hf_mac_lte_sch_subheader = -1;
112 static int hf_mac_lte_mch = -1;
113 static int hf_mac_lte_mch_header = -1;
114 static int hf_mac_lte_mch_subheader = -1;
115
116 static int hf_mac_lte_sch_reserved = -1;
117 static int hf_mac_lte_dlsch_lcid = -1;
118 static int hf_mac_lte_ulsch_lcid = -1;
119 static int hf_mac_lte_sch_extended = -1;
120 static int hf_mac_lte_sch_format = -1;
121 static int hf_mac_lte_sch_length = -1;
122 static int hf_mac_lte_mch_reserved = -1;
123 static int hf_mac_lte_mch_lcid = -1;
124 static int hf_mac_lte_mch_extended = -1;
125 static int hf_mac_lte_mch_format = -1;
126 static int hf_mac_lte_mch_length = -1;
127
128 static int hf_mac_lte_sch_header_only = -1;
129 static int hf_mac_lte_mch_header_only = -1;
130
131 /* Data */
132 static int hf_mac_lte_sch_sdu = -1;
133 static int hf_mac_lte_mch_sdu = -1;
134 static int hf_mac_lte_bch_pdu = -1;
135 static int hf_mac_lte_pch_pdu = -1;
136 static int hf_mac_lte_predefined_pdu = -1;
137 static int hf_mac_lte_raw_pdu = -1;
138 static int hf_mac_lte_padding_data = -1;
139 static int hf_mac_lte_padding_length = -1;
140
141
142 /* RAR fields */
143 static int hf_mac_lte_rar = -1;
144 static int hf_mac_lte_rar_headers = -1;
145 static int hf_mac_lte_rar_header = -1;
146 static int hf_mac_lte_rar_extension = -1;
147 static int hf_mac_lte_rar_t = -1;
148 static int hf_mac_lte_rar_bi = -1;
149 static int hf_mac_lte_rar_rapid = -1;
150 static int hf_mac_lte_rar_no_of_rapids = -1;
151 static int hf_mac_lte_rar_reserved = -1;
152 static int hf_mac_lte_rar_body = -1;
153 static int hf_mac_lte_rar_reserved2 = -1;
154 static int hf_mac_lte_rar_ta = -1;
155 static int hf_mac_lte_rar_ul_grant = -1;
156 static int hf_mac_lte_rar_ul_grant_hopping = -1;
157 static int hf_mac_lte_rar_ul_grant_fsrba = -1;
158 static int hf_mac_lte_rar_ul_grant_tmcs = -1;
159 static int hf_mac_lte_rar_ul_grant_tcsp = -1;
160 static int hf_mac_lte_rar_ul_grant_ul_delay = -1;
161 static int hf_mac_lte_rar_ul_grant_cqi_request = -1;
162 static int hf_mac_lte_rar_temporary_crnti = -1;
163
164 /* Common channel control values */
165 static int hf_mac_lte_control_bsr = -1;
166 static int hf_mac_lte_control_bsr_lcg_id = -1;
167 static int hf_mac_lte_control_short_bsr_buffer_size = -1;
168 static int hf_mac_lte_control_long_bsr_buffer_size_0 = -1;
169 static int hf_mac_lte_control_long_bsr_buffer_size_1 = -1;
170 static int hf_mac_lte_control_long_bsr_buffer_size_2 = -1;
171 static int hf_mac_lte_control_long_bsr_buffer_size_3 = -1;
172 static int hf_mac_lte_control_short_ext_bsr_buffer_size = -1;
173 static int hf_mac_lte_control_long_ext_bsr_buffer_size_0 = -1;
174 static int hf_mac_lte_control_long_ext_bsr_buffer_size_1 = -1;
175 static int hf_mac_lte_control_long_ext_bsr_buffer_size_2 = -1;
176 static int hf_mac_lte_control_long_ext_bsr_buffer_size_3 = -1;
177 static int hf_mac_lte_control_crnti = -1;
178 static int hf_mac_lte_control_timing_advance = -1;
179 static int hf_mac_lte_control_timing_advance_group_id = -1;
180 static int hf_mac_lte_control_timing_advance_command = -1;
181 static int hf_mac_lte_control_ue_contention_resolution = -1;
182 static int hf_mac_lte_control_ue_contention_resolution_identity = -1;
183 static int hf_mac_lte_control_ue_contention_resolution_msg3 = -1;
184 static int hf_mac_lte_control_ue_contention_resolution_msg3_matched = -1;
185 static int hf_mac_lte_control_ue_contention_resolution_time_since_msg3 = -1;
186 static int hf_mac_lte_control_power_headroom = -1;
187 static int hf_mac_lte_control_power_headroom_reserved = -1;
188 static int hf_mac_lte_control_power_headroom_level = -1;
189 static int hf_mac_lte_control_ext_power_headroom = -1;
190 static int hf_mac_lte_control_ext_power_headroom_c7 = -1;
191 static int hf_mac_lte_control_ext_power_headroom_c6 = -1;
192 static int hf_mac_lte_control_ext_power_headroom_c5 = -1;
193 static int hf_mac_lte_control_ext_power_headroom_c4 = -1;
194 static int hf_mac_lte_control_ext_power_headroom_c3 = -1;
195 static int hf_mac_lte_control_ext_power_headroom_c2 = -1;
196 static int hf_mac_lte_control_ext_power_headroom_c1 = -1;
197 static int hf_mac_lte_control_ext_power_headroom_reserved = -1;
198 static int hf_mac_lte_control_ext_power_headroom_power_backoff = -1;
199 static int hf_mac_lte_control_ext_power_headroom_value = -1;
200 static int hf_mac_lte_control_ext_power_headroom_level = -1;
201 static int hf_mac_lte_control_ext_power_headroom_reserved2 = -1;
202 static int hf_mac_lte_control_ext_power_headroom_pcmaxc = -1;
203 static int hf_mac_lte_control_activation_deactivation = -1;
204 static int hf_mac_lte_control_activation_deactivation_c7 = -1;
205 static int hf_mac_lte_control_activation_deactivation_c6 = -1;
206 static int hf_mac_lte_control_activation_deactivation_c5 = -1;
207 static int hf_mac_lte_control_activation_deactivation_c4 = -1;
208 static int hf_mac_lte_control_activation_deactivation_c3 = -1;
209 static int hf_mac_lte_control_activation_deactivation_c2 = -1;
210 static int hf_mac_lte_control_activation_deactivation_c1 = -1;
211 static int hf_mac_lte_control_activation_deactivation_reserved = -1;
212 static int hf_mac_lte_control_mch_scheduling_info = -1;
213 static int hf_mac_lte_control_mch_scheduling_info_lcid = -1;
214 static int hf_mac_lte_control_mch_scheduling_info_stop_mtch = -1;
215
216 static int hf_mac_lte_dl_harq_resend_original_frame = -1;
217 static int hf_mac_lte_dl_harq_resend_time_since_previous_frame = -1;
218 static int hf_mac_lte_dl_harq_resend_next_frame = -1;
219 static int hf_mac_lte_dl_harq_resend_time_until_next_frame = -1;
220
221 static int hf_mac_lte_ul_harq_resend_original_frame = -1;
222 static int hf_mac_lte_ul_harq_resend_time_since_previous_frame = -1;
223 static int hf_mac_lte_ul_harq_resend_next_frame = -1;
224 static int hf_mac_lte_ul_harq_resend_time_until_next_frame = -1;
225
226 static int hf_mac_lte_grant_answering_sr = -1;
227 static int hf_mac_lte_failure_answering_sr = -1;
228 static int hf_mac_lte_sr_leading_to_failure = -1;
229 static int hf_mac_lte_sr_leading_to_grant = -1;
230 static int hf_mac_lte_sr_time_since_request = -1;
231 static int hf_mac_lte_sr_time_until_answer = -1;
232
233 static int hf_mac_lte_drx_config = -1;
234 static int hf_mac_lte_drx_config_frame_num = -1;
235 static int hf_mac_lte_drx_config_previous_frame_num = -1;
236 static int hf_mac_lte_drx_config_long_cycle = -1;
237 static int hf_mac_lte_drx_config_cycle_offset = -1;
238 static int hf_mac_lte_drx_config_onduration_timer = -1;
239 static int hf_mac_lte_drx_config_inactivity_timer = -1;
240 static int hf_mac_lte_drx_config_retransmission_timer = -1;
241 static int hf_mac_lte_drx_config_short_cycle = -1;
242 static int hf_mac_lte_drx_config_short_cycle_timer = -1;
243
244 static int hf_mac_lte_drx_state = -1;
245 static int hf_mac_lte_drx_state_long_cycle_offset = -1;
246 static int hf_mac_lte_drx_state_long_cycle_on = -1;
247 static int hf_mac_lte_drx_state_short_cycle_offset = -1;
248 static int hf_mac_lte_drx_state_short_cycle_on = -1;
249 static int hf_mac_lte_drx_state_inactivity_remaining = -1;
250 static int hf_mac_lte_drx_state_onduration_remaining = -1;
251 static int hf_mac_lte_drx_state_retransmission_remaining = -1;
252 static int hf_mac_lte_drx_state_rtt_remaining = -1;
253 static int hf_mac_lte_drx_state_short_cycle_remaining = -1;
254
255 /* Subtrees. */
256 static int ett_mac_lte = -1;
257 static int ett_mac_lte_context = -1;
258 static int ett_mac_lte_phy_context = -1;
259 static int ett_mac_lte_ulsch_header = -1;
260 static int ett_mac_lte_dlsch_header = -1;
261 static int ett_mac_lte_mch_header = -1;
262 static int ett_mac_lte_sch_subheader = -1;
263 static int ett_mac_lte_mch_subheader = -1;
264 static int ett_mac_lte_rar_headers = -1;
265 static int ett_mac_lte_rar_header = -1;
266 static int ett_mac_lte_rar_body = -1;
267 static int ett_mac_lte_rar_ul_grant = -1;
268 static int ett_mac_lte_bsr = -1;
269 static int ett_mac_lte_bch = -1;
270 static int ett_mac_lte_pch = -1;
271 static int ett_mac_lte_activation_deactivation = -1;
272 static int ett_mac_lte_contention_resolution = -1;
273 static int ett_mac_lte_timing_advance = -1;
274 static int ett_mac_lte_power_headroom = -1;
275 static int ett_mac_lte_extended_power_headroom = -1;
276 static int ett_mac_lte_extended_power_headroom_cell = -1;
277 static int ett_mac_lte_mch_scheduling_info = -1;
278 static int ett_mac_lte_oob = -1;
279 static int ett_mac_lte_drx_config = -1;
280 static int ett_mac_lte_drx_state = -1;
281
282 static expert_field ei_mac_lte_context_rnti_type = EI_INIT;
283 static expert_field ei_mac_lte_lcid_unexpected = EI_INIT;
284 static expert_field ei_mac_lte_ul_mac_frame_retx = EI_INIT;
285 static expert_field ei_mac_lte_oob_sr_failure = EI_INIT;
286 static expert_field ei_mac_lte_control_timing_advance_command_correction_needed = EI_INIT;
287 static expert_field ei_mac_lte_sch_header_only = EI_INIT;
288 static expert_field ei_mac_lte_control_timing_advance_command_no_correction = EI_INIT;
289 static expert_field ei_mac_lte_rar_timing_advance_not_zero_note = EI_INIT;
290 static expert_field ei_mac_lte_padding_data_start_and_end = EI_INIT;
291 static expert_field ei_mac_lte_bch_pdu = EI_INIT;
292 static expert_field ei_mac_lte_rach_preamble_sent_note = EI_INIT;
293 static expert_field ei_mac_lte_pch_pdu = EI_INIT;
294 static expert_field ei_mac_lte_ul_harq_resend_next_frame = EI_INIT;
295 static expert_field ei_mac_lte_control_bsr_multiple = EI_INIT;
296 static expert_field ei_mac_lte_padding_data_multiple = EI_INIT;
297 static expert_field ei_mac_lte_context_sysframe_number = EI_INIT;
298 static expert_field ei_mac_lte_rar_bi_present = EI_INIT;
299 static expert_field ei_mac_lte_control_element_size_invalid = EI_INIT;
300 static expert_field ei_mac_lte_bsr_warn_threshold_exceeded = EI_INIT;
301 static expert_field ei_mac_lte_too_many_subheaders = EI_INIT;
302 static expert_field ei_mac_lte_oob_send_sr = EI_INIT;
303 static expert_field ei_mac_lte_orig_tx_ul_frame_not_found = EI_INIT;
304 static expert_field ei_mac_lte_control_ue_contention_resolution_msg3_matched = EI_INIT;
305 static expert_field ei_mac_lte_sr_results_not_grant_or_failure_indication = EI_INIT;
306 static expert_field ei_mac_lte_context_crc_status = EI_INIT;
307 static expert_field ei_mac_lte_sr_invalid_event = EI_INIT;
308 static expert_field ei_mac_lte_control_subheader_after_data_subheader = EI_INIT;
309 static expert_field ei_mac_lte_rar_bi_not_first_subheader = EI_INIT;
310 static expert_field ei_mac_lte_context_length = EI_INIT;
311 static expert_field ei_mac_lte_reserved_not_zero = EI_INIT;
312 static expert_field ei_mac_lte_rar_timing_advance_not_zero_warn = EI_INIT;
313 static expert_field ei_mac_lte_dlsch_lcid = EI_INIT;
314 static expert_field ei_mac_lte_padding_data_before_control_subheader = EI_INIT;
315 static expert_field ei_mac_lte_rach_preamble_sent_warn = EI_INIT;
316
317
318 /* Constants and value strings */
319
320 static const value_string radio_type_vals[] =
321 {
322     { FDD_RADIO,      "FDD"},
323     { TDD_RADIO,      "TDD"},
324     { 0, NULL }
325 };
326
327
328 static const value_string direction_vals[] =
329 {
330     { DIRECTION_UPLINK,      "Uplink"},
331     { DIRECTION_DOWNLINK,    "Downlink"},
332     { 0, NULL }
333 };
334
335
336 static const value_string rnti_type_vals[] =
337 {
338     { NO_RNTI,     "NO-RNTI"},
339     { P_RNTI,      "P-RNTI"},
340     { RA_RNTI,     "RA-RNTI"},
341     { C_RNTI,      "C-RNTI"},
342     { SI_RNTI,     "SI-RNTI"},
343     { SPS_RNTI,    "SPS-RNTI"},
344     { M_RNTI,      "M-RNTI"},
345     { 0, NULL }
346 };
347
348 static const value_string bch_transport_channel_vals[] =
349 {
350     { SI_RNTI,      "DL-SCH"},
351     { NO_RNTI,      "BCH"},
352     { 0, NULL }
353 };
354
355 static const value_string crc_status_vals[] =
356 {
357     { crc_success,                "OK"},
358     { crc_fail,                   "Failed"},
359     { crc_high_code_rate,         "High Code Rate"},
360     { crc_pdsch_lost,             "PDSCH Lost"},
361     { crc_duplicate_nonzero_rv,   "Duplicate_nonzero_rv"},
362     { crc_false_dci,              "False DCI"},
363     { 0, NULL }
364 };
365
366 static const value_string carrier_id_vals[] =
367 {
368     { carrier_id_primary,       "Primary"},
369     { carrier_id_secondary_1,   "Secondary-1"},
370     { carrier_id_secondary_2,   "Secondary-2"},
371     { carrier_id_secondary_3,   "Secondary-3"},
372     { carrier_id_secondary_4,   "Secondary-4"},
373     { 0, NULL }
374 };
375
376 static const value_string dci_format_vals[] =
377 {
378     { 0, "0"},
379     { 1, "1"},
380     { 2, "1A"},
381     { 3, "1B"},
382     { 4, "1C"},
383     { 5, "1D"},
384     { 6, "2"},
385     { 7, "2A"},
386     { 8, "3/3A"},
387     { 0, NULL }
388 };
389
390 static const value_string aggregation_level_vals[] =
391 {
392     { 0, "1"},
393     { 1, "2"},
394     { 2, "4"},
395     { 3, "8"},
396     { 0, NULL }
397 };
398
399 static const value_string modulation_type_vals[] =
400 {
401     { 2, "QPSK"},
402     { 4, "QAM16"},
403     { 6, "QAM64"},
404     { 0, NULL }
405 };
406
407 static const true_false_string mac_lte_scell_ph_vals = {
408     "Reported",
409     "Not reported"
410 };
411
412 static const true_false_string mac_lte_power_backoff_vals = {
413     "Applied",
414     "Not applied"
415 };
416
417 static const true_false_string mac_lte_ph_value_vals = {
418     "Based on reference format",
419     "Based on real transmission"
420 };
421
422 static const true_false_string mac_lte_scell_status_vals = {
423     "Activated",
424     "Deactivated"
425 };
426
427 #define ACTIVATION_DEACTIVATION_LCID           0x1b
428 #define UE_CONTENTION_RESOLUTION_IDENTITY_LCID 0x1c
429 #define TIMING_ADVANCE_LCID                    0x1d
430 #define DRX_COMMAND_LCID                       0x1e
431 #define PADDING_LCID                           0x1f
432
433 static const value_string dlsch_lcid_vals[] =
434 {
435     { 0,                                        "CCCH"},
436     { 1,                                        "1"},
437     { 2,                                        "2"},
438     { 3,                                        "3"},
439     { 4,                                        "4"},
440     { 5,                                        "5"},
441     { 6,                                        "6"},
442     { 7,                                        "7"},
443     { 8,                                        "8"},
444     { 9,                                        "9"},
445     { 10,                                       "10"},
446     { ACTIVATION_DEACTIVATION_LCID          ,   "Activation/Deactivation"},
447     { UE_CONTENTION_RESOLUTION_IDENTITY_LCID,   "UE Contention Resolution Identity"},
448     { TIMING_ADVANCE_LCID                   ,   "Timing Advance"},
449     { DRX_COMMAND_LCID                      ,   "DRX Command"},
450     { PADDING_LCID                          ,   "Padding" },
451     { 0, NULL }
452 };
453
454 #define EXTENDED_POWER_HEADROOM_REPORT_LCID 0x19
455 #define POWER_HEADROOM_REPORT_LCID          0x1a
456 #define CRNTI_LCID                          0x1b
457 #define TRUNCATED_BSR_LCID                  0x1c
458 #define SHORT_BSR_LCID                      0x1d
459 #define LONG_BSR_LCID                       0x1e
460
461 static const value_string ulsch_lcid_vals[] =
462 {
463     { 0,                                   "CCCH"},
464     { 1,                                   "1"},
465     { 2,                                   "2"},
466     { 3,                                   "3"},
467     { 4,                                   "4"},
468     { 5,                                   "5"},
469     { 6,                                   "6"},
470     { 7,                                   "7"},
471     { 8,                                   "8"},
472     { 9,                                   "9"},
473     { 10,                                  "10"},
474     { EXTENDED_POWER_HEADROOM_REPORT_LCID, "Extended Power Headroom Report"},
475     { POWER_HEADROOM_REPORT_LCID,          "Power Headroom Report"},
476     { CRNTI_LCID,                          "C-RNTI"},
477     { TRUNCATED_BSR_LCID,                  "Truncated BSR"},
478     { SHORT_BSR_LCID,                      "Short BSR"},
479     { LONG_BSR_LCID,                       "Long BSR"},
480     { PADDING_LCID,                        "Padding" },
481     { 0, NULL }
482 };
483
484 #define MCH_SCHEDULING_INFO_LCID 0x1e
485
486 static const value_string mch_lcid_vals[] =
487 {
488     { 0,                            "MCCH"},
489     { 1,                            "1"},
490     { 2,                            "2"},
491     { 3,                            "3"},
492     { 4,                            "4"},
493     { 5,                            "5"},
494     { 6,                            "6"},
495     { 7,                            "7"},
496     { 8,                            "8"},
497     { 9,                            "9"},
498     { 10,                           "10"},
499     { 11,                           "11"},
500     { 12,                           "12"},
501     { 13,                           "13"},
502     { 14,                           "14"},
503     { 15,                           "15"},
504     { 16,                           "16"},
505     { 17,                           "17"},
506     { 18,                           "18"},
507     { 19,                           "19"},
508     { 20,                           "20"},
509     { 21,                           "21"},
510     { 22,                           "22"},
511     { 23,                           "23"},
512     { 24,                           "24"},
513     { 25,                           "25"},
514     { 26,                           "26"},
515     { 27,                           "27"},
516     { 28,                           "28"},
517     { MCH_SCHEDULING_INFO_LCID,     "MCH Scheduling Information"},
518     { PADDING_LCID,                 "Padding" },
519     { 0, NULL }
520 };
521
522 static const value_string format_vals[] =
523 {
524     { 0,      "Data length is < 128 bytes"},
525     { 1,      "Data length is >= 128 bytes"},
526     { 0, NULL }
527 };
528
529
530 static const value_string rar_type_vals[] =
531 {
532     { 0,      "Backoff Indicator present"},
533     { 1,      "RAPID present"},
534     { 0, NULL }
535 };
536
537
538 static const value_string rar_bi_vals[] =
539 {
540     { 0,      "0"},
541     { 1,      "10"},
542     { 2,      "20"},
543     { 3,      "30"},
544     { 4,      "40"},
545     { 5,      "60"},
546     { 6,      "80"},
547     { 7,      "120"},
548     { 8,      "160"},
549     { 9,      "240"},
550     { 10,     "320"},
551     { 11,     "480"},
552     { 12,     "960"},
553     { 0, NULL }
554 };
555
556
557 static const value_string buffer_size_vals[] =
558 {
559     { 0,      "BS = 0"},
560     { 1,      "0 < BS <= 10"},
561     { 2,      "10 < BS <= 12"},
562     { 3,      "12 < BS <= 14"},
563     { 4,      "14 < BS <= 17"},
564     { 5,      "17 < BS <= 19"},
565     { 6,      "19 < BS <= 22"},
566     { 7,      "22 < BS <= 26"},
567     { 8,      "26 < BS <= 31"},
568     { 9,      "31 < BS <= 36"},
569     { 10,     "36 < BS <= 42"},
570     { 11,     "42 < BS <= 49"},
571     { 12,     "49 < BS <= 57"},
572     { 13,     "47 < BS <= 67"},
573     { 14,     "67 < BS <= 78"},
574     { 15,     "78 < BS <= 91"},
575     { 16,     "91 < BS <= 107"},
576     { 17,     "107 < BS <= 125"},
577     { 18,     "125 < BS <= 146"},
578     { 19,     "146 < BS <= 171"},
579     { 20,     "171 < BS <= 200"},
580     { 21,     "200 < BS <= 234"},
581     { 22,     "234 < BS <= 274"},
582     { 23,     "274 < BS <= 321"},
583     { 24,     "321 < BS <= 376"},
584     { 25,     "376 < BS <= 440"},
585     { 26,     "440 < BS <= 515"},
586     { 27,     "515 < BS <= 603"},
587     { 28,     "603 < BS <= 706"},
588     { 29,     "706 < BS <= 826"},
589     { 30,     "826 < BS <= 967"},
590     { 31,     "967 < BS <= 1132"},
591     { 32,     "1132 < BS <= 1326"},
592     { 33,     "1326 < BS <= 1552"},
593     { 34,     "1552 < BS <= 1817"},
594     { 35,     "1817 < BS <= 2127"},
595     { 36,     "2127 < BS <= 2490"},
596     { 37,     "2490 < BS <= 2915"},
597     { 38,     "2915 < BS <= 3413"},
598     { 39,     "3413 < BS <= 3995"},
599     { 40,     "3995 < BS <= 4677"},
600     { 41,     "4677 < BS <= 5476"},
601     { 42,     "5476 < BS <= 6411"},
602     { 43,     "6411 < BS <= 7505"},
603     { 44,     "7505 < BS <= 8787"},
604     { 45,     "8787 < BS <= 10276"},
605     { 46,     "10287 < BS <= 12043"},
606     { 47,     "12043 < BS <= 14099"},
607     { 48,     "14099 < BS <= 16507"},
608     { 49,     "16507 < BS <= 19325"},
609     { 50,     "19325 < BS <= 22624"},
610     { 51,     "22624 < BS <= 26487"},
611     { 52,     "26487 < BS <= 31009"},
612     { 53,     "31009 < BS <= 36304"},
613     { 54,     "36304 < BS <= 42502"},
614     { 55,     "42502 < BS <= 49759"},
615     { 56,     "49759 < BS <= 58255"},
616     { 57,     "58255 < BS <= 68201"},
617     { 58,     "68201 < BS <= 79846"},
618     { 59,     "79846 < BS <= 93479"},
619     { 60,     "93479 < BS <= 109439"},
620     { 61,     "109439 < BS <= 128125"},
621     { 62,     "128125 < BS <= 150000"},
622     { 63,     "BS > 150000"},
623     { 0, NULL }
624 };
625 static value_string_ext buffer_size_vals_ext = VALUE_STRING_EXT_INIT(buffer_size_vals);
626
627 static const value_string ext_buffer_size_vals[] =
628 {
629     { 0,      "BS = 0"},
630     { 1,      "0 < BS <= 10"},
631     { 2,      "10 < BS <= 13"},
632     { 3,      "13 < BS <= 16"},
633     { 4,      "16 < BS <= 19"},
634     { 5,      "19 < BS <= 23"},
635     { 6,      "23 < BS <= 29"},
636     { 7,      "29 < BS <= 35"},
637     { 8,      "35 < BS <= 43"},
638     { 9,      "43 < BS <= 53"},
639     { 10,     "53 < BS <= 65"},
640     { 11,     "65 < BS <= 80"},
641     { 12,     "80 < BS <= 98"},
642     { 13,     "98 < BS <= 120"},
643     { 14,     "120 < BS <= 147"},
644     { 15,     "147 < BS <= 181"},
645     { 16,     "181 < BS <= 223"},
646     { 17,     "223 < BS <= 274"},
647     { 18,     "274 < BS <= 337"},
648     { 19,     "337 < BS <= 414"},
649     { 20,     "414 < BS <= 509"},
650     { 21,     "509 < BS <= 625"},
651     { 22,     "625 < BS <= 769"},
652     { 23,     "769 < BS <= 945"},
653     { 24,     "945 < BS <= 1162"},
654     { 25,     "1162 < BS <= 1429"},
655     { 26,     "1429 < BS <= 1757"},
656     { 27,     "1757 < BS <= 2161"},
657     { 28,     "2161 < BS <= 2657"},
658     { 29,     "2657 < BS <= 3267"},
659     { 30,     "3267 < BS <= 4017"},
660     { 31,     "4017 < BS <= 4940"},
661     { 32,     "4940 < BS <= 6074"},
662     { 33,     "6074 < BS <= 7469"},
663     { 34,     "7469 < BS <= 9185"},
664     { 35,     "9185 < BS <= 11294"},
665     { 36,     "11294 < BS <= 13888"},
666     { 37,     "13888 < BS <= 17077"},
667     { 38,     "17077 < BS <= 20999"},
668     { 39,     "20999 < BS <= 25822"},
669     { 40,     "25822 < BS <= 31752"},
670     { 41,     "31752 < BS <= 39045"},
671     { 42,     "39045 < BS <= 48012"},
672     { 43,     "48012 < BS <= 59039"},
673     { 44,     "59039 < BS <= 72598"},
674     { 45,     "72598 < BS <= 89272"},
675     { 46,     "89272 < BS <= 109774"},
676     { 47,     "109774 < BS <= 134986"},
677     { 48,     "134986 < BS <= 165989"},
678     { 49,     "165989 < BS <= 204111"},
679     { 50,     "204111 < BS <= 250990"},
680     { 51,     "250990 < BS <= 308634"},
681     { 52,     "308634 < BS <= 379519"},
682     { 53,     "379519 < BS <= 466683"},
683     { 54,     "466683 < BS <= 573866"},
684     { 55,     "573866 < BS <= 705666"},
685     { 56,     "705666 < BS <= 867737"},
686     { 57,     "867737 < BS <= 1067031"},
687     { 58,     "1067031 < BS <= 1312097"},
688     { 59,     "1312097 < BS <= 1613447"},
689     { 60,     "1613447 < BS <= 1984009"},
690     { 61,     "1984009 < BS <= 2439678"},
691     { 62,     "2439678 < BS <= 3000000"},
692     { 63,     "BS > 3000000"},
693     { 0, NULL }
694 };
695 static value_string_ext ext_buffer_size_vals_ext = VALUE_STRING_EXT_INIT(ext_buffer_size_vals);
696
697 static const value_string power_headroom_vals[] =
698 {
699     { 0,      "-23 <= PH < -22"},
700     { 1,      "-22 <= PH < -21"},
701     { 2,      "-21 <= PH < -20"},
702     { 3,      "-20 <= PH < -19"},
703     { 4,      "-19 <= PH < -18"},
704     { 5,      "-18 <= PH < -17"},
705     { 6,      "-17 <= PH < -16"},
706     { 7,      "-16 <= PH < -15"},
707     { 8,      "-15 <= PH < -14"},
708     { 9,      "-14 <= PH < -13"},
709     { 10,     "-13 <= PH < -12"},
710     { 11,     "-12 <= PH < -11"},
711     { 12,     "-11 <= PH < -10"},
712     { 13,     "-10 <= PH < -9"},
713     { 14,     "-9 <= PH < -8"},
714     { 15,     "-8 <= PH < -7"},
715     { 16,     "-7 <= PH < -6"},
716     { 17,     "-6 <= PH < -5"},
717     { 18,     "-5 <= PH < -4"},
718     { 19,     "-4 <= PH < -3"},
719     { 20,     "-3 <= PH < -2"},
720     { 21,     "-2 <= PH < -1"},
721     { 22,     "-1 <= PH < 0"},
722     { 23,     "0 <= PH < 1"},
723     { 24,     "1 <= PH < 2"},
724     { 25,     "2 <= PH < 3"},
725     { 26,     "3 <= PH < 4"},
726     { 27,     "4 <= PH < 5"},
727     { 28,     "5 <= PH < 6"},
728     { 29,     "6 <= PH < 7"},
729     { 30,     "7 <= PH < 8"},
730     { 31,     "8 <= PH < 9"},
731     { 32,     "9 <= PH < 10"},
732     { 33,     "10 <= PH < 11"},
733     { 34,     "11 <= PH < 12"},
734     { 35,     "12 <= PH < 13"},
735     { 36,     "13 <= PH < 14"},
736     { 37,     "14 <= PH < 15"},
737     { 38,     "15 <= PH < 16"},
738     { 39,     "16 <= PH < 17"},
739     { 40,     "17 <= PH < 18"},
740     { 41,     "18 <= PH < 19"},
741     { 42,     "19 <= PH < 20"},
742     { 43,     "20 <= PH < 21"},
743     { 44,     "21 <= PH < 22"},
744     { 45,     "22 <= PH < 23"},
745     { 46,     "23 <= PH < 24"},
746     { 47,     "24 <= PH < 25"},
747     { 48,     "25 <= PH < 26"},
748     { 49,     "26 <= PH < 27"},
749     { 50,     "27 <= PH < 28"},
750     { 51,     "28 <= PH < 29"},
751     { 52,     "29 <= PH < 30"},
752     { 53,     "30 <= PH < 31"},
753     { 54,     "31 <= PH < 32"},
754     { 55,     "32 <= PH < 33"},
755     { 56,     "33 <= PH < 34"},
756     { 57,     "34 <= PH < 35"},
757     { 58,     "34 <= PH < 36"},
758     { 59,     "36 <= PH < 37"},
759     { 60,     "37 <= PH < 38"},
760     { 61,     "38 <= PH < 39"},
761     { 62,     "39 <= PH < 40"},
762     { 63,     "PH >= 40"},
763     { 0, NULL }
764 };
765 static value_string_ext power_headroom_vals_ext = VALUE_STRING_EXT_INIT(power_headroom_vals);
766
767 static const value_string pcmaxc_vals[] =
768 {
769     { 0,      "Pcmax,c < -29"},
770     { 1,      "-29 <= Pcmax,c < -28"},
771     { 2,      "-28 <= Pcmax,c < -27"},
772     { 3,      "-27 <= Pcmax,c < -26"},
773     { 4,      "-26 <= Pcmax,c < -25"},
774     { 5,      "-25 <= Pcmax,c < -24"},
775     { 6,      "-24 <= Pcmax,c < -23"},
776     { 7,      "-23 <= Pcmax,c < -22"},
777     { 8,      "-22 <= Pcmax,c < -21"},
778     { 9,      "-21 <= Pcmax,c < -20"},
779     { 10,     "-20 <= Pcmax,c < -19"},
780     { 11,     "-19 <= Pcmax,c < -18"},
781     { 12,     "-18 <= Pcmax,c < -17"},
782     { 13,     "-17 <= Pcmax,c < -16"},
783     { 14,     "-16 <= Pcmax,c < -15"},
784     { 15,     "-15 <= Pcmax,c < -14"},
785     { 16,     "-14 <= Pcmax,c < -13"},
786     { 17,     "-13 <= Pcmax,c < -12"},
787     { 18,     "-12 <= Pcmax,c < -11"},
788     { 19,     "-11 <= Pcmax,c < -10"},
789     { 20,     "-10 <= Pcmax,c < -9"},
790     { 21,     "-9 <= Pcmax,c < -8"},
791     { 22,     "-8 <= Pcmax,c < -7"},
792     { 23,     "-7 <= Pcmax,c < -6"},
793     { 24,     "-6 <= Pcmax,c < -5"},
794     { 25,     "-5 <= Pcmax,c < -4"},
795     { 26,     "-4 <= Pcmax,c < -3"},
796     { 27,     "-3 <= Pcmax,c < -2"},
797     { 28,     "-2 <= Pcmax,c < -1"},
798     { 29,     "-1 <= Pcmax,c < 0"},
799     { 30,     "0 <= Pcmax,c < 1"},
800     { 31,     "1 <= Pcmax,c < 2"},
801     { 32,     "2 <= Pcmax,c < 3"},
802     { 33,     "3 <= Pcmax,c < 4"},
803     { 34,     "4 <= Pcmax,c < 5"},
804     { 35,     "5 <= Pcmax,c < 6"},
805     { 36,     "6 <= Pcmax,c < 7"},
806     { 37,     "7 <= Pcmax,c < 8"},
807     { 38,     "8 <= Pcmax,c < 9"},
808     { 39,     "9 <= Pcmax,c < 10"},
809     { 40,     "10 <= Pcmax,c < 11"},
810     { 41,     "11 <= Pcmax,c < 12"},
811     { 42,     "12 <= Pcmax,c < 13"},
812     { 43,     "13 <= Pcmax,c < 14"},
813     { 44,     "14 <= Pcmax,c < 15"},
814     { 45,     "15 <= Pcmax,c < 16"},
815     { 46,     "16 <= Pcmax,c < 17"},
816     { 47,     "17 <= Pcmax,c < 18"},
817     { 48,     "18 <= Pcmax,c < 19"},
818     { 49,     "19 <= Pcmax,c < 20"},
819     { 50,     "20 <= Pcmax,c < 21"},
820     { 51,     "21 <= Pcmax,c < 22"},
821     { 52,     "22 <= Pcmax,c < 23"},
822     { 53,     "23 <= Pcmax,c < 24"},
823     { 54,     "24 <= Pcmax,c < 25"},
824     { 55,     "25 <= Pcmax,c < 26"},
825     { 56,     "26 <= Pcmax,c < 27"},
826     { 57,     "27 <= Pcmax,c < 28"},
827     { 58,     "28 <= Pcmax,c < 29"},
828     { 59,     "29 <= Pcmax,c < 30"},
829     { 60,     "30 <= Pcmax,c < 31"},
830     { 61,     "31 <= Pcmax,c < 32"},
831     { 62,     "32 <= Pcmax,c < 33"},
832     { 63,     "33 <= Pcmax,c"},
833     { 0, NULL }
834 };
835 static value_string_ext pcmaxc_vals_ext = VALUE_STRING_EXT_INIT(pcmaxc_vals);
836
837 static const value_string header_only_vals[] =
838 {
839     { 0,      "MAC PDU Headers and body present"},
840     { 1,      "MAC PDU Headers only"},
841     { 0, NULL }
842 };
843
844 static const value_string predefined_frame_vals[] =
845 {
846     { 0,      "Real MAC PDU present - will dissect"},
847     { 1,      "Predefined frame present - will not dissect"},
848     { 0, NULL }
849 };
850
851 static const value_string ul_retx_grant_vals[] =
852 {
853     { 0,      "PDCCH ReTx"},
854     { 1,      "PHICH NACK"},
855     { 0, NULL }
856 };
857
858 /**************************************************************************/
859 /* Preferences state                                                      */
860 /**************************************************************************/
861
862 /* If this PDU has been NACK'd (by HARQ) more than a certain number of times,
863    we trigger an expert warning. */
864 static gint global_mac_lte_retx_counter_trigger = 3;
865
866 /* By default try to decode transparent data (BCH, PCH and CCCH) data using LTE RRC dissector */
867 static gboolean global_mac_lte_attempt_rrc_decode = TRUE;
868
869 /* Whether should attempt to dissect frames failing CRC check */
870 static gboolean global_mac_lte_dissect_crc_failures = FALSE;
871
872 /* Whether should attempt to decode lcid 1&2 SDUs as srb1/2 (i.e. AM RLC) */
873 static gboolean global_mac_lte_attempt_srb_decode = TRUE;
874
875 /* Whether should attempt to decode MCH LCID 0 as MCCH */
876 static gboolean global_mac_lte_attempt_mcch_decode = FALSE;
877
878 /* Whether should call RLC dissector to decode MTCH LCIDs */
879 static gboolean global_mac_lte_call_rlc_for_mtch = FALSE;
880
881 /* Where to take LCID -> DRB mappings from */
882 enum lcid_drb_source {
883     FromStaticTable, FromConfigurationProtocol
884 };
885 static gint global_mac_lte_lcid_drb_source = (gint)FromStaticTable;
886
887 /* Threshold for warning in expert info about high BSR values */
888 static gint global_mac_lte_bsr_warn_threshold = 50; /* default is 19325 -> 22624 */
889
890 /* Whether or not to track SRs and related frames */
891 static gboolean global_mac_lte_track_sr = TRUE;
892
893 /* Which layer info to show in the info column */
894 enum layer_to_show {
895     ShowPHYLayer, ShowMACLayer, ShowRLCLayer
896 };
897
898 /* Which layer's details to show in Info column */
899 static gint     global_mac_lte_layer_to_show = (gint)ShowRLCLayer;
900
901 /* Whether to decode Contention Resolution body as UL CCCH */
902 static gboolean global_mac_lte_decode_cr_body = FALSE;
903
904 /* Whether to record config and try to show DRX state for each configured UE */
905 static gboolean global_mac_lte_show_drx = FALSE;
906
907
908
909 /* When showing RLC info, count PDUs so can append info column properly */
910 static guint8   s_number_of_rlc_pdus_shown = 0;
911
912 /***********************************************************************/
913 /* How to dissect lcid 3-10 (presume drb logical channels)             */
914
915 static const value_string drb_lcid_vals[] = {
916     { 3,  "LCID 3"},
917     { 4,  "LCID 4"},
918     { 5,  "LCID 5"},
919     { 6,  "LCID 6"},
920     { 7,  "LCID 7"},
921     { 8,  "LCID 8"},
922     { 9,  "LCID 9"},
923     { 10, "LCID 10"},
924     { 0, NULL }
925 };
926
927 typedef enum rlc_channel_type_t {
928     rlcRaw,
929     rlcTM,
930     rlcUM5,
931     rlcUM10,
932     rlcAM
933 } rlc_channel_type_t;
934
935 static const value_string rlc_channel_type_vals[] = {
936     { rlcTM,    "TM"},
937     { rlcUM5 ,  "UM, SN Len=5"},
938     { rlcUM10,  "UM, SN Len=10"},
939     { rlcAM  ,  "AM"},
940     { 0, NULL }
941 };
942
943
944 /* Mapping type */
945 typedef struct lcid_drb_mapping_t {
946     guint16 lcid;
947     gint    drbid;
948     rlc_channel_type_t channel_type;
949 } lcid_drb_mapping_t;
950
951 /* Mapping entity */
952 static lcid_drb_mapping_t *lcid_drb_mappings = NULL;
953 static guint num_lcid_drb_mappings = 0;
954
955 UAT_VS_DEF(lcid_drb_mappings, lcid, lcid_drb_mapping_t, guint16, 3, "LCID 3")
956 UAT_DEC_CB_DEF(lcid_drb_mappings, drbid, lcid_drb_mapping_t)
957 UAT_VS_DEF(lcid_drb_mappings, channel_type, lcid_drb_mapping_t, rlc_channel_type_t, rlcAM, "AM")
958
959 /* UAT object */
960 static uat_t* lcid_drb_mappings_uat;
961
962 /* Dynamic mappings (set by configuration protocol)
963    LCID is the index into the array of these */
964 typedef struct dynamic_lcid_drb_mapping_t {
965     gboolean valid;
966     gint     drbid;
967     rlc_channel_type_t channel_type;
968     guint8   ul_priority;
969 } dynamic_lcid_drb_mapping_t;
970
971 typedef struct ue_dynamic_drb_mappings_t {
972     dynamic_lcid_drb_mapping_t mapping[11];  /* Index is LCID */
973     guint8 drb_to_lcid_mappings[32];         /* Also map drbid -> lcid */
974 } ue_dynamic_drb_mappings_t;
975
976 static GHashTable *mac_lte_ue_channels_hash = NULL;
977
978
979 extern int proto_rlc_lte;
980
981 /***************************************************************/
982
983
984
985 /***************************************************************/
986 /* Keeping track of Msg3 bodies so they can be compared with   */
987 /* Contention Resolution bodies.                               */
988
989 typedef struct Msg3Data {
990     guint8   data[6];
991     nstime_t msg3Time;
992     guint32  framenum;
993 } Msg3Data;
994
995
996 /* This table stores (RNTI -> Msg3Data*).  Will be populated when
997    Msg3 frames are first read.  */
998 static GHashTable *mac_lte_msg3_hash = NULL;
999
1000 /* Hash table functions for mac_lte_msg3_hash.  Hash is just the (RNTI) key */
1001 static gint mac_lte_rnti_hash_equal(gconstpointer v, gconstpointer v2)
1002 {
1003     return (v == v2);
1004 }
1005
1006 static guint mac_lte_rnti_hash_func(gconstpointer v)
1007 {
1008     return GPOINTER_TO_UINT(v);
1009 }
1010
1011
1012 typedef enum ContentionResolutionStatus {
1013     NoMsg3,
1014     Msg3Match,
1015     Msg3NoMatch
1016 } ContentionResolutionStatus;
1017
1018 typedef struct ContentionResolutionResult {
1019     ContentionResolutionStatus status;
1020     guint                      msg3FrameNum;
1021     guint                      msSinceMsg3;
1022 } ContentionResolutionResult;
1023
1024
1025 /* This table stores (CRFrameNum -> CRResult).  It is assigned during the first
1026    pass and used thereafter */
1027 static GHashTable *mac_lte_cr_result_hash = NULL;
1028
1029 /* Hash table functions for mac_lte_cr_result_hash.  Hash is just the (framenum) key */
1030 static gint mac_lte_framenum_hash_equal(gconstpointer v, gconstpointer v2)
1031 {
1032     return (v == v2);
1033 }
1034
1035 static guint mac_lte_framenum_hash_func(gconstpointer v)
1036 {
1037     return GPOINTER_TO_UINT(v);
1038 }
1039
1040 /**************************************************************************/
1041
1042
1043
1044 /****************************************************************/
1045 /* Keeping track of last DL frames per C-RNTI so can guess when */
1046 /* there has been a HARQ retransmission                         */
1047 /* TODO: this should be simplified now that harq-id & ndi are   */
1048 /* being logged!                                                */
1049
1050 /* Could be bigger, but more than enough to flag suspected resends */
1051 #define MAX_EXPECTED_PDU_LENGTH 2048
1052
1053 typedef struct LastFrameData {
1054     gboolean inUse;
1055     guint32  framenum;
1056     gboolean ndi;
1057     nstime_t received_time;
1058     gint     length;
1059     guint8   data[MAX_EXPECTED_PDU_LENGTH];
1060 } LastFrameData;
1061
1062 typedef struct DLHarqBuffers {
1063     LastFrameData harqid[2][15];  /* 2 blocks (1 for each antenna) needed for DL */
1064 } DLHarqBuffers;
1065
1066
1067 /* This table stores (RNTI -> DLHARQBuffers*).  Will be populated when
1068    DL frames are first read.  */
1069 static GHashTable *mac_lte_dl_harq_hash = NULL;
1070
1071 typedef struct DLHARQResult {
1072     gboolean    previousSet, nextSet;
1073     guint       previousFrameNum;
1074     guint       timeSincePreviousFrame;
1075     guint       nextFrameNum;
1076     guint       timeToNextFrame;
1077 } DLHARQResult;
1078
1079
1080 /* This table stores (FrameNumber -> *DLHARQResult).  It is assigned during the first
1081    pass and used thereafter */
1082 static GHashTable *mac_lte_dl_harq_result_hash = NULL;
1083
1084 /**************************************************************************/
1085
1086
1087 /*****************************************************************/
1088 /* Keeping track of last UL frames per C-RNTI so can verify when */
1089 /* told that a frame is a retx                                   */
1090
1091 typedef struct ULHarqBuffers {
1092     LastFrameData harqid[8];
1093 } ULHarqBuffers;
1094
1095
1096 /* This table stores (RNTI -> ULHarqBuffers*).  Will be populated when
1097    UL frames are first read.  */
1098 static GHashTable *mac_lte_ul_harq_hash = NULL;
1099
1100 typedef struct ULHARQResult {
1101     gboolean    previousSet, nextSet;
1102     guint       previousFrameNum;
1103     guint       timeSincePreviousFrame;
1104     guint       nextFrameNum;
1105     guint       timeToNextFrame;
1106 } ULHARQResult;
1107
1108
1109 /* This table stores (FrameNum -> ULHARQResult).  It is assigned during the first
1110    pass and used thereafter */
1111 static GHashTable *mac_lte_ul_harq_result_hash = NULL;
1112
1113 /**************************************************************************/
1114
1115
1116 /**************************************************************************/
1117 /* Tracking of Scheduling Requests (SRs).                                 */
1118 /* Keep track of:                                                         */
1119 /* - last grant before SR                                                 */
1120 /* - SR failures following request                                        */
1121 /* - grant following SR                                                   */
1122
1123 typedef enum SREvent {
1124     SR_Grant,
1125     SR_Request,
1126     SR_Failure
1127 } SREvent;
1128
1129 static const value_string sr_event_vals[] =
1130 {
1131     { SR_Grant,        "Grant"},
1132     { SR_Request,      "SR Request"},
1133     { SR_Failure,      "SR Failure"},
1134     { 0,               NULL}
1135 };
1136
1137 typedef enum SRStatus {
1138     None,
1139     SR_Outstanding,
1140     SR_Failed
1141 } SRStatus;
1142
1143 static const value_string sr_status_vals[] =
1144 {
1145     { None,                "Receiving grants"},
1146     { SR_Outstanding,      "SR Request outstanding"},
1147     { SR_Failed,           "SR has Failed"},
1148     { 0,                   NULL}
1149 };
1150
1151
1152 typedef struct SRState {
1153     SRStatus status;
1154     guint32  lastSRFramenum;
1155     guint32  lastGrantFramenum;
1156     nstime_t requestTime;
1157 } SRState;
1158
1159
1160 /* This table keeps track of the SR state for each UE.
1161    (RNTI -> SRState) */
1162 static GHashTable *mac_lte_ue_sr_state = NULL;
1163
1164
1165 typedef enum SRResultType {
1166     GrantAnsweringSR,
1167     FailureAnsweringSR,
1168     SRLeadingToGrant,
1169     SRLeadingToFailure,
1170     InvalidSREvent
1171 } SRResultType;
1172
1173
1174 typedef struct SRResult {
1175     SRResultType type;
1176     guint32      frameNum;
1177     guint32      timeDifference;
1178
1179     /* These 2 are only used with InvalidSREvent */
1180     SRStatus     status;
1181     SREvent      event;
1182 } SRResult;
1183
1184 /* Entries in this table are created during the first pass
1185    It maps (SRFrameNum -> SRResult) */
1186 static GHashTable *mac_lte_sr_request_hash = NULL;
1187
1188 /**************************************************************************/
1189
1190
1191
1192 /**************************************************************************/
1193 /* DRX State                                                              */
1194 /* Config for current cycle/timer state for a configured UE               */
1195
1196
1197 /* Entries in this table are maintained during the first pass
1198    It maps (UEId -> drx_state_t). */
1199 static GHashTable *mac_lte_drx_ue_state = NULL;
1200
1201 typedef struct drx_running_state_t
1202 {
1203     gboolean     firstCycleStartSet;
1204
1205     /* Cycle information */
1206     gboolean     inShortCycle;
1207
1208     /* Timers */
1209     nstime_t     currentTime;  /* absolute time of last PDU. Used to detect whole
1210                                   missing SFN cycle */
1211
1212     guint64      currentTicks;
1213     guint16      currentSFN;
1214     guint16      currentSF;
1215
1216     /* These timers are absolute times when these events expire */
1217     guint64      onDurationTimer;
1218     guint64      inactivityTimer;
1219     guint64      RTT[8];
1220     guint64      retransmissionTimer[8];
1221     guint64      shortCycleTimer;
1222
1223 } drx_running_state_t;
1224
1225 /* Have 2 states for each PDU.  One for before the PDU/event, and one after.
1226    Only then can show if we don't think it should have been active at that point... */
1227 typedef struct drx_state_t {
1228     drx_config_t          config;
1229     drx_running_state_t   state_before;
1230     drx_running_state_t   state_after;
1231 } drx_state_t;
1232
1233
1234 typedef struct drx_state_key_t {
1235     guint32 frameNumber;
1236     guint   pdu_instance;
1237 } drx_state_key_t;
1238
1239 /* Entries in this table are written during the first pass
1240    It maps (drx_state_key_t -> drx_state_t), so state at that point may be shown. */
1241 static GHashTable *mac_lte_drx_frame_result = NULL;
1242
1243 static gint mac_lte_framenum_instance_hash_equal(gconstpointer v, gconstpointer v2)
1244 {
1245     const drx_state_key_t *p1 = (const drx_state_key_t*)v;
1246     const drx_state_key_t *p2 = (const drx_state_key_t*)v2;
1247
1248     return ((p1->frameNumber == p2->frameNumber) &&
1249             (p1->pdu_instance == p2->pdu_instance));
1250 }
1251
1252 static guint mac_lte_framenum_instance_hash_func(gconstpointer v)
1253 {
1254     const drx_state_key_t *p1 = (const drx_state_key_t*)v;
1255
1256     /* XXX which one return ? */
1257     return p1->frameNumber + (p1->pdu_instance >> 8);
1258     return GPOINTER_TO_UINT(v);
1259 }
1260
1261
1262
1263
1264 /* Initialise the UE DRX state */
1265 static void init_drx_ue_state(drx_state_t *drx_state, gboolean at_init)
1266 {
1267     int i;
1268     drx_state->state_before.inShortCycle = FALSE;
1269     if (at_init) {
1270         drx_state->state_before.onDurationTimer = G_GUINT64_CONSTANT(0);
1271     }
1272     drx_state->state_before.inactivityTimer = G_GUINT64_CONSTANT(0);
1273     for (i=0; i < 8; i++) {
1274         drx_state->state_before.RTT[i] = G_GUINT64_CONSTANT(0);
1275         drx_state->state_before.retransmissionTimer[i] = G_GUINT64_CONSTANT(0);
1276     }
1277     drx_state->state_before.shortCycleTimer = G_GUINT64_CONSTANT(0);
1278 }
1279
1280 typedef enum drx_timer_type_t {
1281     drx_onduration_timer,
1282     drx_inactivity_timer,
1283     drx_rtt_timer,
1284     drx_retx_timer,
1285     drx_short_cycle_timer
1286 } drx_timer_type_t;
1287
1288 /* Start the specified timer.  Use the time period in the config */
1289 static void mac_lte_drx_start_timer(drx_state_t *p_state, drx_timer_type_t timer_type, guint8 timer_id)
1290 {
1291     /* Get current time in ms */
1292     guint64 *pTimer;
1293     guint16 timerLength;
1294
1295     /* Get pointer to timer value, and fetch from config how much to add to it */
1296     switch (timer_type) {
1297         case drx_onduration_timer:
1298             pTimer = &(p_state->state_before.onDurationTimer);
1299             timerLength = p_state->config.onDurationTimer;
1300             break;
1301         case drx_inactivity_timer:
1302             pTimer = &(p_state->state_before.inactivityTimer);
1303             timerLength = p_state->config.inactivityTimer;
1304             break;
1305         case drx_rtt_timer:
1306             pTimer = &(p_state->state_before.RTT[timer_id]);
1307             timerLength = 8;
1308             break;
1309         case drx_retx_timer:
1310             pTimer = &(p_state->state_before.retransmissionTimer[timer_id]);
1311             timerLength = p_state->config.retransmissionTimer;
1312             break;
1313         case drx_short_cycle_timer:
1314         default:
1315             pTimer = &(p_state->state_before.shortCycleTimer);
1316             timerLength = p_state->config.shortCycle * p_state->config.shortCycleTimer;
1317             break;
1318     }
1319
1320     /* Set timer */
1321     *pTimer = p_state->state_before.currentTicks + timerLength;
1322 }
1323
1324 /* Stop the specified timer.  */
1325 static void mac_lte_drx_stop_timer(drx_state_t *p_state, drx_timer_type_t timer_type, guint8 timer_id)
1326 {
1327     /* Set indicated timer value to 0 */
1328     switch (timer_type) {
1329         case drx_onduration_timer:
1330             p_state->state_before.onDurationTimer = G_GUINT64_CONSTANT(0);
1331             break;
1332         case drx_inactivity_timer:
1333             p_state->state_before.inactivityTimer = G_GUINT64_CONSTANT(0);
1334             break;
1335         case drx_rtt_timer:
1336             p_state->state_before.RTT[timer_id] = G_GUINT64_CONSTANT(0);
1337             break;
1338         case drx_retx_timer:
1339             p_state->state_before.retransmissionTimer[timer_id] = G_GUINT64_CONSTANT(0);
1340             break;
1341         case drx_short_cycle_timer:
1342             p_state->state_before.shortCycleTimer = G_GUINT64_CONSTANT(0);
1343             break;
1344     }
1345 }
1346
1347 /* Has the specified timer expired?  */
1348 static gboolean mac_lte_drx_has_timer_expired(drx_state_t *p_state, drx_timer_type_t timer_type, guint8 timer_id,
1349                                               gboolean before_event,
1350                                               guint64 *time_until_expires)
1351 {
1352     guint64 *pTimer = NULL;
1353     drx_running_state_t *state_to_use;
1354
1355     if (before_event) {
1356         state_to_use = &p_state->state_before;
1357     }
1358     else {
1359         state_to_use = &p_state->state_after;
1360     }
1361
1362
1363     /* Get pointer to timer value */
1364     switch (timer_type) {
1365         case drx_onduration_timer:
1366             pTimer = &(state_to_use->onDurationTimer);
1367             break;
1368         case drx_inactivity_timer:
1369             pTimer = &(state_to_use->inactivityTimer);
1370             break;
1371         case drx_rtt_timer:
1372             pTimer = &(state_to_use->RTT[timer_id]);
1373             break;
1374         case drx_retx_timer:
1375             pTimer = &(state_to_use->retransmissionTimer[timer_id]);
1376             break;
1377         case drx_short_cycle_timer:
1378             pTimer = &(state_to_use->shortCycleTimer);
1379             break;
1380
1381         default:
1382             return FALSE;
1383     }
1384
1385     /* TODO: verify using SFN/SF ? */
1386     if (state_to_use->currentTicks == *pTimer) {
1387         *time_until_expires = 0;
1388         return TRUE;
1389     }
1390
1391     if (state_to_use->currentTicks > *pTimer) {
1392         *time_until_expires = 0;
1393     }
1394     else {
1395         *time_until_expires = *pTimer - state_to_use->currentTicks;
1396     }
1397
1398     return FALSE;
1399 }
1400
1401
1402 /* Handling of triggers that can prompt changes in state */
1403
1404 static void mac_lte_drx_new_ulsch_data(guint16 ueid)
1405 {
1406     /* Look up state of this UE */
1407     drx_state_t *ue_state = (drx_state_t *)g_hash_table_lookup(mac_lte_drx_ue_state, GUINT_TO_POINTER((guint)ueid));
1408
1409     /* Start inactivity timer */
1410     if (ue_state != NULL) {
1411         mac_lte_drx_start_timer(ue_state, drx_inactivity_timer, 0);
1412     }
1413 }
1414
1415 static void mac_lte_drx_new_dlsch_data(guint16 ueid)
1416 {
1417     /* Look up state of this UE */
1418     drx_state_t *ue_state = (drx_state_t *)g_hash_table_lookup(mac_lte_drx_ue_state,
1419                                                                GUINT_TO_POINTER((guint)ueid));
1420
1421     /* Start retransmission timer */
1422     if (ue_state != NULL) {
1423         mac_lte_drx_start_timer(ue_state, drx_inactivity_timer, 0);
1424     }
1425 }
1426
1427 static void mac_lte_drx_dl_crc_error(guint16 ueid)
1428 {
1429     /* Look up state of this UE */
1430     drx_state_t *ue_state = (drx_state_t *)g_hash_table_lookup(mac_lte_drx_ue_state,
1431                                                                GUINT_TO_POINTER((guint)ueid));
1432
1433     /* Start timer */
1434     if (ue_state != NULL) {
1435         mac_lte_drx_start_timer(ue_state, drx_retx_timer, 0);
1436     }
1437 }
1438
1439 /* A DRX control element has been received */
1440 static void mac_lte_drx_control_element_received(guint16 ueid)
1441 {
1442     /* Look up state of this UE */
1443     drx_state_t *ue_state = (drx_state_t *)g_hash_table_lookup(mac_lte_drx_ue_state,
1444                                                                GUINT_TO_POINTER((guint)ueid));
1445
1446     /* Start timers */
1447     if (ue_state != NULL) {
1448         mac_lte_drx_stop_timer(ue_state, drx_onduration_timer, 0);
1449         mac_lte_drx_stop_timer(ue_state, drx_inactivity_timer, 0);
1450     }
1451 }
1452
1453
1454 /* Update the DRX state of the UE based on previous info and current time.
1455    This is called every time a UE with DRX configured has an UL or DL PDU */
1456 static void update_drx_info(packet_info *pinfo, mac_lte_info *p_mac_lte_info)
1457 {
1458     int harq_id;
1459     guint64 time_until_expires;
1460
1461     /* Look up state of this UE */
1462     drx_state_t *ue_state = (drx_state_t *)g_hash_table_lookup(mac_lte_drx_ue_state,
1463                                                                GUINT_TO_POINTER((guint)p_mac_lte_info->ueid));
1464
1465     if (ue_state != NULL) {
1466         /* We loop until we find this subframe */
1467         guint16 SFN = p_mac_lte_info->sysframeNumber;
1468         guint16 SF = p_mac_lte_info->subframeNumber;
1469
1470         /* Make sure the first time reference has been set */
1471         if (!ue_state->state_before.firstCycleStartSet) {
1472             /* Set current time to now */
1473             ue_state->state_before.currentSFN = SFN;
1474             ue_state->state_before.currentSF = SF;
1475
1476             ue_state->state_before.currentTicks = SFN*10 + SF;
1477
1478             ue_state->state_before.firstCycleStartSet = TRUE;
1479         }
1480
1481         /* Will loop around these checks, once for each subframe between previous
1482            currentTime for this UE, and the time now!!! */
1483         /* It *should* be possible to just deal with the elapsed time all at once,
1484            but much harder to get right, so loop. */
1485
1486         /* If > ~10s since last PDU, just zero all timers (except onDuration) */
1487         if ((pinfo->fd->abs_ts.secs - ue_state->state_before.currentTime.secs) >= 9) {
1488             init_drx_ue_state(ue_state, FALSE);
1489         }
1490
1491         while ((ue_state->state_before.currentSFN != SFN) || (ue_state->state_before.currentSF != SF)) {
1492
1493             /* Check for timers that have expired and change state accordingly */
1494
1495             /* See if onDuration timer should be started */
1496             guint16 subframes = ue_state->state_before.currentSFN*10 + ue_state->state_before.currentSF;
1497             if (!ue_state->state_before.inShortCycle) {
1498                 if ((subframes % ue_state->config.longCycle) == ue_state->config.cycleOffset) {
1499                     mac_lte_drx_start_timer(ue_state, drx_onduration_timer, 0);
1500                 }
1501             }
1502             else {
1503                 if ((subframes % ue_state->config.shortCycle) == (ue_state->config.cycleOffset % ue_state->config.shortCycle)) {
1504                     mac_lte_drx_start_timer(ue_state, drx_onduration_timer, 0);
1505                 }
1506             }
1507
1508             /* Check for HARQ RTT Timer expiring.
1509                In practice only one could expire in any given subframe... */
1510             for (harq_id = 0 ; harq_id < 8; harq_id++) {
1511                 if (mac_lte_drx_has_timer_expired(ue_state, drx_rtt_timer, harq_id, TRUE, &time_until_expires)) {
1512                     /* Start the Retransmission timer */
1513                     mac_lte_drx_start_timer(ue_state, drx_retx_timer, harq_id);
1514                 }
1515             }
1516
1517             /* Reception of DRX command is dealt with separately at the moment... */
1518
1519             /* Inactivity timer expired */
1520             if (mac_lte_drx_has_timer_expired(ue_state, drx_inactivity_timer, 0, TRUE, &time_until_expires)) {
1521                 if (ue_state->config.shortCycleConfigured) {
1522                     ue_state->state_before.inShortCycle = TRUE;
1523                     mac_lte_drx_start_timer(ue_state, drx_short_cycle_timer, 0);
1524                 }
1525             }
1526
1527
1528             /* Move subframe along by one */
1529             if (ue_state->state_before.currentSF == 9) {
1530                 ue_state->state_before.currentSF = 0;
1531                 if (ue_state->state_before.currentSFN == 1023) {
1532                     ue_state->state_before.currentSFN = 0;
1533                 }
1534                 else {
1535                     ue_state->state_before.currentSFN++;
1536                 }
1537             }
1538             else {
1539                 ue_state->state_before.currentSF++;
1540             }
1541
1542             ue_state->state_before.currentTicks++;
1543         }
1544
1545         /* Set current time to now */
1546         ue_state->state_before.currentTime = pinfo->fd->abs_ts;
1547     }
1548 }
1549
1550 /* Convenience function to get a pointer for the hash_func to work with */
1551 static gpointer get_drx_result_hash_key(guint32 frameNumber,
1552                                         guint pdu_instance,
1553                                         gboolean do_persist)
1554 {
1555     static drx_state_key_t key;
1556     drx_state_key_t *p_key;
1557
1558     /* Only allocate a struct when will be adding entry */
1559     if (do_persist) {
1560         p_key = wmem_new0(wmem_file_scope(), drx_state_key_t);
1561     }
1562     else {
1563         memset(&key, 0, sizeof(drx_state_key_t));
1564         p_key = &key;
1565     }
1566
1567     /* Fill in details, and return pointer */
1568     p_key->frameNumber = frameNumber;
1569     p_key->pdu_instance = pdu_instance;
1570
1571     return p_key;
1572 }
1573
1574
1575 /* Set DRX information to display for the current MAC frame.
1576    Only called on first pass through frames. */
1577 static void set_drx_info(packet_info *pinfo, mac_lte_info *p_mac_lte_info, gboolean before_event, guint pdu_instance)
1578 {
1579     /* Look up state of this UE */
1580     drx_state_t *ue_state = (drx_state_t *)g_hash_table_lookup(mac_lte_drx_ue_state,
1581                                                                GUINT_TO_POINTER((guint)p_mac_lte_info->ueid));
1582     drx_state_t *frame_result;
1583
1584     if (ue_state != NULL) {
1585         /* Should only need to allocate frame_result and add to the result table when
1586            before PDU is processed */
1587         if (before_event) {
1588             /* Copy UE snapshot for this frame, and add to result table */
1589             frame_result = wmem_new(wmem_file_scope(), drx_state_t);
1590
1591             /* Deep-copy this snapshot for this frame */
1592             *frame_result = *ue_state;
1593
1594             /* And store in table */
1595             g_hash_table_insert(mac_lte_drx_frame_result, get_drx_result_hash_key(pinfo->fd->num, pdu_instance, TRUE), frame_result);
1596         }
1597         else {
1598             /* After update, so just copy ue_state 'state' info after part of frame */
1599             frame_result = (drx_state_t*)g_hash_table_lookup(mac_lte_drx_frame_result,
1600                                                              get_drx_result_hash_key(pinfo->fd->num, pdu_instance, FALSE));
1601             if (frame_result != NULL) {
1602                 /* Deep-copy updated state from UE */
1603                 frame_result->state_after = ue_state->state_before;
1604             }
1605         }
1606     }
1607 }
1608
1609 /* Show DRX information associated with this MAC frame */
1610 static void show_drx_info(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb,
1611                           mac_lte_info *p_mac_lte_info, gboolean before_event, guint pdu_instance)
1612 {
1613     drx_state_t         *frame_state;
1614     drx_running_state_t *state_to_show;
1615     guint64             time_until_expires;
1616     guint               n;
1617
1618     /* Look up entry by frame number in result table */
1619     frame_state = (drx_state_t *)g_hash_table_lookup(mac_lte_drx_frame_result,
1620                                                      get_drx_result_hash_key(pinfo->fd->num, pdu_instance, FALSE));
1621
1622     /* Show available information */
1623     if (frame_state != NULL) {
1624         proto_tree *drx_config_tree, *drx_state_tree;
1625         proto_item *drx_config_ti, *drx_state_ti, *ti;
1626
1627         /* Show config only if 'before */
1628         if (before_event) {
1629             /************************************/
1630             /* Create config subtree            */
1631             drx_config_ti = proto_tree_add_string_format(tree, hf_mac_lte_drx_config,
1632                                                   tvb, 0, 0, "", "DRX Config");
1633             drx_config_tree = proto_item_add_subtree(drx_config_ti, ett_mac_lte_drx_config);
1634             PROTO_ITEM_SET_GENERATED(drx_config_ti);
1635
1636             /* Link back to configuration (RRC) frame */
1637             ti = proto_tree_add_uint(drx_config_tree, hf_mac_lte_drx_config_frame_num, tvb,
1638                                      0, 0, frame_state->config.frameNum);
1639             PROTO_ITEM_SET_GENERATED(ti);
1640
1641             /* Link back to any previous config frame (only from current config frame) */
1642             if ((frame_state->config.frameNum == pinfo->fd->num) &&
1643                 (frame_state->config.previousFrameNum != 0)) {
1644                     ti = proto_tree_add_uint(drx_config_tree, hf_mac_lte_drx_config_previous_frame_num, tvb,
1645                                              0, 0, frame_state->config.previousFrameNum);
1646                     PROTO_ITEM_SET_GENERATED(ti);
1647             }
1648
1649             /* Config fields */
1650             ti = proto_tree_add_uint(drx_config_tree, hf_mac_lte_drx_config_long_cycle, tvb,
1651                                      0, 0, frame_state->config.longCycle);
1652             PROTO_ITEM_SET_GENERATED(ti);
1653             ti = proto_tree_add_uint(drx_config_tree, hf_mac_lte_drx_config_cycle_offset, tvb,
1654                                      0, 0, frame_state->config.cycleOffset);
1655             PROTO_ITEM_SET_GENERATED(ti);
1656             ti = proto_tree_add_uint(drx_config_tree, hf_mac_lte_drx_config_onduration_timer, tvb,
1657                                      0, 0, frame_state->config.onDurationTimer);
1658             PROTO_ITEM_SET_GENERATED(ti);
1659             ti = proto_tree_add_uint(drx_config_tree, hf_mac_lte_drx_config_inactivity_timer, tvb,
1660                                      0, 0, frame_state->config.inactivityTimer);
1661             PROTO_ITEM_SET_GENERATED(ti);
1662             ti = proto_tree_add_uint(drx_config_tree, hf_mac_lte_drx_config_retransmission_timer, tvb,
1663                                      0, 0, frame_state->config.retransmissionTimer);
1664             PROTO_ITEM_SET_GENERATED(ti);
1665
1666             if (frame_state->config.shortCycleConfigured) {
1667                 ti = proto_tree_add_uint(drx_config_tree, hf_mac_lte_drx_config_short_cycle, tvb,
1668                                          0, 0, frame_state->config.shortCycle);
1669                 PROTO_ITEM_SET_GENERATED(ti);
1670
1671                 ti = proto_tree_add_uint(drx_config_tree, hf_mac_lte_drx_config_short_cycle_timer, tvb,
1672                                          0, 0, frame_state->config.shortCycleTimer);
1673                 PROTO_ITEM_SET_GENERATED(ti);
1674             }
1675
1676             proto_item_append_text(drx_config_ti, " (Long-cycle=%u cycle-offset=%u onDuration=%u)",
1677                                    frame_state->config.longCycle, frame_state->config.cycleOffset,
1678                                    frame_state->config.onDurationTimer);
1679             if (frame_state->config.shortCycleConfigured) {
1680                 proto_item_append_text(drx_config_ti, " (Short-cycle=%u Short-cycle-timer=%u)",
1681                                        frame_state->config.shortCycle, frame_state->config.shortCycleTimer);
1682             }
1683         }
1684
1685         /*************************************/
1686         /* Create state subtree              */
1687         drx_state_ti = proto_tree_add_string_format(tree, hf_mac_lte_drx_state,
1688                                                     tvb, 0, 0, "",
1689                                                     (before_event) ? "DRX State Before" : "DRX State After");
1690         /* Get appropriate state pointer to use below */
1691         if (before_event) {
1692             state_to_show = &frame_state->state_before;
1693         }
1694         else {
1695             state_to_show = &frame_state->state_after;
1696         }
1697
1698         drx_state_tree = proto_item_add_subtree(drx_state_ti, ett_mac_lte_drx_state);
1699         PROTO_ITEM_SET_GENERATED(drx_state_ti);
1700
1701         /* Show cycle information */
1702
1703         if (!state_to_show->inShortCycle) {
1704             /* Show where we are in current long cycle */
1705             guint16 offset_into_long_cycle = ((p_mac_lte_info->sysframeNumber*10) + p_mac_lte_info->subframeNumber) %
1706                                               frame_state->config.longCycle;
1707             ti = proto_tree_add_uint(drx_state_tree, hf_mac_lte_drx_state_long_cycle_offset, tvb,
1708                                      0, 0, offset_into_long_cycle);
1709             PROTO_ITEM_SET_GENERATED(ti);
1710         }
1711         else {
1712             /* Show where we are inside short cycle */
1713             guint16 offset_into_short_cycle = ((p_mac_lte_info->sysframeNumber*10) + p_mac_lte_info->subframeNumber) %
1714                                                 frame_state->config.shortCycle;
1715
1716             ti = proto_tree_add_uint(drx_state_tree, hf_mac_lte_drx_state_short_cycle_offset, tvb,
1717                                      0, 0, offset_into_short_cycle);
1718             PROTO_ITEM_SET_GENERATED(ti);
1719
1720             /* Is short-cycle-timer running? */
1721             if (!mac_lte_drx_has_timer_expired(frame_state, drx_short_cycle_timer, 0, before_event, &time_until_expires)) {
1722                 if (time_until_expires) {
1723                     ti = proto_tree_add_uint(drx_state_tree, hf_mac_lte_drx_state_short_cycle_remaining, tvb,
1724                                              0, 0, (guint16)time_until_expires);
1725                     PROTO_ITEM_SET_GENERATED(ti);
1726                 }
1727             }
1728         }
1729
1730         /* Show which timers are still running and how long they have to go.
1731            TODO: Complain if it looks like DRX looks like it should be on
1732            TODO: if PDU is a retranmission, would be good to check to see if DRX
1733                  would have been on for original Tx! */
1734
1735         /* Is onduration timer running? */
1736         if (!mac_lte_drx_has_timer_expired(frame_state, drx_onduration_timer, 0, before_event, &time_until_expires)) {
1737             if (time_until_expires) {
1738                 ti = proto_tree_add_uint(drx_state_tree, hf_mac_lte_drx_state_onduration_remaining, tvb,
1739                                          0, 0, (guint16)time_until_expires);
1740                 PROTO_ITEM_SET_GENERATED(ti);
1741             }
1742         }
1743
1744         /* Is inactivity timer running? */
1745         if (!mac_lte_drx_has_timer_expired(frame_state, drx_inactivity_timer, 0, before_event, &time_until_expires)) {
1746             if (time_until_expires) {
1747                 ti = proto_tree_add_uint(drx_state_tree, hf_mac_lte_drx_state_inactivity_remaining, tvb,
1748                                          0, 0, (guint16)time_until_expires);
1749                 PROTO_ITEM_SET_GENERATED(ti);
1750             }
1751         }
1752
1753         /* Are any of the Retransmission timers running? */
1754         for (n=0; n < 8; n++) {
1755             if (!mac_lte_drx_has_timer_expired(frame_state, drx_retx_timer, n, before_event, &time_until_expires)) {
1756                 if (time_until_expires) {
1757                     ti = proto_tree_add_uint(drx_state_tree, hf_mac_lte_drx_state_retransmission_remaining, tvb,
1758                                              0, 0, (guint16)time_until_expires);
1759                     PROTO_ITEM_SET_GENERATED(ti);
1760                     proto_item_append_text(ti, " (harqid=%u)", n);
1761                 }
1762             }
1763         }
1764
1765         /* Are any of the RTT timers running? */
1766         for (n=0; n < 8; n++) {
1767             if (!mac_lte_drx_has_timer_expired(frame_state, drx_rtt_timer, n, before_event, &time_until_expires)) {
1768                 if (time_until_expires) {
1769                     ti = proto_tree_add_uint(drx_state_tree, hf_mac_lte_drx_state_rtt_remaining, tvb,
1770                                              0, 0, (guint16)time_until_expires);
1771                     PROTO_ITEM_SET_GENERATED(ti);
1772                     proto_item_append_text(ti, " (harqid=%u)", n);
1773                 }
1774             }
1775         }
1776     }
1777 }
1778
1779
1780 /**************************************************************************/
1781
1782
1783
1784 /* Forward declarations */
1785 int dissect_mac_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void*);
1786
1787 static guint8 get_mac_lte_channel_priority(guint16 ueid _U_, guint8 lcid,
1788                                            guint8 direction);
1789
1790
1791 /* Heuristic dissection */
1792 static gboolean global_mac_lte_heur = FALSE;
1793
1794 static void call_with_catch_all(dissector_handle_t handle, tvbuff_t* tvb, packet_info *pinfo, proto_tree *tree)
1795 {
1796     /* Call it (catch exceptions so that stats will be updated) */
1797     TRY {
1798         call_dissector_only(handle, tvb, pinfo, tree, NULL);
1799     }
1800     CATCH_ALL {
1801     }
1802     ENDTRY
1803 }
1804
1805 /* Dissect context fields in the format described in packet-mac-lte.h.
1806    Return TRUE if the necessary information was successfully found */
1807 gboolean dissect_mac_lte_context_fields(struct mac_lte_info  *p_mac_lte_info, tvbuff_t *tvb,
1808                                         gint *p_offset)
1809 {
1810     gint    offset = *p_offset;
1811     guint8  tag = 0;
1812
1813     /* Read fixed fields */
1814     p_mac_lte_info->radioType = tvb_get_guint8(tvb, offset++);
1815     p_mac_lte_info->direction = tvb_get_guint8(tvb, offset++);
1816
1817     if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
1818         p_mac_lte_info->detailed_phy_info.ul_info.present = FALSE;
1819     }
1820     else {
1821         p_mac_lte_info->detailed_phy_info.dl_info.present = FALSE;
1822     }
1823
1824     p_mac_lte_info->rntiType = tvb_get_guint8(tvb, offset++);
1825
1826     /* Initialize RNTI with a default value in case optional field is not present */
1827     switch (p_mac_lte_info->rntiType) {
1828         case M_RNTI:
1829             p_mac_lte_info->rnti = 0xFFFD;
1830             break;
1831         case P_RNTI:
1832             p_mac_lte_info->rnti = 0xFFFE;
1833             break;
1834         case SI_RNTI:
1835             p_mac_lte_info->rnti = 0xFFFF;
1836             break;
1837         case RA_RNTI:
1838         case C_RNTI:
1839         case SPS_RNTI:
1840             p_mac_lte_info->rnti = 0x0001;
1841             break;
1842         default:
1843             break;
1844     }
1845
1846     /* Read optional fields */
1847     while (tag != MAC_LTE_PAYLOAD_TAG) {
1848         /* Process next tag */
1849         tag = tvb_get_guint8(tvb, offset++);
1850         switch (tag) {
1851             case MAC_LTE_RNTI_TAG:
1852                 p_mac_lte_info->rnti = tvb_get_ntohs(tvb, offset);
1853                 offset += 2;
1854                 break;
1855             case MAC_LTE_UEID_TAG:
1856                 p_mac_lte_info->ueid = tvb_get_ntohs(tvb, offset);
1857                 offset += 2;
1858                 break;
1859             case MAC_LTE_FRAME_SUBFRAME_TAG:
1860                 {
1861                     guint16 sfn_sf = tvb_get_ntohs(tvb, offset);
1862                     p_mac_lte_info->sysframeNumber = (sfn_sf >> 4) & 0x03ff;
1863                     p_mac_lte_info->subframeNumber = sfn_sf & 0x000f;
1864                     offset += 2;
1865                 }
1866                 break;
1867             case MAC_LTE_PREDEFINED_DATA_TAG:
1868                 p_mac_lte_info->isPredefinedData = tvb_get_guint8(tvb, offset);
1869                 offset++;
1870                 break;
1871             case MAC_LTE_RETX_TAG:
1872                 p_mac_lte_info->reTxCount = tvb_get_guint8(tvb, offset);
1873                 offset++;
1874                 break;
1875             case MAC_LTE_CRC_STATUS_TAG:
1876                 p_mac_lte_info->crcStatusValid = TRUE;
1877                 p_mac_lte_info->crcStatus =
1878                     (mac_lte_crc_status)tvb_get_guint8(tvb, offset);
1879                 offset++;
1880                 break;
1881             case MAC_LTE_EXT_BSR_SIZES_TAG:
1882                 p_mac_lte_info->isExtendedBSRSizes = TRUE;
1883                 break;
1884             case MAC_LTE_SEND_PREAMBLE_TAG:
1885                 p_mac_lte_info->oob_event = ltemac_send_preamble;
1886                 p_mac_lte_info->rapid = tvb_get_guint8(tvb, offset);
1887                 offset++;
1888                 p_mac_lte_info->rach_attempt_number = tvb_get_guint8(tvb, offset);
1889                 offset++;
1890                 break;
1891             case MAC_LTE_CARRIER_ID_TAG:
1892                 p_mac_lte_info->carrierId = 
1893                     (mac_lte_carrier_id)tvb_get_guint8(tvb, offset);
1894                 offset++;
1895                 break;
1896             case MAC_LTE_PHY_TAG:
1897                 {
1898                     gint len, offset1;
1899
1900                     len = tvb_get_guint8(tvb, offset++);
1901                     offset1 = offset;
1902                     if (p_mac_lte_info->direction == DIRECTION_DOWNLINK) {
1903                         if (len < 10)
1904                             goto next;
1905                         p_mac_lte_info->detailed_phy_info.dl_info.present = TRUE;
1906                         p_mac_lte_info->detailed_phy_info.dl_info.dci_format = 
1907                             tvb_get_guint8(tvb, offset);
1908                         offset++;
1909                         p_mac_lte_info->detailed_phy_info.dl_info.resource_allocation_type = 
1910                             tvb_get_guint8(tvb, offset);
1911                         offset++;
1912                         p_mac_lte_info->detailed_phy_info.dl_info.aggregation_level = 
1913                             tvb_get_guint8(tvb, offset);
1914                         offset++;
1915                         p_mac_lte_info->detailed_phy_info.dl_info.mcs_index = 
1916                             tvb_get_guint8(tvb, offset);
1917                         offset++;
1918                         p_mac_lte_info->detailed_phy_info.dl_info.redundancy_version_index = 
1919                             tvb_get_guint8(tvb, offset);
1920                         offset++;
1921                         p_mac_lte_info->detailed_phy_info.dl_info.resource_block_length = 
1922                             tvb_get_guint8(tvb, offset);
1923                         offset++;
1924                         p_mac_lte_info->detailed_phy_info.dl_info.harq_id = 
1925                             tvb_get_guint8(tvb, offset);
1926                         offset++;
1927                         p_mac_lte_info->detailed_phy_info.dl_info.ndi = 
1928                             tvb_get_guint8(tvb, offset);
1929                         offset++;
1930                         p_mac_lte_info->detailed_phy_info.dl_info.transport_block = 
1931                             tvb_get_guint8(tvb, offset);
1932                         offset++;
1933                         p_mac_lte_info->dl_retx = 
1934                             (mac_lte_dl_retx)tvb_get_guint8(tvb, offset);
1935                     } else {
1936                         if (len < 6)
1937                             goto next;
1938                         p_mac_lte_info->detailed_phy_info.ul_info.present = TRUE;
1939                         p_mac_lte_info->detailed_phy_info.ul_info.modulation_type = 
1940                             tvb_get_guint8(tvb, offset);
1941                         offset++;
1942                         p_mac_lte_info->detailed_phy_info.ul_info.tbs_index = 
1943                             tvb_get_guint8(tvb, offset);
1944                         offset++;
1945                         p_mac_lte_info->detailed_phy_info.ul_info.resource_block_length = 
1946                             tvb_get_guint8(tvb, offset);
1947                         offset++;
1948                         p_mac_lte_info->detailed_phy_info.ul_info.resource_block_start = 
1949                             tvb_get_guint8(tvb, offset);
1950                         offset++;
1951                         p_mac_lte_info->detailed_phy_info.ul_info.harq_id = 
1952                             tvb_get_guint8(tvb, offset);
1953                         offset++;
1954                         p_mac_lte_info->detailed_phy_info.ul_info.ndi = 
1955                             tvb_get_guint8(tvb, offset);
1956                     }
1957                 next:
1958                     offset = offset1 + len;
1959                 }
1960                 break;
1961
1962             case MAC_LTE_PAYLOAD_TAG:
1963                 /* Have reached data, so set payload length and get out of loop */
1964                 /* TODO: this is not correct if there is padding which isn't in frame */
1965                 p_mac_lte_info->length= tvb_length_remaining(tvb, offset);
1966                 continue;
1967
1968             default:
1969                 /* It must be a recognised tag */
1970                 return FALSE;
1971         }
1972     }
1973
1974     /* Pass out where offset is now */
1975     *p_offset = offset;
1976
1977     return TRUE;
1978 }
1979
1980 /* Heuristic dissector looks for supported framing protocol (see wiki page)  */
1981 static gboolean dissect_mac_lte_heur(tvbuff_t *tvb, packet_info *pinfo,
1982                                      proto_tree *tree, void *data _U_)
1983 {
1984     gint                 offset = 0;
1985     struct mac_lte_info  *p_mac_lte_info;
1986     tvbuff_t             *mac_tvb;
1987     gboolean             infoAlreadySet = FALSE;
1988
1989     /* This is a heuristic dissector, which means we get all the UDP
1990      * traffic not sent to a known dissector and not claimed by
1991      * a heuristic dissector called before us!
1992      */
1993
1994     if (!global_mac_lte_heur) {
1995         return FALSE;
1996     }
1997
1998     /* Do this again on re-dissection to re-discover offset of actual PDU */
1999
2000     /* Needs to be at least as long as:
2001        - the signature string
2002        - fixed header bytes
2003        - tag for data
2004        - at least one byte of MAC PDU payload */
2005     if (tvb_length_remaining(tvb, offset) < (gint)(strlen(MAC_LTE_START_STRING)+3+2)) {
2006         return FALSE;
2007     }
2008
2009     /* OK, compare with signature string */
2010     if (tvb_strneql(tvb, offset, MAC_LTE_START_STRING, strlen(MAC_LTE_START_STRING)) != 0) {
2011         return FALSE;
2012     }
2013     offset += (gint)strlen(MAC_LTE_START_STRING);
2014
2015     /* If redissecting, use previous info struct (if available) */
2016     p_mac_lte_info = (mac_lte_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_mac_lte, 0);
2017     if (p_mac_lte_info == NULL) {
2018         /* Allocate new info struct for this frame */
2019         p_mac_lte_info = wmem_new0(wmem_file_scope(), struct mac_lte_info);
2020         infoAlreadySet = FALSE;
2021     }
2022     else {
2023         infoAlreadySet = TRUE;
2024     }
2025
2026     /* Dissect the fields to populate p_mac_lte */
2027     if (!dissect_mac_lte_context_fields(p_mac_lte_info, tvb, &offset)) {
2028         return FALSE;
2029     }
2030
2031
2032     if (!infoAlreadySet) {
2033         /* Store info in packet */
2034         p_add_proto_data(wmem_file_scope(), pinfo, proto_mac_lte, 0, p_mac_lte_info);
2035     }
2036
2037     /**************************************/
2038     /* OK, now dissect as MAC LTE         */
2039
2040     /* Create tvb that starts at actual MAC PDU */
2041     mac_tvb = tvb_new_subset_remaining(tvb, offset);
2042     dissect_mac_lte(mac_tvb, pinfo, tree, NULL);
2043
2044     return TRUE;
2045 }
2046
2047
2048 /* Write the given formatted text to:
2049    - the info column (if pinfo != NULL)
2050    - 1 or 2 other labels (optional)
2051 */
2052 static void write_pdu_label_and_info(proto_item *ti1, proto_item *ti2,
2053                                      packet_info *pinfo, const char *format, ...)
2054 {
2055     #define MAX_INFO_BUFFER 256
2056     static char info_buffer[MAX_INFO_BUFFER];
2057     va_list ap;
2058
2059     if ((ti1 == NULL) && (ti2 == NULL) && (pinfo == NULL)) {
2060         return;
2061     }
2062
2063     va_start(ap, format);
2064     g_vsnprintf(info_buffer, MAX_INFO_BUFFER, format, ap);
2065     va_end(ap);
2066
2067     /* Add to indicated places */
2068     if (pinfo != NULL) {
2069         col_append_str(pinfo->cinfo, COL_INFO, info_buffer);
2070     }
2071     if (ti1 != NULL) {
2072         proto_item_append_text(ti1, "%s", info_buffer);
2073     }
2074     if (ti2 != NULL) {
2075         proto_item_append_text(ti2, "%s", info_buffer);
2076     }
2077 }
2078
2079 /* Version of function above, where no g_vsnprintf() call needed */
2080 static void write_pdu_label_and_info_literal(proto_item *ti1, proto_item *ti2,
2081                                              packet_info *pinfo, const char *info_buffer)
2082 {
2083     if ((ti1 == NULL) && (ti2 == NULL) && (pinfo == NULL)) {
2084         return;
2085     }
2086
2087     /* Add to indicated places */
2088     if (pinfo != NULL) {
2089         col_append_str(pinfo->cinfo, COL_INFO, info_buffer);
2090     }
2091     if (ti1 != NULL) {
2092         proto_item_append_text(ti1, "%s", info_buffer);
2093     }
2094     if (ti2 != NULL) {
2095         proto_item_append_text(ti2, "%s", info_buffer);
2096     }
2097 }
2098
2099
2100
2101 /* Show extra PHY parameters (if present) */
2102 static void show_extra_phy_parameters(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree,
2103                                       struct mac_lte_info *p_mac_lte_info)
2104 {
2105     proto_item *phy_ti;
2106     proto_tree *phy_tree;
2107     proto_item *ti;
2108
2109     if (global_mac_lte_layer_to_show == ShowPHYLayer) {
2110         /* Clear the info column */
2111         col_clear(pinfo->cinfo, COL_INFO);
2112     }
2113
2114     if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
2115         if (p_mac_lte_info->detailed_phy_info.ul_info.present) {
2116
2117             /* Create root */
2118             phy_ti = proto_tree_add_string_format(tree, hf_mac_lte_context_phy_ul,
2119                                                   tvb, 0, 0, "", "UL PHY Context");
2120             phy_tree = proto_item_add_subtree(phy_ti, ett_mac_lte_phy_context);
2121             PROTO_ITEM_SET_GENERATED(phy_ti);
2122
2123             /* Add items */
2124             ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_modulation_type,
2125                                      tvb, 0, 0,
2126                                      p_mac_lte_info->detailed_phy_info.ul_info.modulation_type);
2127             PROTO_ITEM_SET_GENERATED(ti);
2128
2129             ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_tbs_index,
2130                                      tvb, 0, 0,
2131                                      p_mac_lte_info->detailed_phy_info.ul_info.tbs_index);
2132             PROTO_ITEM_SET_GENERATED(ti);
2133
2134             ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_resource_block_length,
2135                                      tvb, 0, 0,
2136                                      p_mac_lte_info->detailed_phy_info.ul_info.resource_block_length);
2137             PROTO_ITEM_SET_GENERATED(ti);
2138
2139             ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_resource_block_start,
2140                                      tvb, 0, 0,
2141                                      p_mac_lte_info->detailed_phy_info.ul_info.resource_block_start);
2142             PROTO_ITEM_SET_GENERATED(ti);
2143
2144             ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_harq_id,
2145                                      tvb, 0, 0,
2146                                      p_mac_lte_info->detailed_phy_info.ul_info.harq_id);
2147             PROTO_ITEM_SET_GENERATED(ti);
2148
2149             ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_ndi,
2150                                      tvb, 0, 0,
2151                                      p_mac_lte_info->detailed_phy_info.ul_info.ndi);
2152             PROTO_ITEM_SET_GENERATED(ti);
2153
2154
2155             proto_item_append_text(phy_ti, " (");
2156
2157             write_pdu_label_and_info(phy_ti, NULL,
2158                                      (global_mac_lte_layer_to_show == ShowPHYLayer) ? pinfo : NULL,
2159                                      "UL: UEId=%u RNTI=%u %s Tbs_Index=%u RB_len=%u RB_start=%u",
2160                                      p_mac_lte_info->ueid,
2161                                      p_mac_lte_info->rnti,
2162                                      val_to_str_const(p_mac_lte_info->detailed_phy_info.ul_info.modulation_type,
2163                                                       modulation_type_vals, "Unknown"),
2164                                      p_mac_lte_info->detailed_phy_info.ul_info.tbs_index,
2165                                      p_mac_lte_info->detailed_phy_info.ul_info.resource_block_length,
2166                                      p_mac_lte_info->detailed_phy_info.ul_info.resource_block_start);
2167
2168             proto_item_append_text(phy_ti, ")");
2169
2170             /* Don't want columns to be replaced now */
2171             if (global_mac_lte_layer_to_show == ShowPHYLayer) {
2172                 col_set_writable(pinfo->cinfo, FALSE);
2173             }
2174         }
2175     }
2176     else {
2177         if (p_mac_lte_info->detailed_phy_info.dl_info.present) {
2178
2179             /* Create root */
2180             phy_ti = proto_tree_add_string_format(tree, hf_mac_lte_context_phy_dl,
2181                                                   tvb, 0, 0, "", "DL PHY Context");
2182             phy_tree = proto_item_add_subtree(phy_ti, ett_mac_lte_phy_context);
2183             PROTO_ITEM_SET_GENERATED(phy_ti);
2184
2185             /* Add items */
2186             ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_dci_format,
2187                                      tvb, 0, 0,
2188                                      p_mac_lte_info->detailed_phy_info.dl_info.dci_format);
2189             PROTO_ITEM_SET_GENERATED(ti);
2190
2191             ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_resource_allocation_type,
2192                                      tvb, 0, 0,
2193                                      p_mac_lte_info->detailed_phy_info.dl_info.resource_allocation_type);
2194             PROTO_ITEM_SET_GENERATED(ti);
2195
2196             ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_aggregation_level,
2197                                      tvb, 0, 0,
2198                                      p_mac_lte_info->detailed_phy_info.dl_info.aggregation_level);
2199             PROTO_ITEM_SET_GENERATED(ti);
2200
2201             ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_mcs_index,
2202                                      tvb, 0, 0,
2203                                      p_mac_lte_info->detailed_phy_info.dl_info.mcs_index);
2204             PROTO_ITEM_SET_GENERATED(ti);
2205
2206             ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_redundancy_version_index,
2207                                      tvb, 0, 0,
2208                                      p_mac_lte_info->detailed_phy_info.dl_info.redundancy_version_index);
2209             PROTO_ITEM_SET_GENERATED(ti);
2210
2211             ti = proto_tree_add_boolean(phy_tree, hf_mac_lte_context_phy_dl_retx,
2212                                         tvb, 0, 0,
2213                                         p_mac_lte_info->dl_retx);
2214             PROTO_ITEM_SET_GENERATED(ti);
2215
2216             ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_resource_block_length,
2217                                      tvb, 0, 0,
2218                                      p_mac_lte_info->detailed_phy_info.dl_info.resource_block_length);
2219             PROTO_ITEM_SET_GENERATED(ti);
2220
2221             ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_harq_id,
2222                                      tvb, 0, 0,
2223                                      p_mac_lte_info->detailed_phy_info.dl_info.harq_id);
2224             PROTO_ITEM_SET_GENERATED(ti);
2225
2226             ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_ndi,
2227                                      tvb, 0, 0,
2228                                      p_mac_lte_info->detailed_phy_info.dl_info.ndi);
2229             PROTO_ITEM_SET_GENERATED(ti);
2230
2231             ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_tb,
2232                                      tvb, 0, 0,
2233                                      p_mac_lte_info->detailed_phy_info.dl_info.transport_block);
2234             PROTO_ITEM_SET_GENERATED(ti);
2235
2236
2237             proto_item_append_text(phy_ti, " (");
2238
2239             write_pdu_label_and_info(phy_ti, NULL,
2240                                      (global_mac_lte_layer_to_show == ShowPHYLayer) ? pinfo : NULL,
2241                                      "DL: UEId=%u RNTI=%u DCI_Format=%s Res_Alloc=%u Aggr_Level=%s MCS=%u RV=%u "
2242                                      "Res_Block_len=%u HARQ_id=%u NDI=%u",
2243                                      p_mac_lte_info->ueid,
2244                                      p_mac_lte_info->rnti,
2245                                      val_to_str_const(p_mac_lte_info->detailed_phy_info.dl_info.dci_format,
2246                                                       dci_format_vals, "Unknown"),
2247                                      p_mac_lte_info->detailed_phy_info.dl_info.resource_allocation_type,
2248                                      val_to_str_const(p_mac_lte_info->detailed_phy_info.dl_info.aggregation_level,
2249                                                       aggregation_level_vals, "Unknown"),
2250                                      p_mac_lte_info->detailed_phy_info.dl_info.mcs_index,
2251                                      p_mac_lte_info->detailed_phy_info.dl_info.redundancy_version_index,
2252                                      p_mac_lte_info->detailed_phy_info.dl_info.resource_block_length,
2253                                      p_mac_lte_info->detailed_phy_info.dl_info.harq_id,
2254                                      p_mac_lte_info->detailed_phy_info.dl_info.ndi);
2255             proto_item_append_text(phy_ti, ")");
2256
2257             /* Don't want columns to be replaced now */
2258             if (global_mac_lte_layer_to_show == ShowPHYLayer) {
2259                 col_set_writable(pinfo->cinfo, FALSE);
2260             }
2261         }
2262     }
2263 }
2264
2265
2266 /* Dissect a single Random Access Reponse body */
2267 static gint dissect_rar_entry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2268                               proto_item *pdu_ti,
2269                               gint offset, guint8 rapid)
2270 {
2271     guint8      reserved;
2272     guint       start_body_offset = offset;
2273     proto_item *ti;
2274     proto_item *rar_body_ti;
2275     proto_tree *rar_body_tree;
2276     proto_tree *ul_grant_tree;
2277     proto_item *ul_grant_ti;
2278     guint16     timing_advance;
2279     guint32     ul_grant;
2280     guint16     temp_crnti;
2281
2282     /* Create tree for this Body */
2283     rar_body_ti = proto_tree_add_item(tree,
2284                                       hf_mac_lte_rar_body,
2285                                       tvb, offset, 0, ENC_ASCII|ENC_NA);
2286     rar_body_tree = proto_item_add_subtree(rar_body_ti, ett_mac_lte_rar_body);
2287
2288     /* Dissect an RAR entry */
2289
2290     /* Check reserved bit */
2291     reserved = (tvb_get_guint8(tvb, offset) & 0x80) >> 7;
2292     ti = proto_tree_add_item(rar_body_tree, hf_mac_lte_rar_reserved2, tvb, offset, 1, ENC_BIG_ENDIAN);
2293     if (reserved != 0) {
2294             expert_add_info_format(pinfo, ti, &ei_mac_lte_reserved_not_zero, "RAR body Reserved bit not zero (found 0x%x)", reserved);
2295     }
2296
2297     /* Timing Advance */
2298     timing_advance = (tvb_get_ntohs(tvb, offset) & 0x7ff0) >> 4;
2299     ti = proto_tree_add_item(rar_body_tree, hf_mac_lte_rar_ta, tvb, offset, 2, ENC_BIG_ENDIAN);
2300     if (timing_advance != 0) {
2301         if (timing_advance <= 31) {
2302             expert_add_info_format(pinfo, ti, &ei_mac_lte_rar_timing_advance_not_zero_note,
2303                                "RAR Timing advance not zero (%u)", timing_advance);
2304         } else {
2305             expert_add_info_format(pinfo, ti, &ei_mac_lte_rar_timing_advance_not_zero_warn,
2306                                "RAR Timing advance not zero (%u)", timing_advance);
2307         }
2308     }
2309     offset++;
2310
2311     /* UL Grant */
2312     ul_grant = (tvb_get_ntohl(tvb, offset) & 0x0fffff00) >> 8;
2313     ul_grant_ti = proto_tree_add_item(rar_body_tree, hf_mac_lte_rar_ul_grant, tvb, offset, 3, ENC_BIG_ENDIAN);
2314
2315     /* Break these 20 bits down as described in 36.213, section 6.2 */
2316     /* Create subtree for UL grant break-down */
2317     ul_grant_tree = proto_item_add_subtree(ul_grant_ti, ett_mac_lte_rar_ul_grant);
2318
2319     /* Hopping flag (1 bit) */
2320     proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_hopping,
2321                         tvb, offset, 1, ENC_BIG_ENDIAN);
2322
2323     /* Fixed sized resource block assignment (10 bits) */
2324     proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_fsrba,
2325                         tvb, offset, 2, ENC_BIG_ENDIAN);
2326
2327     /* Truncated Modulation and coding scheme (4 bits) */
2328     proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_tmcs,
2329                         tvb, offset+1, 2, ENC_BIG_ENDIAN);
2330
2331     /* TPC command for scheduled PUSCH (3 bits) */
2332     proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_tcsp,
2333                         tvb, offset+2, 1, ENC_BIG_ENDIAN);
2334
2335     /* UL delay (1 bit) */
2336     proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_ul_delay,
2337                         tvb, offset+2, 1, ENC_BIG_ENDIAN);
2338
2339     /* CQI request (1 bit) */
2340     proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_cqi_request,
2341                         tvb, offset+2, 1, ENC_BIG_ENDIAN);
2342
2343     offset += 3;
2344
2345     /* Temporary C-RNTI */
2346     temp_crnti = tvb_get_ntohs(tvb, offset);
2347     proto_tree_add_item(rar_body_tree, hf_mac_lte_rar_temporary_crnti, tvb, offset, 2, ENC_BIG_ENDIAN);
2348     offset += 2;
2349
2350     write_pdu_label_and_info(pdu_ti, rar_body_ti, pinfo,
2351                              "(RAPID=%u: TA=%u, UL-Grant=%u, Temp C-RNTI=%u) ",
2352                              rapid, timing_advance, ul_grant, temp_crnti);
2353
2354     proto_item_set_len(rar_body_ti, offset-start_body_offset);
2355
2356     return offset;
2357 }
2358
2359
2360 #define MAX_RAR_PDUS 64
2361 /* Dissect Random Access Reponse (RAR) PDU */
2362 static void dissect_rar(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *pdu_ti,
2363                         gint offset, mac_lte_info *p_mac_lte_info, mac_lte_tap_info *tap_info)
2364 {
2365     gint        number_of_rars         = 0; /* No of RAR bodies expected following headers */
2366     guint8     *rapids                 = (guint8 *)wmem_alloc(wmem_packet_scope(), MAX_RAR_PDUS * sizeof(guint8));
2367     gboolean    backoff_indicator_seen = FALSE;
2368     guint8      backoff_indicator      = 0;
2369     guint8      extension;
2370     gint        n;
2371     proto_tree *rar_headers_tree;
2372     proto_item *ti;
2373     proto_item *rar_headers_ti;
2374     proto_item *padding_length_ti;
2375     int         start_headers_offset   = offset;
2376
2377     write_pdu_label_and_info(pdu_ti, NULL, pinfo,
2378                              "RAR (RA-RNTI=%u, SFN=%-4u, SF=%u) ",
2379                              p_mac_lte_info->rnti, p_mac_lte_info->sysframeNumber, p_mac_lte_info->subframeNumber);
2380
2381     /* Create hidden 'virtual root' so can filter on mac-lte.rar */
2382     ti = proto_tree_add_item(tree, hf_mac_lte_rar, tvb, offset, -1, ENC_NA);
2383     PROTO_ITEM_SET_HIDDEN(ti);
2384
2385     /* Create headers tree */
2386     rar_headers_ti = proto_tree_add_item(tree,
2387                                          hf_mac_lte_rar_headers,
2388                                          tvb, offset, 0, ENC_ASCII|ENC_NA);
2389     rar_headers_tree = proto_item_add_subtree(rar_headers_ti, ett_mac_lte_rar_headers);
2390
2391
2392     /***************************/
2393     /* Read the header entries */
2394     do {
2395         int start_header_offset = offset;
2396         proto_tree *rar_header_tree;
2397         proto_item *rar_header_ti;
2398         guint8 type_value;
2399         guint8 first_byte = tvb_get_guint8(tvb, offset);
2400
2401         /* Create tree for this header */
2402         rar_header_ti = proto_tree_add_item(rar_headers_tree,
2403                                             hf_mac_lte_rar_header,
2404                                             tvb, offset, 0, ENC_ASCII|ENC_NA);
2405         rar_header_tree = proto_item_add_subtree(rar_header_ti, ett_mac_lte_rar_header);
2406
2407         /* Extension */
2408         extension = (first_byte & 0x80) >> 7;
2409         proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_extension, tvb, offset, 1, ENC_BIG_ENDIAN);
2410
2411         /* Type */
2412         type_value = (first_byte & 0x40) >> 6;
2413         proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_t, tvb, offset, 1, ENC_BIG_ENDIAN);
2414
2415         if (type_value == 0) {
2416             /* Backoff Indicator (BI) case */
2417
2418             guint8 reserved;
2419             proto_item *tii;
2420             proto_item *bi_ti;
2421
2422             /* 2 Reserved bits */
2423             reserved = (tvb_get_guint8(tvb, offset) & 0x30) >> 4;
2424             tii = proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
2425             if (reserved != 0) {
2426                 expert_add_info_format(pinfo, tii, &ei_mac_lte_reserved_not_zero,
2427                                        "RAR header Reserved bits not zero (found 0x%x)", reserved);
2428             }
2429
2430             /* Backoff Indicator */
2431             backoff_indicator = tvb_get_guint8(tvb, offset) & 0x0f;
2432             bi_ti = proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_bi, tvb, offset, 1, ENC_BIG_ENDIAN);
2433
2434             /* As of March 2009 spec, it must be first, and may only appear once */
2435             if (backoff_indicator_seen) {
2436                 expert_add_info(pinfo, bi_ti, &ei_mac_lte_rar_bi_present);
2437             }
2438             backoff_indicator_seen = TRUE;
2439
2440             write_pdu_label_and_info(pdu_ti, rar_header_ti, pinfo,
2441                                      "(Backoff Indicator=%sms)",
2442                                      val_to_str_const(backoff_indicator, rar_bi_vals, "Illegal-value "));
2443
2444             /* If present, it must be the first subheader */
2445             if (number_of_rars > 0) {
2446                 expert_add_info(pinfo, bi_ti, &ei_mac_lte_rar_bi_not_first_subheader);
2447             }
2448
2449         }
2450         else {
2451             /* RAPID case */
2452             /* TODO: complain if the same RAPID appears twice in same frame? */
2453             rapids[number_of_rars] = tvb_get_guint8(tvb, offset) & 0x3f;
2454             proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_rapid, tvb, offset, 1, ENC_BIG_ENDIAN);
2455
2456             proto_item_append_text(rar_header_ti, "(RAPID=%u)", rapids[number_of_rars]);
2457
2458             number_of_rars++;
2459         }
2460
2461         offset++;
2462
2463         /* Finalise length of header tree selection */
2464         proto_item_set_len(rar_header_ti, offset - start_header_offset);
2465
2466     } while (extension && number_of_rars < MAX_RAR_PDUS);
2467
2468     /* Append summary to headers root */
2469     proto_item_append_text(rar_headers_ti, " (%u RARs", number_of_rars);
2470     ti = proto_tree_add_uint(rar_headers_tree, hf_mac_lte_rar_no_of_rapids, tvb, 0, 0, number_of_rars);
2471     PROTO_ITEM_SET_GENERATED(ti);
2472     if (backoff_indicator_seen) {
2473         proto_item_append_text(rar_headers_ti, ", BI=%sms)",
2474                                val_to_str_const(backoff_indicator, rar_bi_vals, "Illegal-value "));
2475     }
2476     else {
2477         proto_item_append_text(rar_headers_ti, ")");
2478     }
2479
2480     /* Set length for headers root */
2481     proto_item_set_len(rar_headers_ti, offset-start_headers_offset);
2482
2483
2484     /***************************/
2485     /* Read any indicated RARs */
2486     for (n=0; n < number_of_rars; n++) {
2487         offset = dissect_rar_entry(tvb, pinfo, tree, pdu_ti, offset, rapids[n]);
2488     }
2489
2490     /* Update TAP info */
2491     tap_info->number_of_rars += number_of_rars;
2492
2493     /* Padding may follow */
2494     if (tvb_length_remaining(tvb, offset) > 0) {
2495         proto_tree_add_item(tree, hf_mac_lte_padding_data,
2496                             tvb, offset, -1, ENC_NA);
2497     }
2498     padding_length_ti = proto_tree_add_int(tree, hf_mac_lte_padding_length,
2499                                            tvb, offset, 0,
2500                                            p_mac_lte_info->length - offset);
2501     PROTO_ITEM_SET_GENERATED(padding_length_ti);
2502
2503     /* Update padding bytes in stats */
2504     tap_info->padding_bytes += (p_mac_lte_info->length - offset);
2505 }
2506
2507
2508 /* Dissect BCH PDU */
2509 static void dissect_bch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2510                         proto_item *pdu_ti,
2511                         int offset, mac_lte_info *p_mac_lte_info)
2512 {
2513     proto_item *ti;
2514
2515     write_pdu_label_and_info(pdu_ti, NULL, pinfo,
2516                              "BCH PDU (%u bytes, on %s transport)  ",
2517                              tvb_length_remaining(tvb, offset),
2518                              val_to_str_const(p_mac_lte_info->rntiType,
2519                                               bch_transport_channel_vals,
2520                                               "Unknown"));
2521
2522     /* Show which transport layer it came in on (inferred from RNTI type) */
2523     ti = proto_tree_add_uint(tree, hf_mac_lte_context_bch_transport_channel,
2524                              tvb, offset, 0, p_mac_lte_info->rntiType);
2525     PROTO_ITEM_SET_GENERATED(ti);
2526
2527     /****************************************/
2528     /* Whole frame is BCH data              */
2529
2530     /* Raw data */
2531     ti = proto_tree_add_item(tree, hf_mac_lte_bch_pdu,
2532                              tvb, offset, -1, ENC_NA);
2533
2534     if (global_mac_lte_attempt_rrc_decode) {
2535         /* Attempt to decode payload using LTE RRC dissector */
2536         tvbuff_t *rrc_tvb = tvb_new_subset_remaining(tvb, offset);
2537
2538         /* Get appropriate dissector handle */
2539         dissector_handle_t protocol_handle = 0;
2540         if (p_mac_lte_info->rntiType == SI_RNTI) {
2541             protocol_handle = find_dissector("lte_rrc.bcch_dl_sch");
2542         }
2543         else {
2544             protocol_handle = find_dissector("lte_rrc.bcch_bch");
2545         }
2546
2547         /* Hide raw view of bytes */
2548         PROTO_ITEM_SET_HIDDEN(ti);
2549
2550         call_with_catch_all(protocol_handle, rrc_tvb, pinfo, tree);
2551     }
2552
2553     /* Check that this *is* downlink! */
2554     if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
2555         expert_add_info(pinfo, ti, &ei_mac_lte_bch_pdu);
2556     }
2557 }
2558
2559
2560 /* Dissect PCH PDU */
2561 static void dissect_pch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2562                         proto_item *pdu_ti, int offset, guint8 direction,  mac_lte_tap_info *tap_info)
2563 {
2564     proto_item *ti;
2565
2566     write_pdu_label_and_info(pdu_ti, NULL, pinfo,
2567                              "PCH PDU (%u bytes)  ",
2568                              tvb_length_remaining(tvb, offset));
2569
2570     /****************************************/
2571     /* Whole frame is PCH data              */
2572
2573     /* Always show as raw data */
2574     ti = proto_tree_add_item(tree, hf_mac_lte_pch_pdu,
2575                              tvb, offset, -1, ENC_NA);
2576
2577     /* Get number of paging IDs for tap */
2578     tap_info->number_of_paging_ids = (tvb_get_guint8(tvb, offset) & 0x40) ?
2579                                         ((tvb_get_ntohs(tvb, offset) >> 7) & 0x000f) + 1 : 0;
2580
2581     if (global_mac_lte_attempt_rrc_decode) {
2582
2583         /* Attempt to decode payload using LTE RRC dissector */
2584         tvbuff_t *rrc_tvb = tvb_new_subset_remaining(tvb, offset);
2585
2586         /* Get appropriate dissector handle */
2587         dissector_handle_t protocol_handle = find_dissector("lte_rrc.pcch");
2588
2589         /* Hide raw view of bytes */
2590         PROTO_ITEM_SET_HIDDEN(ti);
2591
2592         /* Call it (catch exceptions so that stats will be updated) */
2593         call_with_catch_all(protocol_handle, rrc_tvb, pinfo, tree);
2594     }
2595
2596     /* Check that this *is* downlink! */
2597     if (direction == DIRECTION_UPLINK) {
2598         expert_add_info(pinfo, ti, &ei_mac_lte_pch_pdu);
2599     }
2600 }
2601
2602
2603 /* Does this header entry correspond to a fixed-sized control element? */
2604 static int is_fixed_sized_control_element(guint8 lcid, guint8 direction)
2605 {
2606     if (direction == DIRECTION_UPLINK) {
2607         /* Uplink */
2608         switch (lcid) {
2609             case POWER_HEADROOM_REPORT_LCID:
2610             case CRNTI_LCID:
2611             case TRUNCATED_BSR_LCID:
2612             case SHORT_BSR_LCID:
2613             case LONG_BSR_LCID:
2614                 return TRUE;
2615
2616             default:
2617                 return FALSE;
2618         }
2619     }
2620     else {
2621         /* Assume Downlink */
2622         switch (lcid) {
2623             case ACTIVATION_DEACTIVATION_LCID:
2624             case UE_CONTENTION_RESOLUTION_IDENTITY_LCID:
2625             case TIMING_ADVANCE_LCID:
2626             case DRX_COMMAND_LCID:
2627                 return TRUE;
2628
2629             default:
2630                 return FALSE;
2631         }
2632     }
2633 }
2634
2635
2636 /* Is this a BSR report header? */
2637 static int is_bsr_lcid(guint8 lcid)
2638 {
2639     return ((lcid == TRUNCATED_BSR_LCID) ||
2640             (lcid == SHORT_BSR_LCID) ||
2641             (lcid == LONG_BSR_LCID));
2642 }
2643
2644
2645 /* Helper function to call RLC dissector for SDUs (where channel params are known) */
2646 static void call_rlc_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2647                                proto_item *pdu_ti,
2648                                int offset, guint16 data_length,
2649                                guint8 mode, guint8 direction, guint16 ueid,
2650                                guint16 channelType, guint16 channelId,
2651                                guint8 UMSequenceNumberLength,
2652                                guint8 priority)
2653 {
2654     tvbuff_t            *rb_tvb = tvb_new_subset(tvb, offset, data_length, data_length);
2655     struct rlc_lte_info *p_rlc_lte_info;
2656
2657     /* Resuse or create RLC info */
2658     p_rlc_lte_info = (rlc_lte_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc_lte, 0);
2659     if (p_rlc_lte_info == NULL) {
2660         p_rlc_lte_info = wmem_new0(wmem_file_scope(), struct rlc_lte_info);
2661     }
2662
2663     /* Fill in struct details for srb channels */
2664     p_rlc_lte_info->rlcMode = mode;
2665     p_rlc_lte_info->direction = direction;
2666     p_rlc_lte_info->priority = priority;
2667     p_rlc_lte_info->ueid = ueid;
2668     p_rlc_lte_info->channelType = channelType;
2669     p_rlc_lte_info->channelId = channelId;
2670     p_rlc_lte_info->pduLength = data_length;
2671     p_rlc_lte_info->UMSequenceNumberLength = UMSequenceNumberLength;
2672
2673     /* Store info in packet */
2674     p_add_proto_data(wmem_file_scope(), pinfo, proto_rlc_lte, 0, p_rlc_lte_info);
2675
2676     if (global_mac_lte_layer_to_show != ShowRLCLayer) {
2677         /* Don't want these columns replaced */
2678         col_set_writable(pinfo->cinfo, FALSE);
2679     }
2680     else {
2681         /* Clear info column before first RLC PDU */
2682         if (s_number_of_rlc_pdus_shown == 0) {
2683             col_clear(pinfo->cinfo, COL_INFO);
2684         }
2685         else {
2686             /* Add a separator and protect column contents here */
2687             write_pdu_label_and_info_literal(pdu_ti, NULL, pinfo, "   ||   ");
2688             col_set_fence(pinfo->cinfo, COL_INFO);
2689         }
2690     }
2691     s_number_of_rlc_pdus_shown++;
2692
2693     /* Call it (catch exceptions so that stats will be updated) */
2694     call_with_catch_all(rlc_lte_handle, rb_tvb, pinfo, tree);
2695
2696     /* Let columns be written to again */
2697     col_set_writable(pinfo->cinfo, TRUE);
2698 }
2699
2700
2701 /* For DL frames, look for previous Tx. Add link back if found */
2702 static void TrackReportedDLHARQResend(packet_info *pinfo, tvbuff_t *tvb, volatile int length,
2703                                       proto_tree *tree, mac_lte_info *p_mac_lte_info)
2704 {
2705     DLHARQResult *result = NULL;
2706     DLHARQResult *original_result = NULL;
2707
2708     /* If don't have detailed DL PHy info, just give up */
2709     if (!p_mac_lte_info->detailed_phy_info.dl_info.present) {
2710         return;
2711     }
2712
2713     /* TDD may not work... */
2714
2715     if (!pinfo->fd->flags.visited) {
2716         /* First time, so set result and update DL harq table */
2717         LastFrameData *lastData = NULL;
2718         LastFrameData *thisData = NULL;
2719
2720         DLHarqBuffers *ueData;
2721
2722         /* Read these for convenience */
2723         guint8 harq_id = p_mac_lte_info->detailed_phy_info.dl_info.harq_id;
2724         guint8 transport_block = p_mac_lte_info->detailed_phy_info.dl_info.transport_block;
2725
2726         /* Check harq-id bounds, give up if invalid */
2727         if ((harq_id >= 15) || (transport_block > 1)) {
2728             return;
2729         }
2730
2731         /* Look up entry for this UE/RNTI */
2732         ueData = (DLHarqBuffers *)g_hash_table_lookup(mac_lte_dl_harq_hash, GUINT_TO_POINTER((guint)p_mac_lte_info->rnti));
2733
2734         if (ueData != NULL) {
2735             /* Get previous info for this harq-id */
2736             lastData = &(ueData->harqid[transport_block][harq_id]);
2737             if (lastData->inUse) {
2738                 /* Compare time difference, ndi, data to see if this looks like a retx */
2739                 if ((length == lastData->length) &&
2740                     (p_mac_lte_info->detailed_phy_info.dl_info.ndi == lastData->ndi) &&
2741                     tvb_memeql(tvb, 0, lastData->data, MIN(lastData->length, MAX_EXPECTED_PDU_LENGTH)) == 0) {
2742
2743                     /* Work out gap between frames */
2744                     gint seconds_between_packets = (gint)
2745                           (pinfo->fd->abs_ts.secs - lastData->received_time.secs);
2746                     gint nseconds_between_packets =
2747                           pinfo->fd->abs_ts.nsecs - lastData->received_time.nsecs;
2748
2749                     /* Round difference to nearest millisecond */
2750                     gint total_gap = (seconds_between_packets*1000) +
2751                                      ((nseconds_between_packets+500000) / 1000000);
2752
2753                     /* Expect to be within (say) 8-13 subframes since previous */
2754                     if ((total_gap >= 8) && (total_gap <= 13)) {
2755
2756                         /* Resend detected! Store result pointing back. */
2757                         result = wmem_new0(wmem_file_scope(), DLHARQResult);
2758                         result->previousSet = TRUE;
2759                         result->previousFrameNum = lastData->framenum;
2760                         result->timeSincePreviousFrame = total_gap;
2761                         g_hash_table_insert(mac_lte_dl_harq_result_hash, GUINT_TO_POINTER(pinfo->fd->num), result);
2762
2763                         /* Now make previous frame point forward to here */
2764                         original_result = (DLHARQResult *)g_hash_table_lookup(mac_lte_dl_harq_result_hash, GUINT_TO_POINTER(lastData->framenum));
2765                         if (original_result == NULL) {
2766                             original_result = wmem_new0(wmem_file_scope(), DLHARQResult);
2767                             g_hash_table_insert(mac_lte_dl_harq_result_hash, GUINT_TO_POINTER(lastData->framenum), original_result);
2768                         }
2769                         original_result->nextSet = TRUE;
2770                         original_result->nextFrameNum = pinfo->fd->num;
2771                         original_result->timeToNextFrame = total_gap;
2772                     }
2773                 }
2774             }
2775         }
2776         else {
2777             /* Allocate entry in table for this UE/RNTI */
2778             ueData = wmem_new0(wmem_file_scope(), DLHarqBuffers);
2779             g_hash_table_insert(mac_lte_dl_harq_hash, GUINT_TO_POINTER((guint)p_mac_lte_info->rnti), ueData);
2780         }
2781
2782         /* Store this frame's details in table */
2783         thisData = &(ueData->harqid[transport_block][harq_id]);
2784         thisData->inUse = TRUE;
2785         thisData->length = length;
2786         tvb_memcpy(tvb, thisData->data, 0, MIN(thisData->length, MAX_EXPECTED_PDU_LENGTH));
2787         thisData->ndi = p_mac_lte_info->detailed_phy_info.dl_info.ndi;
2788         thisData->framenum = pinfo->fd->num;
2789         thisData->received_time = pinfo->fd->abs_ts;
2790     }
2791     else {
2792         /* Not first time, so just set whats already stored in result */
2793         result = (DLHARQResult *)g_hash_table_lookup(mac_lte_dl_harq_result_hash, GUINT_TO_POINTER(pinfo->fd->num));
2794     }
2795
2796
2797     /***************************************************/
2798     /* Show link back to original frame (if available) */
2799     if (result != NULL) {
2800         if (result->previousSet) {
2801             proto_item *gap_ti;
2802             proto_item *original_ti = proto_tree_add_uint(tree, hf_mac_lte_dl_harq_resend_original_frame,
2803                                                           tvb, 0, 0, result->previousFrameNum);
2804             PROTO_ITEM_SET_GENERATED(original_ti);
2805
2806             gap_ti = proto_tree_add_uint(tree, hf_mac_lte_dl_harq_resend_time_since_previous_frame,
2807                                          tvb, 0, 0, result->timeSincePreviousFrame);
2808             PROTO_ITEM_SET_GENERATED(gap_ti);
2809         }
2810
2811         if (result->nextSet) {
2812             proto_item *gap_ti;
2813             proto_item *next_ti = proto_tree_add_uint(tree, hf_mac_lte_dl_harq_resend_next_frame,
2814                                                       tvb, 0, 0, result->nextFrameNum);
2815             PROTO_ITEM_SET_GENERATED(next_ti);
2816
2817             gap_ti = proto_tree_add_uint(tree, hf_mac_lte_dl_harq_resend_time_until_next_frame,
2818                                          tvb, 0, 0, result->timeToNextFrame);
2819             PROTO_ITEM_SET_GENERATED(gap_ti);
2820         }
2821
2822     }
2823 }
2824
2825
2826 /* Return TRUE if the given packet is thought to be a retx */
2827 int is_mac_lte_frame_retx(packet_info *pinfo, guint8 direction)
2828 {
2829     struct mac_lte_info *p_mac_lte_info = (struct mac_lte_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_mac_lte, 0);
2830
2831     if (p_mac_lte_info == NULL) {
2832         return FALSE;
2833     }
2834
2835     if (direction == DIRECTION_UPLINK) {
2836         /* For UL, retx count is stored in per-packet struct */
2837         return (p_mac_lte_info->reTxCount > 0);
2838     }
2839     else {
2840         /* Use answer if told directly */
2841         if (p_mac_lte_info->dl_retx == dl_retx_yes) {
2842             return TRUE;
2843         }
2844         else {
2845             /* Otherwise look up in table */
2846             DLHARQResult *result = (DLHARQResult *)g_hash_table_lookup(mac_lte_dl_harq_result_hash, GUINT_TO_POINTER(pinfo->fd->num));
2847             return ((result != NULL) && result->previousSet);
2848         }
2849     }
2850 }
2851
2852
2853 /* Track UL frames, so that when a retx is indicated, we can search for
2854    the original tx.  We will either find it, and provide a link back to it,
2855    or flag that we couldn't find as an expert error */
2856 static void TrackReportedULHARQResend(packet_info *pinfo, tvbuff_t *tvb, volatile int offset,
2857                                       proto_tree *tree, mac_lte_info *p_mac_lte_info,
2858                                       proto_item *retx_ti)
2859 {
2860     ULHARQResult *result = NULL;
2861
2862     /* If don't have detailed DL PHY info, just give up */
2863     if (!p_mac_lte_info->detailed_phy_info.ul_info.present) {
2864         return;
2865     }
2866
2867     /* Give up if harqid is out of range */
2868     if (p_mac_lte_info->detailed_phy_info.ul_info.harq_id >= 8) {
2869         return;
2870     }
2871
2872     if (!pinfo->fd->flags.visited) {
2873         /* First time, so set result and update UL harq table */
2874         LastFrameData *lastData = NULL;
2875         LastFrameData *thisData = NULL;
2876
2877         /* Look up entry for this UE/RNTI */
2878         ULHarqBuffers *ueData = (ULHarqBuffers *)g_hash_table_lookup(
2879             mac_lte_ul_harq_hash, GUINT_TO_POINTER((guint)p_mac_lte_info->rnti));
2880         if (ueData != NULL) {
2881             if (p_mac_lte_info->reTxCount >= 1) {
2882                 /* Looking for frame previously on this harq-id */
2883                 lastData = &(ueData->harqid[p_mac_lte_info->detailed_phy_info.ul_info.harq_id]);
2884                 if (lastData->inUse) {
2885                     /* Compare time, sf, data to see if this looks like a retx */
2886                     if ((tvb_length_remaining(tvb, offset) == lastData->length) &&
2887                         (p_mac_lte_info->detailed_phy_info.ul_info.ndi == lastData->ndi) &&
2888                         tvb_memeql(tvb, offset, lastData->data, MIN(lastData->length, MAX_EXPECTED_PDU_LENGTH)) == 0) {
2889
2890                         /* Work out gap between frames */
2891                         gint seconds_between_packets = (gint)
2892                               (pinfo->fd->abs_ts.secs - lastData->received_time.secs);
2893                         gint nseconds_between_packets =
2894                               pinfo->fd->abs_ts.nsecs - lastData->received_time.nsecs;
2895
2896                         /* Round to nearest ms */
2897                         gint total_gap = (seconds_between_packets*1000) +
2898                                          ((nseconds_between_packets+500000) / 1000000);
2899
2900                         /* Could be as many as max-tx (which we don't know) * 8ms ago.
2901                            32 is the most I've seen... */
2902                         if (total_gap <= 33) {
2903                             ULHARQResult *original_result;
2904
2905                             /* Original detected!!! Store result pointing back */
2906                             result = wmem_new0(wmem_file_scope(), ULHARQResult);
2907                             result->previousSet = TRUE;
2908                             result->previousFrameNum = lastData->framenum;
2909                             result->timeSincePreviousFrame = total_gap;
2910                             g_hash_table_insert(mac_lte_ul_harq_result_hash, GUINT_TO_POINTER(pinfo->fd->num), result);
2911
2912                             /* Now make previous frame point forward to here */
2913                             original_result = (ULHARQResult *)g_hash_table_lookup(mac_lte_ul_harq_result_hash, GUINT_TO_POINTER(lastData->framenum));
2914                             if (original_result == NULL) {
2915                                 original_result = wmem_new0(wmem_file_scope(), ULHARQResult);
2916                                 g_hash_table_insert(mac_lte_ul_harq_result_hash, GUINT_TO_POINTER(lastData->framenum), original_result);
2917                             }
2918                             original_result->nextSet = TRUE;
2919                             original_result->nextFrameNum = pinfo->fd->num;
2920                             original_result->timeToNextFrame = total_gap;
2921                         }
2922                     }
2923                 }
2924             }
2925         }
2926         else {
2927             /* Allocate entry in table for this UE/RNTI */
2928             ueData = wmem_new0(wmem_file_scope(), ULHarqBuffers);
2929             g_hash_table_insert(mac_lte_ul_harq_hash, GUINT_TO_POINTER((guint)p_mac_lte_info->rnti), ueData);
2930         }
2931
2932         /* Store this frame's details in table */
2933         thisData = &(ueData->harqid[p_mac_lte_info->detailed_phy_info.ul_info.harq_id]);
2934         thisData->inUse = TRUE;
2935         thisData->length = tvb_length_remaining(tvb, offset);
2936         tvb_memcpy(tvb, thisData->data, offset, MIN(thisData->length, MAX_EXPECTED_PDU_LENGTH));
2937         thisData->ndi = p_mac_lte_info->detailed_phy_info.ul_info.ndi;
2938         thisData->framenum = pinfo->fd->num;
2939         thisData->received_time = pinfo->fd->abs_ts;
2940     }
2941     else {
2942         /* Not first time, so just get whats already stored in result */
2943         result = (ULHARQResult *)g_hash_table_lookup(mac_lte_ul_harq_result_hash, GUINT_TO_POINTER(pinfo->fd->num));
2944     }
2945
2946     /* Show any link back to previous Tx */
2947     if (retx_ti != NULL) {
2948         if (result != NULL) {
2949             if (result->previousSet) {
2950                 proto_item *original_ti, *gap_ti;
2951
2952                 original_ti = proto_tree_add_uint(tree, hf_mac_lte_ul_harq_resend_original_frame,
2953                                                   tvb, 0, 0, result->previousFrameNum);
2954                 PROTO_ITEM_SET_GENERATED(original_ti);
2955
2956                 gap_ti = proto_tree_add_uint(tree, hf_mac_lte_ul_harq_resend_time_since_previous_frame,
2957                                              tvb, 0, 0, result->timeSincePreviousFrame);
2958                 PROTO_ITEM_SET_GENERATED(gap_ti);
2959             }
2960         }
2961         else {
2962             expert_add_info_format(pinfo, retx_ti, &ei_mac_lte_orig_tx_ul_frame_not_found,
2963                                    "Original Tx of UL frame not found (UE %u) !!", p_mac_lte_info->ueid);
2964         }
2965     }
2966
2967     /* Show link forward to any known next Tx */
2968     if ((result != NULL) && result->nextSet) {
2969         proto_item *next_ti, *gap_ti;
2970
2971         next_ti = proto_tree_add_uint(tree, hf_mac_lte_ul_harq_resend_next_frame,
2972                                           tvb, 0, 0, result->nextFrameNum);
2973         expert_add_info_format(pinfo, next_ti, &ei_mac_lte_ul_harq_resend_next_frame,
2974                                "UL MAC PDU (UE %u) needed to be retransmitted", p_mac_lte_info->ueid);
2975
2976         PROTO_ITEM_SET_GENERATED(next_ti);
2977
2978         gap_ti = proto_tree_add_uint(tree, hf_mac_lte_ul_harq_resend_time_until_next_frame,
2979                                      tvb, 0, 0, result->timeToNextFrame);
2980         PROTO_ITEM_SET_GENERATED(gap_ti);
2981     }
2982 }
2983
2984
2985 /* Look up SRResult associated with a given frame. Will create one if necessary
2986    if can_create is set */
2987 static SRResult *GetSRResult(guint32 frameNum, gboolean can_create)
2988 {
2989     SRResult *result;
2990     result = (SRResult *)g_hash_table_lookup(mac_lte_sr_request_hash, GUINT_TO_POINTER(frameNum));
2991
2992     if ((result == NULL) && can_create) {
2993         result = wmem_new0(wmem_file_scope(), SRResult);
2994         g_hash_table_insert(mac_lte_sr_request_hash, GUINT_TO_POINTER((guint)frameNum), result);
2995     }
2996     return result;
2997 }
2998
2999
3000 /* Keep track of SR requests, failures and related grants, in order to show them
3001    as generated fields in these frames */
3002 static void TrackSRInfo(SREvent event, packet_info *pinfo, proto_tree *tree,
3003                         tvbuff_t *tvb, mac_lte_info *p_mac_lte_info, gint idx, proto_item *event_ti)
3004 {
3005     SRResult   *result           = NULL;
3006     SRState    *state;
3007     SRResult   *resultForSRFrame = NULL;
3008
3009     guint16     rnti;
3010     guint16     ueid;
3011     proto_item *ti;
3012
3013     /* Get appropriate identifiers */
3014     if (event == SR_Request) {
3015         rnti = p_mac_lte_info->oob_rnti[idx];
3016         ueid = p_mac_lte_info->oob_ueid[idx];
3017     }
3018     else {
3019         rnti = p_mac_lte_info->rnti;
3020         ueid = p_mac_lte_info->ueid;
3021     }
3022
3023     /* Create state for this RNTI if necessary */
3024     state = (SRState *)g_hash_table_lookup(mac_lte_ue_sr_state, GUINT_TO_POINTER((guint)rnti));
3025     if (state == NULL) {
3026         /* Allocate status for this RNTI */
3027         state = wmem_new(wmem_file_scope(), SRState);
3028         state->status = None;
3029         g_hash_table_insert(mac_lte_ue_sr_state, GUINT_TO_POINTER((guint)rnti), state);
3030     }
3031
3032     /* First time through - update state with new info */
3033     if (!pinfo->fd->flags.visited) {
3034         guint32 timeSinceRequest;
3035
3036         /* Store time of request */
3037         if (event == SR_Request) {
3038             state->requestTime = pinfo->fd->abs_ts;
3039         }
3040
3041         switch (state->status) {
3042             case None:
3043                 switch (event) {
3044                     case SR_Grant:
3045                         /* Got another grant - fine */
3046
3047                         /* update state */
3048                         state->lastGrantFramenum = pinfo->fd->num;
3049                         break;
3050
3051                     case SR_Request:
3052                         /* Sent an SR - fine */
3053
3054                         /* Update state */
3055                         state->status = SR_Outstanding;
3056                         state->lastSRFramenum = pinfo->fd->num;
3057                         break;
3058
3059                     case SR_Failure:
3060                         /* This is an error, since we hadn't send an SR... */
3061                         result = GetSRResult(pinfo->fd->num, TRUE);
3062                         result->type = InvalidSREvent;
3063                         result->status = None;
3064                         result->event = SR_Failure;
3065                         break;
3066                 }
3067                 break;
3068
3069             case SR_Outstanding:
3070                 timeSinceRequest = (guint32)(((pinfo->fd->abs_ts.secs - state->requestTime.secs) * 1000) +
3071                                              ((pinfo->fd->abs_ts.nsecs - state->requestTime.nsecs) / 1000000));
3072
3073                 switch (event) {
3074                     case SR_Grant:
3075                         /* Got grant we were waiting for, so state goes to None */
3076
3077                         /* Update state */
3078                         state->status = None;
3079
3080                         /* Set result info */
3081                         result = GetSRResult(pinfo->fd->num, TRUE);
3082                         result->type = GrantAnsweringSR;
3083                         result->frameNum = state->lastSRFramenum;
3084                         result->timeDifference = timeSinceRequest;
3085
3086                         /* Also set forward link for SR */
3087                         resultForSRFrame = GetSRResult(state->lastSRFramenum, TRUE);
3088                         resultForSRFrame->type = SRLeadingToGrant;
3089                         resultForSRFrame->frameNum = pinfo->fd->num;
3090                         resultForSRFrame->timeDifference = timeSinceRequest;
3091                         break;
3092
3093                     case SR_Request:
3094                         /* Another request when already have one pending */
3095                         result = GetSRResult(pinfo->fd->num, TRUE);
3096                         result->type = InvalidSREvent;
3097                         result->status = SR_Outstanding;
3098                         result->event = SR_Request;
3099                         break;
3100
3101                     case SR_Failure:
3102                         /* We sent an SR but it failed */
3103
3104                         /* Update state */
3105                         state->status = SR_Failed;
3106
3107                         /* Set result info for failure frame */
3108                         result = GetSRResult(pinfo->fd->num, TRUE);
3109                         result->type = FailureAnsweringSR;
3110                         result->frameNum = state->lastSRFramenum;
3111                         result->timeDifference = timeSinceRequest;
3112
3113                         /* Also set forward link for SR */
3114                         resultForSRFrame = GetSRResult(state->lastSRFramenum, TRUE);
3115                         resultForSRFrame->type = SRLeadingToFailure;
3116                         resultForSRFrame->frameNum = pinfo->fd->num;
3117                         resultForSRFrame->timeDifference = timeSinceRequest;
3118                         break;
3119                 }
3120                 break;
3121
3122             case SR_Failed:
3123                 switch (event) {
3124                     case SR_Grant:
3125                         /* Got a grant, presumably after a subsequent RACH - fine */
3126
3127                         /* Update state */
3128                         state->status = None;
3129                         break;
3130
3131                     case SR_Request:
3132                         /* Tried another SR after previous one failed.
3133                            Presumably a subsequent RACH was tried in-between... */
3134
3135                         state->status = SR_Outstanding;
3136
3137                         result = GetSRResult(pinfo->fd->num, TRUE);
3138                         result->status = SR_Outstanding;
3139                         result->event = SR_Request;
3140                         break;
3141
3142                     case SR_Failure:
3143                         /* 2 failures in a row.... */
3144                         result = GetSRResult(pinfo->fd->num, TRUE);
3145                         result->type = InvalidSREvent;
3146                         result->status = SR_Failed;
3147                         result->event = SR_Failure;
3148                         break;
3149                 }
3150                 break;
3151         }
3152     }
3153
3154     /* Get stored result for this frame */
3155     result = GetSRResult(pinfo->fd->num, FALSE);
3156     if (result == NULL) {
3157         /* For an SR frame, there should always be either a PDCCH grant or indication
3158            that the SR has failed */
3159         if (event == SR_Request) {
3160             expert_add_info_format(pinfo, event_ti, &ei_mac_lte_sr_results_not_grant_or_failure_indication,
3161                                    "UE %u: SR results in neither a grant nor a failure indication",
3162                                    ueid);
3163         }
3164         return;
3165     }
3166
3167
3168     /* Show result info */
3169     switch (result->type) {
3170         case GrantAnsweringSR:
3171             ti = proto_tree_add_uint(tree, hf_mac_lte_grant_answering_sr,
3172                                      tvb, 0, 0, result->frameNum);
3173             PROTO_ITEM_SET_GENERATED(ti);
3174             ti = proto_tree_add_uint(tree, hf_mac_lte_sr_time_since_request,
3175                                      tvb, 0, 0, result->timeDifference);
3176             PROTO_ITEM_SET_GENERATED(ti);
3177             break;
3178
3179         case FailureAnsweringSR:
3180             ti = proto_tree_add_uint(tree, hf_mac_lte_failure_answering_sr,
3181                                      tvb, 0, 0, result->frameNum);
3182             PROTO_ITEM_SET_GENERATED(ti);
3183             ti = proto_tree_add_uint(tree, hf_mac_lte_sr_time_since_request,
3184                                      tvb, 0, 0, result->timeDifference);
3185             PROTO_ITEM_SET_GENERATED(ti);
3186             break;
3187
3188         case SRLeadingToGrant:
3189             ti = proto_tree_add_uint(tree, hf_mac_lte_sr_leading_to_grant,
3190                                      tvb, 0, 0, result->frameNum);
3191             PROTO_ITEM_SET_GENERATED(ti);
3192             ti = proto_tree_add_uint(tree, hf_mac_lte_sr_time_until_answer,
3193                                      tvb, 0, 0, result->timeDifference);
3194             PROTO_ITEM_SET_GENERATED(ti);
3195
3196             break;
3197
3198         case SRLeadingToFailure:
3199             ti = proto_tree_add_uint(tree, hf_mac_lte_sr_leading_to_failure,
3200                                      tvb, 0, 0, result->frameNum);
3201             PROTO_ITEM_SET_GENERATED(ti);
3202             ti = proto_tree_add_uint(tree, hf_mac_lte_sr_time_until_answer,
3203                                      tvb, 0, 0, result->timeDifference);
3204             PROTO_ITEM_SET_GENERATED(ti);
3205             break;
3206
3207         case InvalidSREvent:
3208             proto_tree_add_expert_format(tree, pinfo, &ei_mac_lte_sr_invalid_event,
3209                                             tvb, 0, 0, "UE %u: Invalid SR event - state=%s, event=%s",
3210                                             ueid,
3211                                             val_to_str_const(result->status, sr_status_vals, "Unknown"),
3212                                             val_to_str_const(result->event,  sr_event_vals,  "Unknown"));
3213             break;
3214     }
3215 }
3216
3217
3218 /********************************************************/
3219 /* Count number of UEs/TTI (in both directions)         */
3220 /********************************************************/
3221
3222 /* For keeping track during first pass */
3223 typedef struct tti_info_t {
3224     guint16 subframe;
3225     nstime_t ttiStartTime;
3226     guint ues_in_tti;
3227 } tti_info_t;
3228
3229 static tti_info_t UL_tti_info;
3230 static tti_info_t DL_tti_info;
3231
3232 /* For associating with frame and displaying */
3233 typedef struct TTIInfoResult_t {
3234     guint ues_in_tti;
3235 } TTIInfoResult_t;
3236
3237 /* This table stores (FrameNumber -> *TTIInfoResult_t).  It is assigned during the first
3238    pass and used thereafter */
3239 static GHashTable *mac_lte_tti_info_result_hash = NULL;
3240
3241
3242 /* Work out which UE this is within TTI (within direction). Return answer */
3243 static guint16 count_ues_tti(mac_lte_info *p_mac_lte_info, packet_info *pinfo)
3244 {
3245     gboolean same_tti = FALSE;
3246     tti_info_t *tti_info;
3247
3248     /* Just return any previous result */
3249     TTIInfoResult_t *result = (TTIInfoResult_t *)g_hash_table_lookup(mac_lte_tti_info_result_hash, GUINT_TO_POINTER(pinfo->fd->num));
3250     if (result != NULL) {
3251         return result->ues_in_tti;
3252     }
3253
3254     /* Set tti_info based upon direction */
3255     if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
3256         tti_info = &UL_tti_info;
3257     }
3258     else {
3259         tti_info = &DL_tti_info;
3260     }
3261
3262     /* Work out if we are still in the same tti as before */
3263     if (tti_info->subframe == p_mac_lte_info->subframeNumber) {
3264         gint seconds_between_packets = (gint)
3265               (pinfo->fd->abs_ts.secs - tti_info->ttiStartTime.secs);
3266         gint nseconds_between_packets =
3267               pinfo->fd->abs_ts.nsecs -  tti_info->ttiStartTime.nsecs;
3268
3269         /* Round difference to nearest microsecond */
3270         gint total_us_gap = (seconds_between_packets*1000000) +
3271                            ((nseconds_between_packets+500) / 1000);
3272
3273         if (total_us_gap < 1000) {
3274             same_tti = TRUE;
3275         }
3276     }
3277
3278     /* Update global state */
3279     if (!same_tti) {
3280         tti_info->subframe = p_mac_lte_info->subframeNumber;
3281         tti_info->ttiStartTime = pinfo->fd->abs_ts;
3282         tti_info->ues_in_tti = 1;
3283     }
3284     else {
3285         tti_info->ues_in_tti++;
3286     }
3287
3288     /* Set result state for this frame */
3289     result = wmem_new(wmem_file_scope(), TTIInfoResult_t);
3290     result->ues_in_tti = tti_info->ues_in_tti;
3291     g_hash_table_insert(mac_lte_tti_info_result_hash,
3292                         GUINT_TO_POINTER(pinfo->fd->num), result);
3293
3294     return tti_info->ues_in_tti;
3295 }
3296
3297
3298 /* Show which UE this is (within direction) for this TTI */
3299 static void show_ues_tti(packet_info *pinfo, mac_lte_info *p_mac_lte_info, tvbuff_t *tvb, proto_tree *context_tree)
3300 {
3301     /* Look up result */
3302     TTIInfoResult_t *result = (TTIInfoResult_t *)g_hash_table_lookup(mac_lte_tti_info_result_hash, GUINT_TO_POINTER(pinfo->fd->num));
3303     if (result != NULL) {
3304         proto_item *ti =  proto_tree_add_uint(context_tree,
3305                                               (p_mac_lte_info->direction == DIRECTION_UPLINK) ?
3306                                                   hf_mac_lte_ues_ul_per_tti :
3307                                                   hf_mac_lte_ues_dl_per_tti,
3308                                               tvb, 0, 0, result->ues_in_tti);
3309         PROTO_ITEM_SET_GENERATED(ti);
3310     }
3311 }
3312
3313
3314
3315 /* Lookup channel details for lcid */
3316 static void lookup_rlc_channel_from_lcid(guint16 ueid,
3317                                          guint8 lcid,
3318                                          rlc_channel_type_t *rlc_channel_type,
3319                                          guint8 *UM_seqnum_length,
3320                                          gint *drb_id)
3321 {
3322     /* Zero params (in case no match is found) */
3323     *rlc_channel_type = rlcRaw;
3324     *UM_seqnum_length = 0;
3325     *drb_id           = 0;
3326
3327     if (global_mac_lte_lcid_drb_source == (int)FromStaticTable) {
3328
3329         /* Look up in static (UAT) table */
3330         guint m;
3331         for (m=0; m < num_lcid_drb_mappings; m++) {
3332             if (lcid == lcid_drb_mappings[m].lcid) {
3333
3334                 *rlc_channel_type = lcid_drb_mappings[m].channel_type;
3335
3336                 /* Set UM_seqnum_length */
3337                 switch (*rlc_channel_type) {
3338                     case rlcUM5:
3339                         *UM_seqnum_length = 5;
3340                         break;
3341                     case rlcUM10:
3342                         *UM_seqnum_length = 10;
3343                         break;
3344                     default:
3345                         break;
3346                 }
3347
3348                 /* Set drb_id */
3349                 *drb_id = lcid_drb_mappings[m].drbid;
3350                 break;
3351             }
3352         }
3353     }
3354     else {
3355         /* Look up the mappings for this UE */
3356         ue_dynamic_drb_mappings_t *ue_mappings = (ue_dynamic_drb_mappings_t *)g_hash_table_lookup(mac_lte_ue_channels_hash, GUINT_TO_POINTER((guint)ueid));
3357         if (!ue_mappings) {
3358             return;
3359         }
3360
3361         /* Look up setting gleaned from configuration protocol */
3362         if (!ue_mappings->mapping[lcid].valid) {
3363             return;
3364         }
3365
3366         *rlc_channel_type = ue_mappings->mapping[lcid].channel_type;
3367
3368         /* Set UM_seqnum_length */
3369         switch (*rlc_channel_type) {
3370             case rlcUM5:
3371                 *UM_seqnum_length = 5;
3372                 break;
3373             case rlcUM10:
3374                 *UM_seqnum_length = 10;
3375                 break;
3376             default:
3377                 break;
3378         }
3379
3380         /* Set drb_id */
3381         *drb_id = ue_mappings->mapping[lcid].drbid;
3382     }
3383 }
3384
3385
3386
3387 #define MAX_HEADERS_IN_PDU 1024
3388
3389 /* UL-SCH and DL-SCH formats have much in common, so handle them in a common
3390    function */
3391 static void dissect_ulsch_or_dlsch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
3392                                    proto_item *pdu_ti,
3393                                    volatile guint32 offset, guint8 direction,
3394                                    mac_lte_info *p_mac_lte_info, mac_lte_tap_info *tap_info,
3395                                    proto_item *retx_ti,
3396                                    proto_tree *context_tree,
3397                                    guint pdu_instance)
3398 {
3399     guint8            extension;
3400     volatile guint16  n;
3401     proto_item       *truncated_ti;
3402     proto_item       *padding_length_ti;
3403     proto_item       *hidden_root_ti;
3404
3405     /* Keep track of LCIDs and lengths as we dissect the header */
3406     volatile guint16 number_of_headers = 0;
3407     guint8           lcids[MAX_HEADERS_IN_PDU];
3408     gint16           pdu_lengths[MAX_HEADERS_IN_PDU];
3409
3410     proto_item *pdu_header_ti;
3411     proto_tree *pdu_header_tree;
3412
3413     gboolean   have_seen_data_header = FALSE;
3414     guint8     number_of_padding_subheaders = 0;
3415     gboolean   have_seen_non_padding_control = FALSE;
3416     gboolean   have_seen_bsr = FALSE;
3417     gboolean   expecting_body_data = FALSE;
3418     volatile   guint32    is_truncated = FALSE;
3419
3420     /* Maintain/show UEs/TTI count */
3421     tap_info->ueInTTI = count_ues_tti(p_mac_lte_info, pinfo);
3422     show_ues_tti(pinfo, p_mac_lte_info, tvb, context_tree);
3423
3424     write_pdu_label_and_info(pdu_ti, NULL, pinfo,
3425                              "%s: (SFN=%-4u, SF=%u) UEId=%-3u ",
3426                              (direction == DIRECTION_UPLINK) ? "UL-SCH" : "DL-SCH",
3427                              p_mac_lte_info->sysframeNumber,
3428                              p_mac_lte_info->subframeNumber,
3429                              p_mac_lte_info->ueid);
3430
3431     tap_info->raw_length = p_mac_lte_info->length;
3432
3433     /******************************************************/
3434     /* DRX information                                    */
3435
3436     /* Update DRX state of UE */
3437     if (global_mac_lte_show_drx) {
3438         if (!pinfo->fd->flags.visited) {
3439
3440             /* Update UE state to this subframe (but before this event is processed) */
3441             update_drx_info(pinfo, p_mac_lte_info);
3442
3443             /* Store 'before' snapshot of UE state for this frame */
3444             set_drx_info(pinfo, p_mac_lte_info, TRUE, pdu_instance);
3445         }
3446
3447         /* Show current DRX state in tree as 'before' */
3448         show_drx_info(pinfo, tree, tvb, p_mac_lte_info, TRUE, pdu_instance);
3449
3450         /* Changes of state caused by events */
3451         if (!pinfo->fd->flags.visited) {
3452             if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
3453                 if (p_mac_lte_info->reTxCount == 0) {
3454                     mac_lte_drx_new_ulsch_data(p_mac_lte_info->ueid);
3455                 }
3456             }
3457             else {
3458                 /* Downlink */
3459                 if ((p_mac_lte_info->crcStatusValid) && (p_mac_lte_info->crcStatus != crc_success)) {
3460                     mac_lte_drx_dl_crc_error(p_mac_lte_info->ueid);
3461                 }
3462                 else if (p_mac_lte_info->reTxCount == 0) {
3463                     mac_lte_drx_new_dlsch_data(p_mac_lte_info->ueid);
3464                 }
3465             }
3466         }
3467     }
3468
3469
3470     /* For uplink frames, if this is logged as a resend, look for original tx */
3471     if (direction == DIRECTION_UPLINK) {
3472         TrackReportedULHARQResend(pinfo, tvb, offset, tree, p_mac_lte_info, retx_ti);
3473     }
3474
3475     /* For uplink grants, update SR status.  N.B. only newTx grant should stop SR */
3476     if ((direction == DIRECTION_UPLINK) && (p_mac_lte_info->reTxCount == 0) &&
3477         global_mac_lte_track_sr) {
3478
3479         TrackSRInfo(SR_Grant, pinfo, tree, tvb, p_mac_lte_info, 0, NULL);
3480     }
3481
3482     /* Add hidden item to filter on */
3483     hidden_root_ti = proto_tree_add_string_format(tree,
3484                                                  (direction == DIRECTION_UPLINK) ?
3485                                                     hf_mac_lte_ulsch :
3486                                                     hf_mac_lte_dlsch,
3487                                                  tvb, offset, 0,
3488                                                  "",
3489                                                  "Hidden header");
3490     PROTO_ITEM_SET_HIDDEN(hidden_root_ti);
3491
3492     /* Add PDU block header subtree */
3493     pdu_header_ti = proto_tree_add_string_format(tree,
3494                                                  (direction == DIRECTION_UPLINK) ?
3495                                                     hf_mac_lte_ulsch_header :
3496                                                     hf_mac_lte_dlsch_header,
3497                                                  tvb, offset, 0,
3498                                                  "",
3499                                                  "MAC PDU Header");
3500     pdu_header_tree = proto_item_add_subtree(pdu_header_ti,
3501                                              (direction == DIRECTION_UPLINK) ?
3502                                                     ett_mac_lte_ulsch_header :
3503                                                     ett_mac_lte_dlsch_header);
3504
3505
3506     /************************************************************************/
3507     /* Dissect each sub-header.                                             */
3508     do {
3509         guint8 reserved;
3510         guint64 length = 0;
3511         proto_item *pdu_subheader_ti;
3512         proto_tree *pdu_subheader_tree;
3513         proto_item *lcid_ti;
3514         proto_item *ti;
3515         gint       offset_start_subheader = offset;
3516         guint8 first_byte = tvb_get_guint8(tvb, offset);
3517
3518         /* Add PDU block header subtree.
3519            Default with length of 1 byte. */
3520         pdu_subheader_ti = proto_tree_add_string_format(pdu_header_tree,
3521                                                         hf_mac_lte_sch_subheader,
3522                                                         tvb, offset, 1,
3523                                                         "",
3524                                                         "Sub-header");
3525         pdu_subheader_tree = proto_item_add_subtree(pdu_subheader_ti,
3526                                                     ett_mac_lte_sch_subheader);
3527
3528         /* Check 1st 2 reserved bits */
3529         reserved = (first_byte & 0xc0) >> 6;
3530         ti = proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_sch_reserved,
3531                                  tvb, offset, 1, ENC_BIG_ENDIAN);
3532         if (reserved != 0) {
3533             expert_add_info_format(pinfo, ti, &ei_mac_lte_reserved_not_zero,
3534                                    "%cL-SCH header Reserved bits not zero",
3535                                    (p_mac_lte_info->direction == DIRECTION_UPLINK) ? 'U' : 'D');
3536         }
3537
3538         /* Extended bit */
3539         extension = (first_byte & 0x20) >> 5;
3540         proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_sch_extended,
3541                             tvb, offset, 1, ENC_BIG_ENDIAN);
3542
3543         /* LCID.  Has different meaning depending upon direction. */
3544         lcids[number_of_headers] = first_byte & 0x1f;
3545         if (direction == DIRECTION_UPLINK) {
3546
3547             lcid_ti = proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_ulsch_lcid,
3548                                           tvb, offset, 1, ENC_BIG_ENDIAN);
3549             write_pdu_label_and_info(pdu_ti, NULL, pinfo,
3550                                      "(%s",
3551                                      val_to_str_const(lcids[number_of_headers],
3552                                                       ulsch_lcid_vals, "(Unknown LCID)"));
3553         }
3554         else {
3555             /* Downlink */
3556             lcid_ti = proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_dlsch_lcid,
3557                                           tvb, offset, 1, ENC_BIG_ENDIAN);
3558             write_pdu_label_and_info(pdu_ti, NULL, pinfo,
3559                                      "(%s",
3560                                      val_to_str_const(lcids[number_of_headers],
3561                                                       dlsch_lcid_vals, "(Unknown LCID)"));
3562
3563             if (lcids[number_of_headers] == DRX_COMMAND_LCID) {
3564                 expert_add_info_format(pinfo, lcid_ti, &ei_mac_lte_dlsch_lcid,
3565                                        "DRX command received for UE %u (RNTI %u)",
3566                                        p_mac_lte_info->ueid, p_mac_lte_info->rnti);
3567             }
3568         }
3569         offset++;
3570
3571         /* Remember if we've seen a data subheader */
3572         if (lcids[number_of_headers] <= 10) {
3573             have_seen_data_header = TRUE;
3574             expecting_body_data = TRUE;
3575         }
3576
3577         /* Show an expert item if a contol subheader (except Padding) appears
3578            *after* a data PDU */
3579         if (have_seen_data_header &&
3580             (lcids[number_of_headers] > 10) && (lcids[number_of_headers] != PADDING_LCID)) {
3581             expert_add_info_format(pinfo, lcid_ti, &ei_mac_lte_control_subheader_after_data_subheader,
3582                                    "%cL-SCH Control subheaders should not appear after data subheaders",
3583                                    (p_mac_lte_info->direction == DIRECTION_UPLINK) ? 'U' : 'D');
3584             return;
3585         }
3586
3587         /* Show an expert item if we're seeing more then one BSR in a frame */
3588         if ((direction == DIRECTION_UPLINK) && is_bsr_lcid(lcids[number_of_headers])) {
3589             if (have_seen_bsr) {
3590                 expert_add_info(pinfo, lcid_ti, &ei_mac_lte_control_bsr_multiple);
3591                 return;
3592             }
3593             have_seen_bsr = TRUE;
3594         }
3595
3596         /* Should not see padding after non-padding control... */
3597         if ((lcids[number_of_headers] > 10) &&
3598             (lcids[number_of_headers] == PADDING_LCID) &&
3599             extension)
3600         {
3601             number_of_padding_subheaders++;
3602             if (number_of_padding_subheaders > 2) {
3603                 expert_add_info(pinfo, lcid_ti, &ei_mac_lte_padding_data_multiple);
3604             }
3605
3606             if (have_seen_non_padding_control) {
3607                 expert_add_info(pinfo, lcid_ti, &ei_mac_lte_padding_data_before_control_subheader);
3608             }
3609         }
3610
3611         /* Also flag if we have final padding but also padding subheaders
3612            at the start! */
3613         if (!extension && (lcids[number_of_headers] == PADDING_LCID) &&
3614             (number_of_padding_subheaders > 0)) {
3615                 expert_add_info(pinfo, lcid_ti, &ei_mac_lte_padding_data_start_and_end);
3616         }
3617
3618         /* Remember that we've seen non-padding control */
3619         if ((lcids[number_of_headers] > 10) &&
3620             (lcids[number_of_headers] != PADDING_LCID)) {
3621             have_seen_non_padding_control = TRUE;
3622         }
3623
3624
3625
3626         /********************************************************************/
3627         /* Length field follows if not the last header or for a fixed-sized
3628            control element */
3629         if (!extension) {
3630             /* Last one... */
3631             if (is_fixed_sized_control_element(lcids[number_of_headers], direction)) {
3632                 pdu_lengths[number_of_headers] = 0;
3633             }
3634             else {
3635                 pdu_lengths[number_of_headers] = -1;
3636             }
3637         }
3638         else {
3639             /* Not the last one */
3640             if (!is_fixed_sized_control_element(lcids[number_of_headers], direction) &&
3641                 (lcids[number_of_headers] != PADDING_LCID)) {
3642
3643                 guint8  format;
3644
3645                 /* F(ormat) bit tells us how long the length field is */
3646                 format = (tvb_get_guint8(tvb, offset) & 0x80) >> 7;
3647                 proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_sch_format,
3648                                     tvb, offset, 1, ENC_BIG_ENDIAN);
3649
3650                 /* Now read length field itself */
3651                 if (format) {
3652                     /* >= 128 - use 15 bits */
3653                     proto_tree_add_bits_ret_val(pdu_subheader_tree, hf_mac_lte_sch_length,
3654                                                 tvb, offset*8 + 1, 15, &length, ENC_BIG_ENDIAN);
3655
3656                     offset += 2;
3657                 }
3658                 else {
3659                     /* Less than 128 - only 7 bits */
3660                     proto_tree_add_bits_ret_val(pdu_subheader_tree, hf_mac_lte_sch_length,
3661                                                 tvb, offset*8 + 1, 7, &length, ENC_BIG_ENDIAN);
3662                     offset++;
3663                 }
3664                 pdu_lengths[number_of_headers] = (gint16)length;
3665             }
3666             else {
3667                 pdu_lengths[number_of_headers] = 0;
3668             }
3669         }
3670
3671
3672         /* Close off description in info column */
3673         switch (pdu_lengths[number_of_headers]) {
3674             case 0:
3675                 write_pdu_label_and_info_literal(pdu_ti, NULL, pinfo, ") ");
3676                 break;
3677             case -1:
3678                 write_pdu_label_and_info_literal(pdu_ti, NULL, pinfo, ":remainder) ");
3679                 break;
3680             default:
3681                 write_pdu_label_and_info(pdu_ti, NULL, pinfo, ":%u bytes) ",
3682                                          pdu_lengths[number_of_headers]);
3683                 break;
3684         }
3685
3686         /* Append summary to subheader root */
3687         proto_item_append_text(pdu_subheader_ti, " (lcid=%s",
3688                                val_to_str_const(lcids[number_of_headers],
3689                                                 (direction == DIRECTION_UPLINK) ?
3690                                                     ulsch_lcid_vals :
3691                                                         dlsch_lcid_vals,
3692                                                 "Unknown"));
3693
3694         switch (pdu_lengths[number_of_headers]) {
3695             case -1:
3696                 proto_item_append_text(pdu_subheader_ti, ", length is remainder)");
3697                 proto_item_append_text(pdu_header_ti, " (%s:remainder)",
3698                                        val_to_str_const(lcids[number_of_headers],
3699                                                         (direction == DIRECTION_UPLINK) ? ulsch_lcid_vals : dlsch_lcid_vals,
3700                                                         "Unknown"));
3701                 break;
3702             case 0:
3703                 proto_item_append_text(pdu_subheader_ti, ")");
3704                 proto_item_append_text(pdu_header_ti, " (%s)",
3705                                        val_to_str_const(lcids[number_of_headers],
3706                                                         (direction == DIRECTION_UPLINK) ? ulsch_lcid_vals : dlsch_lcid_vals,
3707                                                         "Unknown"));
3708                 break;
3709             default:
3710                 proto_item_append_text(pdu_subheader_ti, ", length=%u)",
3711                                        pdu_lengths[number_of_headers]);
3712                 proto_item_append_text(pdu_header_ti, " (%s:%u)",
3713                                        val_to_str_const(lcids[number_of_headers],
3714                                                         (direction == DIRECTION_UPLINK) ? ulsch_lcid_vals : dlsch_lcid_vals,
3715                                                         "Unknown"),
3716                                        pdu_lengths[number_of_headers]);
3717                 break;
3718         }
3719
3720
3721         /* Flag unknown lcid values in expert info */
3722         if (try_val_to_str(lcids[number_of_headers],
3723                          (direction == DIRECTION_UPLINK) ? ulsch_lcid_vals : dlsch_lcid_vals) == NULL) {
3724             expert_add_info_format(pinfo, pdu_subheader_ti, &ei_mac_lte_lcid_unexpected,
3725                                    "%cL-SCH: Unexpected LCID received (%u)",
3726                                    (p_mac_lte_info->direction == DIRECTION_UPLINK) ? 'U' : 'D',
3727                                    lcids[number_of_headers]);
3728         }
3729
3730         /* Set length of this subheader */
3731         proto_item_set_len(pdu_subheader_ti, offset - offset_start_subheader);
3732
3733         number_of_headers++;
3734     } while ((number_of_headers < MAX_HEADERS_IN_PDU) && extension);
3735
3736     /* Check that we didn't reach the end of the subheader array... */
3737     if (number_of_headers >= MAX_HEADERS_IN_PDU) {
3738         proto_tree_add_expert_format(tree, pinfo, &ei_mac_lte_too_many_subheaders, tvb, offset, 1,
3739                                              "Reached %u subheaders - frame obviously malformed",
3740                                              MAX_HEADERS_IN_PDU);
3741         return;
3742     }
3743
3744
3745     /* Append summary to overall PDU header root */
3746     proto_item_append_text(pdu_header_ti, "  [%u subheaders]",
3747                            number_of_headers);
3748
3749     /* And set its length to offset */
3750     proto_item_set_len(pdu_header_ti, offset);
3751
3752
3753     /* For DL, see if this is a retx.  Use whole PDU present (i.e. ignore padding if not logged) */
3754     if (direction == DIRECTION_DOWNLINK) {
3755         /* Result will be added to context tree */
3756         TrackReportedDLHARQResend(pinfo, tvb, tvb_length_remaining(tvb, 0), context_tree, p_mac_lte_info);
3757
3758         tap_info->isPHYRetx = (p_mac_lte_info->dl_retx == dl_retx_yes);
3759     }
3760
3761
3762     /************************************************************************/
3763     /* Dissect SDUs / control elements / padding.                           */
3764     /************************************************************************/
3765
3766     /* Dissect control element bodies first */
3767
3768     for (n=0; n < number_of_headers; n++) {
3769         /* Get out of loop once see any data SDU subheaders */
3770         if (lcids[n] <= 10) {
3771             /* Update tap sdu count for this channel */
3772             tap_info->sdus_for_lcid[lcids[n]]++;
3773             break;
3774         }
3775
3776         /* Process what should be a valid control PDU type */
3777         if (direction == DIRECTION_DOWNLINK) {
3778
3779             /****************************/
3780             /* DL-SCH Control PDUs      */
3781             switch (lcids[n]) {
3782                 case ACTIVATION_DEACTIVATION_LCID:
3783                     {
3784                         proto_item *ad_ti;
3785                         proto_tree *ad_tree;
3786                         proto_item *ti;
3787                         guint8 reserved;
3788
3789                         /* Create AD root */
3790                         ad_ti = proto_tree_add_string_format(tree,
3791                                                              hf_mac_lte_control_activation_deactivation,
3792                                                              tvb, offset, 1,
3793                                                              "",
3794                                                              "Activation/Deactivation");
3795                         ad_tree = proto_item_add_subtree(ad_ti, ett_mac_lte_activation_deactivation);
3796
3797                         proto_tree_add_item(ad_tree, hf_mac_lte_control_activation_deactivation_c7,
3798                                             tvb, offset, 1, ENC_BIG_ENDIAN);
3799                         proto_tree_add_item(ad_tree, hf_mac_lte_control_activation_deactivation_c6,
3800                                             tvb, offset, 1, ENC_BIG_ENDIAN);
3801                         proto_tree_add_item(ad_tree, hf_mac_lte_control_activation_deactivation_c5,
3802                                             tvb, offset, 1, ENC_BIG_ENDIAN);
3803                         proto_tree_add_item(ad_tree, hf_mac_lte_control_activation_deactivation_c4,
3804                                             tvb, offset, 1, ENC_BIG_ENDIAN);
3805                         proto_tree_add_item(ad_tree, hf_mac_lte_control_activation_deactivation_c3,
3806                                             tvb, offset, 1, ENC_BIG_ENDIAN);
3807                         proto_tree_add_item(ad_tree, hf_mac_lte_control_activation_deactivation_c2,
3808                                             tvb, offset, 1, ENC_BIG_ENDIAN);
3809                         proto_tree_add_item(ad_tree, hf_mac_lte_control_activation_deactivation_c1,
3810                                             tvb, offset, 1, ENC_BIG_ENDIAN);
3811                         ti = proto_tree_add_item(ad_tree, hf_mac_lte_control_activation_deactivation_reserved,
3812                                                  tvb, offset, 1, ENC_BIG_ENDIAN);
3813                         reserved = tvb_get_guint8(tvb, offset) & 0x01;
3814                         if (reserved != 0) {
3815                             expert_add_info_format(pinfo, ti, &ei_mac_lte_reserved_not_zero,
3816                                                    "Activation/Deactivation Reserved bit not zero");
3817                         }
3818                         offset++;
3819                     }
3820                     break;
3821                 case UE_CONTENTION_RESOLUTION_IDENTITY_LCID:
3822                     {
3823                         proto_item *cr_ti;
3824                         proto_tree *cr_tree;
3825                         proto_item *ti;
3826                         ContentionResolutionResult *crResult;
3827
3828                         /* Create CR root */
3829                         cr_ti = proto_tree_add_string_format(tree,
3830                                                              hf_mac_lte_control_ue_contention_resolution,
3831                                                              tvb, offset, 6,
3832                                                              "",
3833                                                              "Contention Resolution");
3834                         cr_tree = proto_item_add_subtree(cr_ti, ett_mac_lte_contention_resolution);
3835
3836                         /* Contention resolution body */
3837                         proto_tree_add_item(cr_tree, hf_mac_lte_control_ue_contention_resolution_identity,
3838                                             tvb, offset, 6, ENC_NA);
3839                         if (global_mac_lte_decode_cr_body) {
3840                             tvbuff_t *cr_body_tvb = tvb_new_subset(tvb, offset, 6, 6);
3841                             dissector_handle_t ul_ccch_handle = find_dissector("lte_rrc.ul_ccch");
3842                             if (ul_ccch_handle != 0) {
3843                                 call_with_catch_all(ul_ccch_handle, cr_body_tvb, pinfo, cr_tree);
3844                             }
3845                         }
3846
3847                         /* Get pointer to result struct for this frame */
3848                         crResult =  (ContentionResolutionResult *)g_hash_table_lookup(mac_lte_cr_result_hash, GUINT_TO_POINTER(pinfo->fd->num));
3849                         if (crResult == NULL) {
3850
3851                             /* Need to set result by looking for and comparing with Msg3 */
3852                             Msg3Data *msg3Data;
3853                             guint msg3Key = p_mac_lte_info->rnti;
3854
3855                             /* Allocate result and add it to the table */
3856                             crResult = wmem_new(wmem_file_scope(), ContentionResolutionResult);
3857                             g_hash_table_insert(mac_lte_cr_result_hash, GUINT_TO_POINTER(pinfo->fd->num), crResult);
3858
3859                             /* Look for Msg3 */
3860                             msg3Data = (Msg3Data *)g_hash_table_lookup(mac_lte_msg3_hash, GUINT_TO_POINTER(msg3Key));
3861
3862                             /* Compare CCCH bytes */
3863                             if (msg3Data != NULL) {
3864                                 crResult->msSinceMsg3 = (guint32)(((pinfo->fd->abs_ts.secs - msg3Data->msg3Time.secs) * 1000) +
3865                                                                   ((pinfo->fd->abs_ts.nsecs - msg3Data->msg3Time.nsecs) / 1000000));
3866                                 crResult->msg3FrameNum = msg3Data->framenum;
3867
3868                                 /* Compare the 6 bytes */
3869                                 if (tvb_memeql(tvb, offset, msg3Data->data, 6) == 0) {
3870                                     crResult->status = Msg3Match;
3871                                 }
3872                                 else {
3873                                     crResult->status = Msg3NoMatch;
3874                                 }
3875                             }
3876                             else {
3877                                 crResult->status = NoMsg3;
3878                             }
3879                         }
3880
3881                         /* Now show CR result in tree */
3882                         switch (crResult->status) {
3883                             case NoMsg3:
3884                                 proto_item_append_text(cr_ti, " (no corresponding Msg3 found!)");
3885                                 break;
3886
3887                             case Msg3Match:
3888                                 ti = proto_tree_add_uint(cr_tree, hf_mac_lte_control_ue_contention_resolution_msg3,
3889                                                          tvb, 0, 0, crResult->msg3FrameNum);
3890                                 PROTO_ITEM_SET_GENERATED(ti);
3891                                 ti = proto_tree_add_uint(cr_tree, hf_mac_lte_control_ue_contention_resolution_time_since_msg3,
3892                                                          tvb, 0, 0, crResult->msSinceMsg3);
3893                                 PROTO_ITEM_SET_GENERATED(ti);
3894
3895                                 ti = proto_tree_add_boolean(cr_tree, hf_mac_lte_control_ue_contention_resolution_msg3_matched,
3896                                                             tvb, 0, 0, TRUE);
3897                                 PROTO_ITEM_SET_GENERATED(ti);
3898                                 proto_item_append_text(cr_ti, " (matches Msg3 from frame %u, %ums ago)",
3899                                                        crResult->msg3FrameNum, crResult->msSinceMsg3);
3900                                 break;
3901
3902                             case Msg3NoMatch:
3903                                 ti = proto_tree_add_uint(cr_tree, hf_mac_lte_control_ue_contention_resolution_msg3,
3904                                                          tvb, 0, 0, crResult->msg3FrameNum);
3905                                 PROTO_ITEM_SET_GENERATED(ti);
3906                                 ti = proto_tree_add_uint(cr_tree, hf_mac_lte_control_ue_contention_resolution_time_since_msg3,
3907                                                          tvb, 0, 0, crResult->msSinceMsg3);
3908                                 PROTO_ITEM_SET_GENERATED(ti);
3909
3910                                 ti = proto_tree_add_boolean(cr_tree, hf_mac_lte_control_ue_contention_resolution_msg3_matched,
3911                                                              tvb, 0, 0, FALSE);
3912                                 expert_add_info_format(pinfo, ti, &ei_mac_lte_control_ue_contention_resolution_msg3_matched,
3913                                                        "CR body in Msg4 doesn't match Msg3 CCCH in frame %u",
3914                                                        crResult->msg3FrameNum);
3915                                 PROTO_ITEM_SET_GENERATED(ti);
3916                                 proto_item_append_text(cr_ti, " (doesn't match Msg3 from frame %u, %u ago)",
3917                                                        crResult->msg3FrameNum, crResult->msSinceMsg3);
3918                                 break;
3919                         };
3920
3921                         offset += 6;
3922                     }
3923                     break;
3924                 case TIMING_ADVANCE_LCID:
3925                     {
3926                         proto_item *ta_ti;
3927                         proto_item *ta_value_ti;
3928                         proto_tree *ta_tree;
3929                         guint8      ta_value;
3930
3931                         /* Create TA root */
3932                         ta_ti = proto_tree_add_string_format(tree,
3933                                                              hf_mac_lte_control_timing_advance,
3934                                                              tvb, offset, 1,
3935                                                              "",
3936                                                              "Timing Advance");
3937                         ta_tree = proto_item_add_subtree(ta_ti, ett_mac_lte_timing_advance);
3938
3939                         /* TAG Id */
3940                         proto_tree_add_item(ta_tree, hf_mac_lte_control_timing_advance_group_id,
3941                                             tvb, offset, 1, ENC_BIG_ENDIAN);
3942
3943                         /* TA value */
3944                         ta_value = tvb_get_guint8(tvb, offset) & 0x3f;
3945                         ta_value_ti = proto_tree_add_item(ta_tree, hf_mac_lte_control_timing_advance_command,
3946                                                            tvb, offset, 1, ENC_BIG_ENDIAN);
3947
3948                         if (ta_value == 31) {
3949                             expert_add_info(pinfo, ta_value_ti, &ei_mac_lte_control_timing_advance_command_no_correction);
3950                         }
3951                         else {
3952                             expert_add_info_format(pinfo, ta_value_ti, &ei_mac_lte_control_timing_advance_command_correction_needed,
3953                                                    "Timing Advance control element received (%u) %s correction needed",
3954                                                    ta_value,
3955                                                    (ta_value < 31) ? "-ve" : "+ve");
3956                         }
3957                         offset++;
3958                     }
3959                     break;
3960                 case DRX_COMMAND_LCID:
3961                     /* No payload */
3962                     mac_lte_drx_control_element_received(p_mac_lte_info->ueid);
3963                     break;
3964                 case PADDING_LCID:
3965                     /* No payload (in this position) */
3966                     tap_info->padding_bytes++;
3967                     break;
3968
3969                 default:
3970                     break;
3971             }
3972         }
3973         else {
3974
3975             /**********************************/
3976             /* UL-SCH Control PDUs            */
3977             switch (lcids[n]) {
3978                 case EXTENDED_POWER_HEADROOM_REPORT_LCID:
3979                     {
3980                         proto_item *ephr_ti;
3981                         proto_tree *ephr_tree;
3982                         proto_item *ti;
3983                         proto_tree *ephr_cell_tree;
3984                         proto_item *ephr_cell_ti;
3985                         guint8 scell_bitmap;
3986                         guint8 scell_count;
3987                         guint8 byte;
3988                         guint i;
3989                         guint32 curr_offset = offset;
3990                         guint32 computed_header_offset;
3991
3992                         if (pdu_lengths[n] == -1) {
3993                             /* Control Element size is the remaining PDU */
3994                             pdu_lengths[n] = (gint16)tvb_length_remaining(tvb, curr_offset);
3995                         }
3996
3997                         /* Create EPHR root */
3998                         ephr_ti = proto_tree_add_string_format(tree,
3999                                                                hf_mac_lte_control_ext_power_headroom,
4000                                                                tvb, curr_offset, pdu_lengths[n],
4001                                                                "",
4002                                                                "Extended Power Headroom");
4003                         ephr_tree = proto_item_add_subtree(ephr_ti, ett_mac_lte_extended_power_headroom);
4004
4005                         scell_bitmap = tvb_get_guint8(tvb, curr_offset);
4006                         proto_tree_add_item(ephr_tree, hf_mac_lte_control_ext_power_headroom_c7,
4007                                             tvb, curr_offset, 1, ENC_BIG_ENDIAN);
4008                         proto_tree_add_item(ephr_tree, hf_mac_lte_control_ext_power_headroom_c6,
4009                                             tvb, curr_offset, 1, ENC_BIG_ENDIAN);
4010                         proto_tree_add_item(ephr_tree, hf_mac_lte_control_ext_power_headroom_c5,
4011                                             tvb, curr_offset, 1, ENC_BIG_ENDIAN);
4012                         proto_tree_add_item(ephr_tree, hf_mac_lte_control_ext_power_headroom_c4,
4013                                             tvb, curr_offset, 1, ENC_BIG_ENDIAN);
4014                         proto_tree_add_item(ephr_tree, hf_mac_lte_control_ext_power_headroom_c3,
4015                                             tvb, curr_offset, 1, ENC_BIG_ENDIAN);
4016                         proto_tree_add_item(ephr_tree, hf_mac_lte_control_ext_power_headroom_c2,
4017                                             tvb, curr_offset, 1, ENC_BIG_ENDIAN);
4018                         proto_tree_add_item(ephr_tree, hf_mac_lte_control_ext_power_headroom_c1,
4019                                             tvb, curr_offset, 1, ENC_BIG_ENDIAN);
4020                         /* Check Reserved bit */
4021                         ti = proto_tree_add_item(ephr_tree, hf_mac_lte_control_ext_power_headroom_reserved,
4022                                                  tvb, curr_offset, 1, ENC_BIG_ENDIAN);
4023                         if (scell_bitmap & 0x01) {
4024                             expert_add_info_format(pinfo, ti, &ei_mac_lte_reserved_not_zero,
4025                                                    "Extended Power Headroom Reserved bit not zero");
4026                         }
4027                         curr_offset++;
4028
4029                         /* Compute expected header size to deduce if PH Type 2 report is present or not */
4030                         /* First count the number of SCells */
4031                         for (i = 0, scell_count = 0; i < 7; i++) {
4032                             if (scell_bitmap & (0x80>>i)) {
4033                                 scell_count++;
4034                             }
4035                         }
4036                         /* Now quickly parse the header */
4037                         computed_header_offset = curr_offset;
4038                         for (i = 0; i < scell_count; i++) {
4039                             if (tvb_get_guint8(tvb, computed_header_offset) & 0x80) {
4040                                 computed_header_offset++;
4041                             }
4042                             computed_header_offset++;
4043                         }
4044
4045                         if ((gint16)(computed_header_offset + 1 - curr_offset) != pdu_lengths[n]) {
4046                             /* PH Type 2 is present */
4047                             if (tvb_get_guint8(tvb, computed_header_offset) & 0x80) {
4048                                 computed_header_offset++;
4049                             }
4050                             computed_header_offset++;
4051                             if ((gint16)(computed_header_offset + 1 - curr_offset) != pdu_lengths[n]) {
4052                                 expert_add_info_format(pinfo, ephr_ti, &ei_mac_lte_control_element_size_invalid,
4053                                     "Control Element has an unexpected size (computed=%d, actual=%d)",
4054                                     computed_header_offset + 1 - curr_offset, pdu_lengths[n]);
4055                                 offset += pdu_lengths[n];
4056                                 break;
4057                             }
4058                             byte = tvb_get_guint8(tvb, curr_offset);
4059                             ephr_cell_ti = proto_tree_add_text(ephr_tree, tvb, curr_offset, ((byte&0x80)?2:1), "PCell");
4060                             ephr_cell_tree = proto_item_add_subtree(ephr_cell_ti, ett_mac_lte_extended_power_headroom_cell);
4061                             proto_tree_add_item(ephr_cell_tree, hf_mac_lte_control_ext_power_headroom_power_backoff,
4062                                                 tvb, curr_offset, 1, ENC_BIG_ENDIAN);
4063                             proto_tree_add_item(ephr_cell_tree, hf_mac_lte_control_ext_power_headroom_value,
4064                                                 tvb, curr_offset, 1, ENC_BIG_ENDIAN);
4065                             proto_tree_add_item(ephr_cell_tree, hf_mac_lte_control_ext_power_headroom_level,
4066                                                 tvb, curr_offset, 1, ENC_BIG_ENDIAN);
4067                             proto_item_append_text(ephr_cell_ti, " (%s)",
4068                                                    val_to_str_ext_const((byte&0x3f), &power_headroom_vals_ext, "Unknown"));
4069                             curr_offset++;
4070                             if (byte & 0x80) {
4071                                 /* Pcmax,c field is present */
4072                                 byte = tvb_get_guint8(tvb, curr_offset);
4073                                 /* Check 2 Reserved bits */
4074                                 ti = proto_tree_add_item(ephr_cell_tree, hf_mac_lte_control_ext_power_headroom_reserved2,
4075                                                          tvb, curr_offset, 1, ENC_BIG_ENDIAN);
4076                                 if (byte & 0xc0) {
4077                                     expert_add_info_format(pinfo, ti, &ei_mac_lte_reserved_not_zero,
4078                                                            "Extended Power Headroom Reserved bits not zero (found 0x%x)",
4079                                                            (byte & 0xc0) >> 6);
4080                                 }
4081                                 proto_tree_add_item(ephr_cell_tree, hf_mac_lte_control_ext_power_headroom_pcmaxc,
4082                                                     tvb, curr_offset, 1, ENC_BIG_ENDIAN);
4083                                 proto_item_append_text(ephr_cell_ti, " (%s)",
4084                                                        val_to_str_ext_const((byte&0x3f), &pcmaxc_vals_ext, "Unknown"));
4085                                 curr_offset++;
4086                             }
4087                         } else {
4088                             if ((gint16)(computed_header_offset + 1 - curr_offset) != pdu_lengths[n]) {
4089                                 expert_add_info_format(pinfo, ephr_ti, &ei_mac_lte_control_element_size_invalid,
4090                                     "Control Element has an unexpected size (computed=%d, actual=%d)",
4091                                     computed_header_offset + 1 - curr_offset, pdu_lengths[n]);
4092                                 offset += pdu_lengths[n];
4093                                 break;
4094                             }
4095                         }
4096                         for (i = 1, scell_bitmap>>=1; i <= 7; i++, scell_bitmap>>=1) {
4097                             if (scell_bitmap & 0x01) {
4098                                 byte = tvb_get_guint8(tvb, curr_offset);
4099                                 ephr_cell_ti = proto_tree_add_text(ephr_tree, tvb, curr_offset, ((byte&0x80)?2:1), "SCell Index %u", i);
4100                                 ephr_cell_tree = proto_item_add_subtree(ephr_cell_ti, ett_mac_lte_extended_power_headroom_cell);
4101                                 proto_tree_add_item(ephr_cell_tree, hf_mac_lte_control_ext_power_headroom_power_backoff,
4102                                                     tvb, curr_offset, 1, ENC_BIG_ENDIAN);
4103                                 proto_tree_add_item(ephr_cell_tree, hf_mac_lte_control_ext_power_headroom_value,
4104                                                     tvb, curr_offset, 1, ENC_BIG_ENDIAN);
4105                                 proto_tree_add_item(ephr_cell_tree, hf_mac_lte_control_ext_power_headroom_level,
4106                                                     tvb, curr_offset, 1, ENC_BIG_ENDIAN);
4107                                 proto_item_append_text(ephr_cell_ti, " (%s)",
4108                                                        val_to_str_ext_const((byte&0x3f), &power_headroom_vals_ext, "Unknown"));
4109                                 curr_offset++;
4110                                 if (byte & 0x80) {
4111                                     /* Pcmax,c field is present */
4112                                     byte = tvb_get_guint8(tvb, curr_offset);
4113                                     /* Check 2 Reserved bits */
4114                                     ti = proto_tree_add_item(ephr_cell_tree, hf_mac_lte_control_ext_power_headroom_reserved2,
4115                                                              tvb, curr_offset, 1, ENC_BIG_ENDIAN);
4116                                     if (byte & 0xc0) {
4117                                         expert_add_info_format(pinfo, ti, &ei_mac_lte_reserved_not_zero,
4118                                                                "Extended Power Headroom Reserved bits not zero (found 0x%x)",
4119                                                                (byte & 0xc0) >> 6);
4120                                     }
4121                                     proto_tree_add_item(ephr_cell_tree, hf_mac_lte_control_ext_power_headroom_pcmaxc,
4122                                                         tvb, curr_offset, 1, ENC_BIG_ENDIAN);
4123                                     proto_item_append_text(ephr_cell_ti, " (%s)",
4124                                                            val_to_str_ext_const((byte&0x3f), &pcmaxc_vals_ext, "Unknown"));
4125                                     curr_offset++;
4126                                 }
4127                             }
4128                         }
4129                         offset += pdu_lengths[n];
4130                     }
4131                     break;
4132                 case POWER_HEADROOM_REPORT_LCID:
4133                     {
4134                         proto_item *phr_ti;
4135                         proto_tree *phr_tree;
4136                         proto_item *ti;
4137                         guint8 reserved;
4138                         guint8 level;
4139
4140                         /* Create PHR root */
4141                         phr_ti = proto_tree_add_string_format(tree,
4142                                                               hf_mac_lte_control_power_headroom,
4143                                                               tvb, offset, 1,
4144                                                               "",
4145                                                               "Power Headroom");
4146                         phr_tree = proto_item_add_subtree(phr_ti, ett_mac_lte_power_headroom);
4147
4148                         /* Check 2 Reserved bits */
4149                         reserved = (tvb_get_guint8(tvb, offset) & 0xc0) >> 6;
4150                         ti = proto_tree_add_item(phr_tree, hf_mac_lte_control_power_headroom_reserved,
4151                                                  tvb, offset, 1, ENC_BIG_ENDIAN);
4152                         if (reserved != 0) {
4153                             expert_add_info_format(pinfo, ti, &ei_mac_lte_reserved_not_zero,
4154                                                    "Power Headroom Reserved bits not zero (found 0x%x)", reserved);
4155                         }
4156
4157                         /* Level */
4158                         level = tvb_get_guint8(tvb, offset) & 0x3f;
4159                         proto_tree_add_item(phr_tree, hf_mac_lte_control_power_headroom_level,
4160                                             tvb, offset, 1, ENC_BIG_ENDIAN);
4161
4162                         /* Show value in root label */
4163                         proto_item_append_text(phr_ti, " (%s)",
4164                                                val_to_str_ext_const(level, &power_headroom_vals_ext, "Unknown"));
4165                         offset++;
4166                     }
4167
4168
4169                     break;
4170                 case CRNTI_LCID:
4171                     proto_tree_add_item(tree, hf_mac_lte_control_crnti,
4172                                         tvb, offset, 2, ENC_BIG_ENDIAN);
4173                     offset += 2;
4174                     break;
4175                 case TRUNCATED_BSR_LCID:
4176                 case SHORT_BSR_LCID:
4177                     {
4178                         proto_tree *bsr_tree;
4179                         proto_item *bsr_ti;
4180                         proto_item *buffer_size_ti;
4181                         guint8 lcgid;
4182                         guint8 buffer_size;
4183                         int hfindex;
4184                         value_string_ext *p_vs_ext;
4185
4186                         if (p_mac_lte_info->isExtendedBSRSizes) {
4187                             hfindex = hf_mac_lte_control_short_ext_bsr_buffer_size;
4188                             p_vs_ext = &ext_buffer_size_vals_ext;
4189                         } else {
4190                             hfindex = hf_mac_lte_control_short_bsr_buffer_size;
4191                             p_vs_ext = &buffer_size_vals_ext;
4192                         }
4193
4194                         bsr_ti = proto_tree_add_string_format(tree,
4195                                                               hf_mac_lte_control_bsr,
4196                                                               tvb, offset, 1,
4197                                                               "",
4198                                                               "Short BSR");
4199                         bsr_tree = proto_item_add_subtree(bsr_ti, ett_mac_lte_bsr);
4200
4201                         /* LCG ID */
4202                         lcgid = (tvb_get_guint8(tvb, offset) & 0xc0) >> 6;
4203                         proto_tree_add_item(bsr_tree, hf_mac_lte_control_bsr_lcg_id,
4204                                                     tvb, offset, 1, ENC_BIG_ENDIAN);
4205                         /* Buffer Size */
4206                         buffer_size = tvb_get_guint8(tvb, offset) & 0x3f;
4207                         buffer_size_ti = proto_tree_add_item(bsr_tree, hfindex,
4208                                                              tvb, offset, 1, ENC_BIG_ENDIAN);
4209                         offset++;
4210                         if (buffer_size >= global_mac_lte_bsr_warn_threshold) {
4211                             expert_add_info_format(pinfo, buffer_size_ti, &ei_mac_lte_bsr_warn_threshold_exceeded,
4212                                                    "UE %u - BSR for LCG %u exceeds threshold: %u (%s)",
4213                                                    p_mac_lte_info->ueid,
4214                                                    lcgid,
4215                                                    buffer_size,
4216                                                    val_to_str_ext_const(buffer_size, p_vs_ext, "Unknown"));
4217                         }
4218
4219
4220                         proto_item_append_text(bsr_ti, " (lcgid=%u  %s)",
4221                                                lcgid,
4222                                                val_to_str_ext_const(buffer_size, &buffer_size_vals_ext, "Unknown"));
4223                     }
4224                     break;
4225                 case LONG_BSR_LCID:
4226                     {
4227                         proto_tree *bsr_tree;
4228                         proto_item *bsr_ti;
4229                         proto_item *buffer_size_ti;
4230                         guint8     buffer_size[4];
4231                         int hfindex[4];
4232                         value_string_ext *p_vs_ext;
4233
4234                         if (p_mac_lte_info->isExtendedBSRSizes) {
4235                             hfindex[0] = hf_mac_lte_control_long_ext_bsr_buffer_size_0;
4236                             hfindex[1] = hf_mac_lte_control_long_ext_bsr_buffer_size_1;
4237                             hfindex[2] = hf_mac_lte_control_long_ext_bsr_buffer_size_2;
4238                             hfindex[3] = hf_mac_lte_control_long_ext_bsr_buffer_size_3;
4239                             p_vs_ext = &ext_buffer_size_vals_ext;
4240                         } else {
4241                             hfindex[0] = hf_mac_lte_control_long_bsr_buffer_size_0;
4242                             hfindex[1] = hf_mac_lte_control_long_bsr_buffer_size_1;
4243                             hfindex[2] = hf_mac_lte_control_long_bsr_buffer_size_2;
4244                             hfindex[3] = hf_mac_lte_control_long_bsr_buffer_size_3;
4245                             p_vs_ext = &buffer_size_vals_ext;
4246                         }
4247
4248                         bsr_ti = proto_tree_add_string_format(tree,
4249                                                               hf_mac_lte_control_bsr,
4250                                                               tvb, offset, 3,
4251                                                               "",
4252                                                               "Long BSR");
4253                         bsr_tree = proto_item_add_subtree(bsr_ti, ett_mac_lte_bsr);
4254
4255                         /* LCID Group 0 */
4256                         buffer_size_ti = proto_tree_add_item(bsr_tree, hfindex[0],
4257                                                              tvb, offset, 1, ENC_BIG_ENDIAN);
4258                         buffer_size[0] = (tvb_get_guint8(tvb, offset) & 0xfc) >> 2;
4259                         if (buffer_size[0] >= global_mac_lte_bsr_warn_threshold) {
4260                             expert_add_info_format(pinfo, buffer_size_ti, &ei_mac_lte_bsr_warn_threshold_exceeded,
4261                                                    "UE %u - BSR for LCG 0 exceeds threshold: %u (%s)",
4262                                                    p_mac_lte_info->ueid,
4263                                                    buffer_size[0],
4264                                                    val_to_str_ext_const(buffer_size[0], p_vs_ext, "Unknown"));
4265                         }
4266
4267                         /* LCID Group 1 */
4268                         buffer_size_ti = proto_tree_add_item(bsr_tree, hfindex[1],
4269                                                              tvb, offset, 2, ENC_BIG_ENDIAN);
4270                         buffer_size[1] = ((tvb_get_guint8(tvb, offset) & 0x03) << 4) | ((tvb_get_guint8(tvb, offset+1) & 0xf0) >> 4);
4271                         offset++;
4272                         if (buffer_size[1] >= global_mac_lte_bsr_warn_threshold) {
4273                             expert_add_info_format(pinfo, buffer_size_ti, &ei_mac_lte_bsr_warn_threshold_exceeded,
4274                                                    "UE %u - BSR for LCG 1 exceeds threshold: %u (%s)",
4275                                                    p_mac_lte_info->ueid,
4276                                                    buffer_size[1],
4277                                                    val_to_str_ext_const(buffer_size[1], p_vs_ext, "Unknown"));
4278                         }
4279
4280                         /* LCID Group 2 */
4281                         buffer_size_ti = proto_tree_add_item(bsr_tree, hfindex[2],
4282                                                              tvb, offset, 2, ENC_BIG_ENDIAN);
4283
4284                         buffer_size[2] = ((tvb_get_guint8(tvb, offset) & 0x0f) << 2) | ((tvb_get_guint8(tvb, offset+1) & 0xc0) >> 6);
4285                         offset++;
4286                         if (buffer_size[2] >= global_mac_lte_bsr_warn_threshold) {
4287                             expert_add_info_format(pinfo, buffer_size_ti, &ei_mac_lte_bsr_warn_threshold_exceeded,
4288                                                    "UE %u - BSR for LCG 2 exceeds threshold: %u (%s)",
4289                                                    p_mac_lte_info->ueid,
4290                                                    buffer_size[2],
4291                                                    val_to_str_ext_const(buffer_size[2], p_vs_ext, "Unknown"));
4292                         }
4293
4294                         /* LCID Group 3 */
4295                         buffer_size_ti = proto_tree_add_item(bsr_tree, hfindex[3],
4296                                                              tvb, offset, 1, ENC_BIG_ENDIAN);
4297                         buffer_size[3] = tvb_get_guint8(tvb, offset) & 0x3f;
4298                         offset++;
4299                         if (buffer_size[3] >= global_mac_lte_bsr_warn_threshold) {
4300                             expert_add_info_format(pinfo, buffer_size_ti, &ei_mac_lte_bsr_warn_threshold_exceeded,
4301                                                    "UE %u - BSR for LCG 3 exceeds threshold: %u (%s)",
4302                                                    p_mac_lte_info->ueid,
4303                                                    buffer_size[3],
4304                                                    val_to_str_ext_const(buffer_size[3], p_vs_ext, "Unknown"));
4305                         }
4306
4307                         /* Append summary to parent */
4308                         proto_item_append_text(bsr_ti, "   0:(%s)  1:(%s)  2:(%s)  3:(%s)",
4309                                                val_to_str_ext_const(buffer_size[0], p_vs_ext, "Unknown"),
4310                                                val_to_str_ext_const(buffer_size[1], p_vs_ext, "Unknown"),
4311                                                val_to_str_ext_const(buffer_size[2], p_vs_ext, "Unknown"),
4312                                                val_to_str_ext_const(buffer_size[3], p_vs_ext, "Unknown"));
4313                     }
4314                     break;
4315                 case PADDING_LCID:
4316                     /* No payload, in this position */
4317                     tap_info->padding_bytes++;
4318                     break;
4319
4320                 default:
4321                     break;
4322             }
4323         }
4324     }
4325
4326     /* There might not be any data, if only headers (plus control data) were logged */
4327     is_truncated = ((tvb_length_remaining(tvb, offset) == 0) && expecting_body_data);
4328     truncated_ti = proto_tree_add_uint(tree, hf_mac_lte_sch_header_only, tvb, 0, 0,
4329                                        is_truncated);
4330     if (is_truncated) {
4331         PROTO_ITEM_SET_GENERATED(truncated_ti);
4332         expert_add_info(pinfo, truncated_ti, &ei_mac_lte_sch_header_only);
4333         return;
4334     }
4335     else {
4336         PROTO_ITEM_SET_HIDDEN(truncated_ti);
4337     }
4338
4339
4340     /* Now process remaining bodies, which should all be data */
4341     for (; n < number_of_headers; n++) {
4342
4343         /* Data SDUs treated identically for Uplink or downlink channels */
4344         proto_item *sdu_ti;
4345         const guint8 *pdu_data;
4346         volatile guint16 data_length;
4347         int i;
4348         char buff[64];
4349         gboolean rlc_called_for_sdu = FALSE;
4350
4351         /* Break out if meet padding */
4352         if (lcids[n] == PADDING_LCID) {
4353             break;
4354         }
4355
4356         /* Work out length */
4357         data_length = (pdu_lengths[n] == -1) ?
4358                             tvb_length_remaining(tvb, offset) :
4359                             pdu_lengths[n];
4360
4361         /* Dissect SDU as raw bytes */
4362         sdu_ti = proto_tree_add_bytes_format(tree, hf_mac_lte_sch_sdu, tvb, offset, pdu_lengths[n],
4363                                              NULL, "SDU (%s, length=%u bytes): ",
4364                                              val_to_str_const(lcids[n],
4365                                                               (direction == DIRECTION_UPLINK) ?
4366                                                                   ulsch_lcid_vals :
4367                                                                   dlsch_lcid_vals,
4368                                                              "Unknown"),
4369                                              data_length);
4370
4371         /* Look for Msg3 data so that it may be compared with later
4372            Contention Resolution body */
4373         if ((lcids[n] == 0) && (direction == DIRECTION_UPLINK) && (data_length == 6)) {
4374             if (!pinfo->fd->flags.visited) {
4375                 guint key = p_mac_lte_info->rnti;
4376                 Msg3Data *data = (Msg3Data *)g_hash_table_lookup(mac_lte_msg3_hash, GUINT_TO_POINTER(key));
4377
4378                 /* Look for previous entry for this UE */
4379                 if (data == NULL) {
4380                     /* Allocate space for data and add to table */
4381                     data = wmem_new(wmem_file_scope(), Msg3Data);
4382                     g_hash_table_insert(mac_lte_msg3_hash, GUINT_TO_POINTER(key), data);
4383                 }
4384
4385                 /* Fill in data details */
4386                 data->framenum = pinfo->fd->num;
4387                 tvb_memcpy(tvb, data->data, offset, data_length);
4388                 data->msg3Time = pinfo->fd->abs_ts;
4389             }
4390         }
4391
4392         /* CCCH frames can be dissected directly by LTE RRC... */
4393         if ((lcids[n] == 0) && global_mac_lte_attempt_rrc_decode) {
4394             tvbuff_t *rrc_tvb = tvb_new_subset(tvb, offset, data_length, data_length);
4395
4396             /* Get appropriate dissector handle */
4397             volatile dissector_handle_t protocol_handle = 0;
4398             if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
4399                 protocol_handle = find_dissector("lte_rrc.ul_ccch");
4400             }
4401             else {
4402                 protocol_handle = find_dissector("lte_rrc.dl_ccch");
4403             }
4404
4405             /* Hide raw view of bytes */
4406             PROTO_ITEM_SET_HIDDEN(sdu_ti);
4407             rlc_called_for_sdu = TRUE;
4408
4409             call_with_catch_all(protocol_handle, rrc_tvb, pinfo, tree);
4410         }
4411
4412         /* LCID 1 and 2 can be assumed to be srb1&2, so can dissect as RLC AM */
4413         else if ((lcids[n] == 1) || (lcids[n] == 2)) {
4414             if (global_mac_lte_attempt_srb_decode) {
4415                 /* Call RLC dissector */
4416                 call_rlc_dissector(tvb, pinfo, tree, pdu_ti, offset, data_length,
4417                                    RLC_AM_MODE, direction, p_mac_lte_info->ueid,
4418                                    CHANNEL_TYPE_SRB, lcids[n], 0,
4419                                    get_mac_lte_channel_priority(p_mac_lte_info->ueid,
4420                                                                 lcids[n], direction));
4421
4422                 /* Hide raw view of bytes */
4423                 PROTO_ITEM_SET_HIDDEN(sdu_ti);
4424                 rlc_called_for_sdu = TRUE;
4425             }
4426         }
4427
4428         else if ((lcids[n] >= 2) && (lcids[n] <= 10)) {
4429
4430             /* Look for mapping for this LCID to drb channel set by UAT table */
4431             rlc_channel_type_t rlc_channel_type;
4432             guint8 UM_seqnum_length;
4433             gint drb_id;
4434             guint8 priority = get_mac_lte_channel_priority(p_mac_lte_info->ueid,
4435                                                            lcids[n], direction);
4436
4437             lookup_rlc_channel_from_lcid(p_mac_lte_info->ueid,
4438                                          lcids[n],
4439                                          &rlc_channel_type,
4440                                          &UM_seqnum_length,
4441                                          &drb_id);
4442
4443             /* Dissect according to channel type */
4444             switch (rlc_channel_type) {
4445                 case rlcUM5:
4446                     call_rlc_dissector(tvb, pinfo, tree, pdu_ti, offset, data_length,
4447                                        RLC_UM_MODE, direction, p_mac_lte_info->ueid,
4448                                        CHANNEL_TYPE_DRB, (guint16)drb_id, UM_seqnum_length,
4449                                        priority);
4450                     break;
4451                 case rlcUM10:
4452                     call_rlc_dissector(tvb, pinfo, tree, pdu_ti, offset, data_length,
4453                                        RLC_UM_MODE, direction, p_mac_lte_info->ueid,
4454                                        CHANNEL_TYPE_DRB, (guint16)drb_id, UM_seqnum_length,
4455                                        priority);
4456                     break;
4457                 case rlcAM:
4458                     call_rlc_dissector(tvb, pinfo, tree, pdu_ti, offset, data_length,
4459                                        RLC_AM_MODE, direction, p_mac_lte_info->ueid,
4460                                        CHANNEL_TYPE_DRB, (guint16)drb_id, 0,
4461                                        priority);
4462                     break;
4463                 case rlcTM:
4464                     call_rlc_dissector(tvb, pinfo, tree, pdu_ti, offset, data_length,
4465                                        RLC_TM_MODE, direction, p_mac_lte_info->ueid,
4466                                        CHANNEL_TYPE_DRB, (guint16)drb_id, 0,
4467                                        priority);
4468                     break;
4469                 case rlcRaw:
4470                     /* Nothing to do! */
4471                     break;
4472             }
4473
4474             if (rlc_channel_type != rlcRaw) {
4475                 /* Hide raw view of bytes */
4476                 PROTO_ITEM_SET_HIDDEN(sdu_ti);
4477                 rlc_called_for_sdu = TRUE;
4478             }
4479
4480         }
4481
4482         /* Show bytes too, if won't be hidden (slow). There must be a nicer way of doing this! */
4483         if (!rlc_called_for_sdu) {
4484             pdu_data = tvb_get_ptr(tvb, offset, pdu_lengths[n]);
4485             for (i=0; i < data_length; i++) {
4486                 g_snprintf(buff+(i*2), 3, "%02x",  pdu_data[i]);
4487                 if (i >= 30) {
4488                     g_snprintf(buff+(i*2), 4, "...");
4489                     break;
4490                 }
4491             }
4492             proto_item_append_text(sdu_ti, "%s", buff);
4493         }
4494
4495         offset += data_length;
4496
4497         /* Update tap byte count for this channel */
4498         tap_info->bytes_for_lcid[lcids[n]] += data_length;
4499     }
4500
4501
4502     /* Now padding, if present, extends to the end of the PDU */
4503     if (lcids[number_of_headers-1] == PADDING_LCID) {
4504         if (tvb_length_remaining(tvb, offset) > 0) {
4505             proto_tree_add_item(tree, hf_mac_lte_padding_data,
4506                                 tvb, offset, -1, ENC_NA);
4507         }
4508         padding_length_ti = proto_tree_add_int(tree, hf_mac_lte_padding_length,
4509                                                tvb, offset, 0,
4510                                                p_mac_lte_info->length - offset);
4511         PROTO_ITEM_SET_GENERATED(padding_length_ti);
4512
4513         /* Update padding bytes in stats */
4514         tap_info->padding_bytes += (p_mac_lte_info->length - offset);
4515
4516         /* Make sure the PDU isn't bigger than reported! */
4517         if (offset > p_mac_lte_info->length) {
4518             expert_add_info_format(pinfo, padding_length_ti, &ei_mac_lte_context_length,
4519                                    "%s MAC PDU is longer than reported length (reported=%u, actual=%u)",
4520                                    (direction == DIRECTION_UPLINK) ? "UL-SCH" : "DL-SCH",
4521                                    p_mac_lte_info->length, offset);
4522         }
4523     }
4524     else {
4525         /* There is no padding at the end of the frame */
4526         if (!is_truncated && (offset < p_mac_lte_info->length)) {
4527             /* There is a problem if we haven't used all of the PDU */
4528             expert_add_info_format(pinfo, pdu_ti, &ei_mac_lte_context_length,
4529                                    "%s PDU for UE %u is shorter than reported length (reported=%u, actual=%u)",
4530                                    (direction == DIRECTION_UPLINK) ? "UL-SCH" : "DL-SCH",
4531                                    p_mac_lte_info->ueid, p_mac_lte_info->length, offset);
4532         }
4533
4534         if (!is_truncated && (offset > p_mac_lte_info->length)) {
4535             /* There is a problem if the PDU is longer than rpeported */
4536             expert_add_info_format(pinfo, pdu_ti, &ei_mac_lte_context_length,
4537                                    "%s PDU for UE %u is longer than reported length (reported=%u, actual=%u)",
4538                                    (direction == DIRECTION_UPLINK) ? "UL-SCH" : "DL-SCH",
4539                                    p_mac_lte_info->ueid, p_mac_lte_info->length, offset);
4540         }
4541     }
4542
4543     /* Can now store updated DRX info and show its info in the tree */
4544     if (global_mac_lte_show_drx) {
4545         if (!pinfo->fd->flags.visited) {
4546             /* Store 'after' snapshot of UE state for this frame */
4547             set_drx_info(pinfo, p_mac_lte_info, FALSE, pdu_instance);
4548         }
4549
4550         /* Show current DRX state in tree as 'after' */
4551         show_drx_info(pinfo, tree, tvb, p_mac_lte_info, FALSE, pdu_instance);
4552     }
4553 }
4554
4555 static void dissect_mch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *pdu_ti,
4556                         volatile guint32 offset, mac_lte_info *p_mac_lte_info)
4557 {
4558     guint8            extension;
4559     volatile guint16  n;
4560     proto_item       *truncated_ti;
4561     proto_item       *padding_length_ti;
4562     proto_item       *hidden_root_ti;
4563
4564     /* Keep track of LCIDs and lengths as we dissect the header */
4565     volatile guint16 number_of_headers = 0;
4566     guint8  lcids[MAX_HEADERS_IN_PDU];
4567     gint16  pdu_lengths[MAX_HEADERS_IN_PDU];
4568
4569     proto_item *pdu_header_ti, *sched_info_ti = NULL;
4570     proto_tree *pdu_header_tree;
4571
4572     gboolean   have_seen_data_header = FALSE;
4573     guint8     number_of_padding_subheaders = 0;
4574     gboolean   have_seen_non_padding_control = FALSE;
4575     gboolean   expecting_body_data = FALSE;
4576     volatile   guint32    is_truncated = FALSE;
4577
4578     write_pdu_label_and_info_literal(pdu_ti, NULL, pinfo, "MCH: ");
4579
4580     /* Add hidden item to filter on */
4581     hidden_root_ti = proto_tree_add_string_format(tree, hf_mac_lte_mch, tvb,
4582                                                   offset, 0, "", "Hidden header");
4583     PROTO_ITEM_SET_HIDDEN(hidden_root_ti);
4584
4585     /* Add PDU block header subtree */
4586     pdu_header_ti = proto_tree_add_string_format(tree, hf_mac_lte_mch_header,
4587                                                  tvb, offset, 0,
4588                                                  "",
4589                                                  "MAC PDU Header");
4590     pdu_header_tree = proto_item_add_subtree(pdu_header_ti, ett_mac_lte_mch_header);
4591
4592
4593     /************************************************************************/
4594     /* Dissect each sub-header.                                             */
4595     do {
4596         guint8 reserved;
4597         guint64 length = 0;
4598         proto_item *pdu_subheader_ti;
4599         proto_tree *pdu_subheader_tree;
4600         proto_item *lcid_ti;
4601         proto_item *ti;
4602         gint       offset_start_subheader = offset;
4603         guint8 first_byte = tvb_get_guint8(tvb, offset);
4604
4605         /* Add PDU block header subtree.
4606            Default with length of 1 byte. */
4607         pdu_subheader_ti = proto_tree_add_string_format(pdu_header_tree,
4608                                                         hf_mac_lte_mch_subheader,
4609                                                         tvb, offset, 1,
4610                                                         "",
4611                                                         "Sub-header");
4612         pdu_subheader_tree = proto_item_add_subtree(pdu_subheader_ti,
4613                                                     ett_mac_lte_mch_subheader);
4614
4615         /* Check 1st 2 reserved bits */
4616         reserved = (first_byte & 0xc0) >> 6;
4617         ti = proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_mch_reserved,
4618                                  tvb, offset, 1, ENC_BIG_ENDIAN);
4619         if (reserved != 0) {
4620             expert_add_info_format(pinfo, ti, &ei_mac_lte_reserved_not_zero,
4621                                    "MCH header Reserved bits not zero");
4622         }
4623
4624         /* Extended bit */
4625         extension = (first_byte & 0x20) >> 5;
4626         proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_mch_extended,
4627                             tvb, offset, 1, ENC_BIG_ENDIAN);
4628
4629         /* LCID */
4630         lcids[number_of_headers] = first_byte & 0x1f;
4631         lcid_ti = proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_mch_lcid,
4632                                       tvb, offset, 1, ENC_BIG_ENDIAN);
4633         if (lcids[number_of_headers] == MCH_SCHEDULING_INFO_LCID) {
4634             sched_info_ti = lcid_ti;
4635         }
4636         write_pdu_label_and_info(pdu_ti, NULL, pinfo,
4637                                  "(%s",
4638                                  val_to_str_const(lcids[number_of_headers],
4639                                                   mch_lcid_vals, "(Unknown LCID)"));
4640         offset++;
4641
4642         /* Remember if we've seen a data subheader */
4643         if (lcids[number_of_headers] <= 28) {
4644             have_seen_data_header = TRUE;
4645             expecting_body_data = TRUE;
4646         }
4647
4648         /* Show an expert item if a contol subheader (except Padding) appears
4649            *after* a data PDU */
4650         if (have_seen_data_header &&
4651             (lcids[number_of_headers] > 28) && (lcids[number_of_headers] != PADDING_LCID)) {
4652             expert_add_info_format(pinfo, lcid_ti, &ei_mac_lte_control_subheader_after_data_subheader,
4653                                    "MCH Control subheaders should not appear after data subheaders");
4654             return;
4655         }
4656
4657         /* Should not see padding after non-padding control... */
4658         if ((lcids[number_of_headers] > 28) &&
4659             (lcids[number_of_headers] == PADDING_LCID) &&
4660             extension)
4661         {
4662             number_of_padding_subheaders++;
4663             if (number_of_padding_subheaders > 2) {
4664                 expert_add_info(pinfo, lcid_ti, &ei_mac_lte_padding_data_multiple);
4665             }
4666
4667             if (have_seen_non_padding_control) {
4668                 expert_add_info(pinfo, lcid_ti, &ei_mac_lte_padding_data_before_control_subheader);
4669             }
4670         }
4671
4672         /* Remember that we've seen non-padding control */
4673         if ((lcids[number_of_headers] > 28) &&
4674             (lcids[number_of_headers] != PADDING_LCID)) {
4675             have_seen_non_padding_control = TRUE;
4676         }
4677
4678
4679
4680         /********************************************************************/
4681         /* Length field follows if not the last header or for a fixed-sized
4682            control element */
4683         if (!extension) {
4684             /* Last one... */
4685             pdu_lengths[number_of_headers] = -1;
4686         }
4687         else {
4688             /* Not the last one */
4689             if (lcids[number_of_headers] != PADDING_LCID) {
4690
4691                 guint8  format;
4692
4693                 /* F(ormat) bit tells us how long the length field is */
4694                 format = (tvb_get_guint8(tvb, offset) & 0x80) >> 7;
4695                 proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_mch_format,
4696                                     tvb, offset, 1, ENC_BIG_ENDIAN);
4697
4698                 /* Now read length field itself */
4699                 if (format) {
4700                     /* >= 128 - use 15 bits */
4701                     proto_tree_add_bits_ret_val(pdu_subheader_tree, hf_mac_lte_mch_length,
4702                                                 tvb, offset*8 + 1, 15, &length, ENC_BIG_ENDIAN);
4703
4704                     offset += 2;
4705                 }
4706                 else {
4707                     /* Less than 128 - only 7 bits */
4708                     proto_tree_add_bits_ret_val(pdu_subheader_tree, hf_mac_lte_mch_length,
4709                                                 tvb, offset*8 + 1, 7, &length, ENC_BIG_ENDIAN);
4710                     offset++;
4711                 }
4712                 pdu_lengths[number_of_headers] = (gint16)length;
4713             }
4714             else {
4715                 pdu_lengths[number_of_headers] = 0;
4716             }
4717         }
4718
4719
4720         /* Close off description in info column */
4721         switch (pdu_lengths[number_of_headers]) {
4722             case 0:
4723                 write_pdu_label_and_info_literal(pdu_ti, NULL, pinfo, ") ");
4724                 break;
4725             case -1:
4726                 write_pdu_label_and_info_literal(pdu_ti, NULL, pinfo, ":remainder) ");
4727                 break;
4728             default:
4729                 write_pdu_label_and_info(pdu_ti, NULL, pinfo, ":%u bytes) ",
4730                                          pdu_lengths[number_of_headers]);
4731                 break;
4732         }
4733
4734         /* Append summary to subheader root */
4735         proto_item_append_text(pdu_subheader_ti, " (lcid=%s",
4736                                val_to_str_const(lcids[number_of_headers],
4737                                                 mch_lcid_vals, "Unknown"));
4738
4739         switch (pdu_lengths[number_of_headers]) {
4740             case -1:
4741                 proto_item_append_text(pdu_subheader_ti, ", length is remainder)");
4742                 proto_item_append_text(pdu_header_ti, " (%s:remainder)",
4743                                        val_to_str_const(lcids[number_of_headers],
4744                                                         mch_lcid_vals,
4745                                                         "Unknown"));
4746                 break;
4747             case 0:
4748                 proto_item_append_text(pdu_subheader_ti, ")");
4749                 proto_item_append_text(pdu_header_ti, " (%s)",
4750                                        val_to_str_const(lcids[number_of_headers],
4751                                                         mch_lcid_vals,
4752                                                         "Unknown"));
4753                 break;
4754             default:
4755                 proto_item_append_text(pdu_subheader_ti, ", length=%u)",
4756                                        pdu_lengths[number_of_headers]);
4757                 proto_item_append_text(pdu_header_ti, " (%s:%u)",
4758                                        val_to_str_const(lcids[number_of_headers],
4759                                                         mch_lcid_vals,
4760                                                         "Unknown"),
4761                                        pdu_lengths[number_of_headers]);
4762                 break;
4763         }
4764
4765
4766         /* Flag unknown lcid values in expert info */
4767         if (try_val_to_str(lcids[number_of_headers],mch_lcid_vals) == NULL) {
4768             expert_add_info_format(pinfo, pdu_subheader_ti, &ei_mac_lte_lcid_unexpected,
4769                                    "MCH: Unexpected LCID received (%u)",
4770                                    lcids[number_of_headers]);
4771         }
4772
4773         /* Set length of this subheader */
4774         proto_item_set_len(pdu_subheader_ti, offset - offset_start_subheader);
4775
4776         number_of_headers++;
4777     } while ((number_of_headers < MAX_HEADERS_IN_PDU) && extension);
4778
4779     /* Check that we didn't reach the end of the subheader array... */
4780     if (number_of_headers >= MAX_HEADERS_IN_PDU) {
4781         proto_tree_add_expert_format(tree, pinfo, &ei_mac_lte_too_many_subheaders, tvb, offset, 1,
4782                                              "Reached %u subheaders - frame obviously malformed",
4783                                              MAX_HEADERS_IN_PDU);
4784         return;
4785     }
4786
4787
4788     /* Append summary to overall PDU header root */
4789     proto_item_append_text(pdu_header_ti, " (%u subheaders)",
4790                            number_of_headers);
4791
4792     /* And set its length to offset */
4793     proto_item_set_len(pdu_header_ti, offset);
4794
4795
4796     /************************************************************************/
4797     /* Dissect SDUs / control elements / padding.                           */
4798     /************************************************************************/
4799
4800     /* Dissect control element bodies first */
4801
4802     for (n=0; n < number_of_headers; n++) {
4803         /* Get out of loop once see any data SDU subheaders */
4804         if (lcids[n] <= 28) {
4805             break;
4806         }
4807
4808         /* Process what should be a valid control PDU type */
4809         switch (lcids[n]) {
4810             case MCH_SCHEDULING_INFO_LCID:
4811                 {
4812                     guint32 curr_offset = offset;
4813                     gint16 i;
4814                     guint16 stop_mtch_val;
4815                     proto_item *mch_sched_info_ti, *ti;
4816                     proto_tree *mch_sched_info_tree;
4817
4818                     if (pdu_lengths[n] == -1) {
4819                         /* Control Element size is the remaining PDU */
4820                         pdu_lengths[n] = (gint16)tvb_length_remaining(tvb, curr_offset);
4821                     }
4822                     if (pdu_lengths[n] & 0x01) {
4823                         expert_add_info_format(pinfo, sched_info_ti, &ei_mac_lte_context_length,
4824                                                "MCH Scheduling Information MAC Control Element should have an even size");
4825                     }
4826
4827                     mch_sched_info_ti = proto_tree_add_string_format(tree,
4828                                                                      hf_mac_lte_control_mch_scheduling_info,
4829                                                                      tvb, curr_offset, pdu_lengths[n],
4830                                                                      "",
4831                                                                      "MCH Scheduling Information");
4832                     mch_sched_info_tree = proto_item_add_subtree(mch_sched_info_ti, ett_mac_lte_mch_scheduling_info);
4833
4834                     for (i=0; i<(pdu_lengths[n]/2); i++) {
4835                         proto_tree_add_item(mch_sched_info_tree, hf_mac_lte_control_mch_scheduling_info_lcid,
4836                                             tvb, curr_offset, 1, ENC_BIG_ENDIAN);
4837                         stop_mtch_val = tvb_get_ntohs(tvb, curr_offset) & 0x7ff;
4838                         ti = proto_tree_add_item(mch_sched_info_tree, hf_mac_lte_control_mch_scheduling_info_stop_mtch,
4839                                                  tvb, curr_offset, 2, ENC_BIG_ENDIAN);
4840                         if ((stop_mtch_val >= 2043) && (stop_mtch_val <= 2046)) {
4841                             proto_item_append_text(ti, " (reserved)");
4842                         }
4843                         else if (stop_mtch_val == 2047) {
4844                             proto_item_append_text(ti, " (MTCH is not scheduled)");
4845                         }
4846                         curr_offset += 2;
4847                     }
4848
4849                     offset += pdu_lengths[n];
4850                 }
4851                 break;
4852             case PADDING_LCID:
4853                 /* No payload (in this position) */
4854                 break;
4855
4856             default:
4857                 break;
4858         }
4859     }
4860
4861
4862     /* There might not be any data, if only headers (plus control data) were logged */
4863     is_truncated = ((tvb_length_remaining(tvb, offset) == 0) && expecting_body_data);
4864     truncated_ti = proto_tree_add_uint(tree, hf_mac_lte_mch_header_only, tvb, 0, 0,
4865                                        is_truncated);
4866     if (is_truncated) {
4867         PROTO_ITEM_SET_GENERATED(truncated_ti);
4868         expert_add_info(pinfo, truncated_ti, &ei_mac_lte_sch_header_only);
4869         return;
4870     }
4871     else {
4872         PROTO_ITEM_SET_HIDDEN(truncated_ti);
4873     }
4874
4875
4876     /* Now process remaining bodies, which should all be data */
4877     for (; n < number_of_headers; n++) {
4878
4879         proto_item *sdu_ti;
4880         const guint8 *pdu_data;
4881         volatile guint16 data_length;
4882         int i;
4883         char buff[64];
4884
4885         /* Break out if meet padding */
4886         if (lcids[n] == PADDING_LCID) {
4887             break;
4888         }
4889
4890         /* Work out length */
4891         data_length = (pdu_lengths[n] == -1) ?
4892                             tvb_length_remaining(tvb, offset) :
4893                             pdu_lengths[n];
4894
4895         if ((lcids[n] == 0) && global_mac_lte_attempt_mcch_decode) {
4896             /* Call RLC dissector */
4897             call_rlc_dissector(tvb, pinfo, tree, pdu_ti, offset, data_length,
4898                                RLC_UM_MODE, DIRECTION_DOWNLINK, 0,
4899                                CHANNEL_TYPE_MCCH, 0, 5, 0);
4900         } else if ((lcids[n] <= 28) && global_mac_lte_call_rlc_for_mtch) {
4901             /* Call RLC dissector */
4902             call_rlc_dissector(tvb, pinfo, tree, pdu_ti, offset, data_length,
4903                                RLC_UM_MODE, DIRECTION_DOWNLINK, 0,
4904                                CHANNEL_TYPE_MTCH, 0, 5, 0);
4905         } else {
4906             /* Dissect SDU as raw bytes */
4907             sdu_ti = proto_tree_add_bytes_format(tree, hf_mac_lte_mch_sdu, tvb, offset, pdu_lengths[n],
4908                                                  NULL, "SDU (%s, length=%u bytes): ",
4909                                                  val_to_str_const(lcids[n], mch_lcid_vals, "Unknown"),
4910                                                  data_length);
4911
4912             /* Show bytes too.  There must be a nicer way of doing this! */
4913             pdu_data = tvb_get_ptr(tvb, offset, pdu_lengths[n]);
4914             for (i=0; i < data_length; i++) {
4915                 g_snprintf(buff+(i*2), 3, "%02x",  pdu_data[i]);
4916                 if (i >= 30) {
4917                     g_snprintf(buff+(i*2), 4, "...");
4918                     break;
4919                 }
4920             }
4921             proto_item_append_text(sdu_ti, "%s", buff);
4922         }
4923
4924         offset += data_length;
4925     }
4926
4927     /* Now padding, if present, extends to the end of the PDU */
4928     if (lcids[number_of_headers-1] == PADDING_LCID) {
4929         if (tvb_length_remaining(tvb, offset) > 0) {
4930             proto_tree_add_item(tree, hf_mac_lte_padding_data,
4931                                 tvb, offset, -1, ENC_NA);
4932         }
4933         padding_length_ti = proto_tree_add_int(tree, hf_mac_lte_padding_length,
4934                                                tvb, offset, 0,
4935                                                p_mac_lte_info->length - offset);
4936         PROTO_ITEM_SET_GENERATED(padding_length_ti);
4937
4938         /* Make sure the PDU isn't bigger than reported! */
4939         if (offset > p_mac_lte_info->length) {
4940             expert_add_info_format(pinfo, padding_length_ti, &ei_mac_lte_context_length,
4941                                    "MAC PDU is longer than reported length (reported=%u, actual=%u)",
4942                                    p_mac_lte_info->length, offset);
4943         }
4944     }
4945     else {
4946         /* There is no padding at the end of the frame */
4947         if (!is_truncated && (offset < p_mac_lte_info->length)) {
4948             /* There is a problem if we haven't used all of the PDU */
4949             expert_add_info_format(pinfo, pdu_ti, &ei_mac_lte_context_length,
4950                                    "PDU is shorter than reported length (reported=%u, actual=%u)",
4951                                    p_mac_lte_info->length, offset);
4952         }
4953
4954         if (!is_truncated && (offset > p_mac_lte_info->length)) {
4955             /* There is a problem if the PDU is longer than rpeported */
4956             expert_add_info_format(pinfo, pdu_ti, &ei_mac_lte_context_length,
4957                                    "PDU is longer than reported length (reported=%u, actual=%u)",
4958                                    p_mac_lte_info->length, offset);
4959         }
4960     }
4961 }
4962
4963
4964 /*****************************/
4965 /* Main dissection function. */
4966 /* 'data' will be cast to an int, where it can then be used to differentiate
4967    multiple MAC PDUs logged in the same frame (e.g. in the LTE eNB LI API definition from
4968    the Small Cell Forum)
4969 */
4970 int dissect_mac_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
4971 {
4972     proto_tree          *mac_lte_tree;
4973     proto_item          *pdu_ti;
4974     proto_tree          *context_tree;
4975     proto_item          *context_ti;
4976     proto_item          *retx_ti        = NULL;
4977     proto_item          *ti;
4978     gint                 offset         = 0;
4979     struct mac_lte_info *p_mac_lte_info;
4980     gint                 n;
4981     guint               pdu_instance = GPOINTER_TO_UINT(data);
4982
4983     /* Allocate and zero tap struct */
4984     mac_lte_tap_info *tap_info = (mac_lte_tap_info *)wmem_alloc0(wmem_file_scope(), sizeof(mac_lte_tap_info));
4985
4986     /* Set protocol name */
4987     col_set_str(pinfo->cinfo, COL_PROTOCOL, "MAC-LTE");
4988
4989     /* Create protocol tree. */
4990     pdu_ti = proto_tree_add_item(tree, proto_mac_lte, tvb, offset, -1, ENC_NA);
4991     proto_item_append_text(pdu_ti, " ");
4992     mac_lte_tree = proto_item_add_subtree(pdu_ti, ett_mac_lte);
4993
4994     /* Look for packet info! */
4995     p_mac_lte_info = (mac_lte_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_mac_lte, 0);
4996
4997     /* Can't dissect anything without it... */
4998     if (p_mac_lte_info == NULL) {
4999         proto_item *tii =
5000             proto_tree_add_text(mac_lte_tree, tvb, offset, -1,
5001                                 "Can't dissect LTE MAC frame because no per-frame info was attached!");
5002         PROTO_ITEM_SET_GENERATED(tii);
5003         return 0;
5004     }
5005
5006     /* Clear info column */
5007     col_clear(pinfo->cinfo, COL_INFO);
5008
5009
5010     /*****************************************/
5011     /* Show context information              */
5012
5013     /* Create context root */
5014     context_ti = proto_tree_add_string_format(mac_lte_tree, hf_mac_lte_context,
5015                                               tvb, offset, 0, "", "Context");
5016     context_tree = proto_item_add_subtree(context_ti, ett_mac_lte_context);
5017     PROTO_ITEM_SET_GENERATED(context_ti);
5018
5019     ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_radio_type,
5020                              tvb, 0, 0, p_mac_lte_info->radioType);
5021     PROTO_ITEM_SET_GENERATED(ti);
5022
5023     ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_direction,
5024                              tvb, 0, 0, p_mac_lte_info->direction);
5025     PROTO_ITEM_SET_GENERATED(ti);
5026
5027     if (p_mac_lte_info->ueid != 0) {
5028         ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_ueid,
5029                                  tvb, 0, 0, p_mac_lte_info->ueid);
5030         PROTO_ITEM_SET_GENERATED(ti);
5031     }
5032
5033     /* There are several out-of-band MAC events that may be indicated in the context info. */
5034     /* Handle them here */
5035     if (p_mac_lte_info->length == 0) {
5036         proto_item *preamble_ti;
5037         proto_tree *preamble_tree;
5038
5039         switch (p_mac_lte_info->oob_event) {
5040             case ltemac_send_preamble:
5041                 preamble_ti = proto_tree_add_item(mac_lte_tree, hf_mac_lte_oob_send_preamble,
5042                                                   tvb, 0, 0, ENC_ASCII|ENC_NA);
5043                 preamble_tree = proto_item_add_subtree(preamble_ti, ett_mac_lte_oob);
5044                 PROTO_ITEM_SET_GENERATED(ti);
5045
5046                 ti = proto_tree_add_uint(preamble_tree, hf_mac_lte_context_rapid,
5047                                          tvb, 0, 0, p_mac_lte_info->rapid);
5048                 PROTO_ITEM_SET_GENERATED(ti);
5049
5050                 ti = proto_tree_add_uint(preamble_tree, hf_mac_lte_context_rach_attempt_number,
5051                                          tvb, 0, 0, p_mac_lte_info->rach_attempt_number);
5052                 PROTO_ITEM_SET_GENERATED(ti);
5053
5054                 /* Info column */
5055                 write_pdu_label_and_info(pdu_ti, preamble_ti, pinfo,
5056                                          "RACH Preamble chosen for UE %u (RAPID=%u, attempt=%u)",
5057                                          p_mac_lte_info->ueid, p_mac_lte_info->rapid,
5058                                          p_mac_lte_info->rach_attempt_number);
5059
5060                 /* Add expert info (a note, unless attempt > 1) */
5061                 expert_add_info_format(pinfo, ti,
5062                     (p_mac_lte_info->rach_attempt_number > 1) ? &ei_mac_lte_rach_preamble_sent_warn : &ei_mac_lte_rach_preamble_sent_note,
5063                                        "RACH Preamble sent for UE %u (RAPID=%u, attempt=%u)",
5064                                        p_mac_lte_info->ueid, p_mac_lte_info->rapid,
5065                                        p_mac_lte_info->rach_attempt_number);
5066                 break;
5067             case ltemac_send_sr:
5068                     /* Count of SRs */
5069                     ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_number_of_srs,
5070                                              tvb, 0, 0, p_mac_lte_info->number_of_srs);
5071                     PROTO_ITEM_SET_GENERATED(ti);
5072
5073
5074                 for (n=0; n < p_mac_lte_info->number_of_srs; n++) {
5075                     proto_item *sr_ti;
5076                     proto_tree *sr_tree;
5077
5078                     /* SR event is subtree */
5079                     sr_ti = proto_tree_add_expert_format(mac_lte_tree, pinfo, &ei_mac_lte_oob_send_sr,
5080                                                 tvb, 0, 0,
5081                                                 "Scheduling Request sent for UE %u (RNTI %u)", p_mac_lte_info->oob_ueid[n], p_mac_lte_info->oob_rnti[n]);
5082                     sr_tree = proto_item_add_subtree(sr_ti, ett_mac_lte_oob);
5083                     PROTO_ITEM_SET_GENERATED(sr_ti);
5084
5085                     /* RNTI */
5086                     ti = proto_tree_add_uint(sr_tree, hf_mac_lte_context_rnti,
5087                                              tvb, 0, 0, p_mac_lte_info->oob_rnti[n]);
5088                     PROTO_ITEM_SET_GENERATED(ti);
5089
5090                     /* UEID */
5091                     ti = proto_tree_add_uint(sr_tree, hf_mac_lte_context_ueid,
5092                                              tvb, 0, 0, p_mac_lte_info->oob_ueid[n]);
5093                     PROTO_ITEM_SET_GENERATED(ti);
5094
5095                     /* Add summary to root. */
5096                     proto_item_append_text(sr_ti, " (UE=%u C-RNTI=%u)",
5097                                            p_mac_lte_info->oob_ueid[n],
5098                                            p_mac_lte_info->oob_rnti[n]);
5099
5100                     /* Info column */
5101                     if (n == 0) {
5102                         write_pdu_label_and_info(pdu_ti, NULL, pinfo,
5103                                                 "Scheduling Requests (%u) sent: (UE=%u C-RNTI=%u)",
5104                                                 p_mac_lte_info->number_of_srs,
5105                                                 p_mac_lte_info->oob_ueid[n],
5106                                                 p_mac_lte_info->oob_rnti[n]);
5107                     }
5108                     else {
5109                         write_pdu_label_and_info(pdu_ti, NULL, pinfo,
5110                                                 " (UE=%u C-RNTI=%u)",
5111                                                 p_mac_lte_info->oob_ueid[n],
5112                                                 p_mac_lte_info->oob_rnti[n]);
5113                     }
5114
5115                     /* Update SR status for this UE */
5116                     if (global_mac_lte_track_sr) {
5117                         TrackSRInfo(SR_Request, pinfo, mac_lte_tree, tvb, p_mac_lte_info, n, sr_ti);
5118                     }
5119                 }
5120                 break;
5121             case ltemac_sr_failure:
5122                 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_rnti,
5123                                          tvb, 0, 0, p_mac_lte_info->rnti);
5124                 PROTO_ITEM_SET_GENERATED(ti);
5125
5126                 proto_tree_add_expert_format(mac_lte_tree, pinfo, &ei_mac_lte_oob_sr_failure,
5127                                          tvb, 0, 0, "Scheduling Request failed for UE %u (RNTI %u)",
5128                                          p_mac_lte_info->ueid, p_mac_lte_info->rnti);
5129                 PROTO_ITEM_SET_GENERATED(ti);
5130
5131                 /* Info column */
5132                 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
5133                                          "Scheduling Request FAILED for UE %u (C-RNTI=%u)",
5134                                          p_mac_lte_info->ueid,
5135                                          p_mac_lte_info->rnti);
5136
5137                 /* Update SR status */
5138                 if (global_mac_lte_track_sr) {
5139                     TrackSRInfo(SR_Failure, pinfo, mac_lte_tree, tvb, p_mac_lte_info, 0, ti);
5140                 }
5141
5142                 break;
5143         }
5144
5145         /* Our work here is done */
5146         return -1;
5147     }
5148
5149     /* Show remaining meta information */
5150     ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_sysframe_number,
5151                              tvb, 0, 0, p_mac_lte_info->sysframeNumber);
5152     PROTO_ITEM_SET_GENERATED(ti);
5153     if (p_mac_lte_info->sysframeNumber > 1023) {
5154         expert_add_info_format(pinfo, ti, &ei_mac_lte_context_sysframe_number,
5155                                "Sysframe number (%u) out of range - valid range is 0-1023",
5156                                p_mac_lte_info->sysframeNumber);
5157     }
5158
5159     ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_subframe_number,
5160                              tvb, 0, 0, p_mac_lte_info->subframeNumber);
5161     PROTO_ITEM_SET_GENERATED(ti);
5162     if (p_mac_lte_info->subframeNumber > 9) {
5163         /* N.B. if we set it to valid value, it won't trigger when we rescan
5164            (at least with DCT2000 files where the context struct isn't re-read). */
5165         expert_add_info_format(pinfo, ti, &ei_mac_lte_context_sysframe_number,
5166                                "Subframe number (%u) out of range - valid range is 0-9",
5167                                p_mac_lte_info->subframeNumber);
5168     }
5169
5170     if (p_mac_lte_info->subframeNumberOfGrantPresent) {
5171         ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_grant_subframe_number,
5172                                  tvb, 0, 0, p_mac_lte_info->subframeNumberOfGrant);
5173         PROTO_ITEM_SET_GENERATED(ti);
5174     }
5175
5176     if (p_mac_lte_info->rntiType != NO_RNTI) {
5177         ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_rnti,
5178                                  tvb, 0, 0, p_mac_lte_info->rnti);
5179         PROTO_ITEM_SET_GENERATED(ti);
5180         proto_item_append_text(context_ti, " (RNTI=%u)", p_mac_lte_info->rnti);
5181     }
5182
5183
5184     ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_rnti_type,
5185                              tvb, 0, 0, p_mac_lte_info->rntiType);
5186     PROTO_ITEM_SET_GENERATED(ti);
5187
5188     /* Check that RNTI value is consistent with given RNTI type */
5189     switch (p_mac_lte_info->rntiType) {
5190         case M_RNTI:
5191             if (p_mac_lte_info->rnti != 0xFFFD) {
5192                 expert_add_info_format(pinfo, ti, &ei_mac_lte_context_rnti_type,
5193                       "M-RNTI indicated, but value is %u (0x%x) (must be 0x%x)",
5194                       p_mac_lte_info->rnti, p_mac_lte_info->rnti, 0xFFFD);
5195                 return 0;
5196             }
5197             break;
5198         case P_RNTI:
5199             if (p_mac_lte_info->rnti != 0xFFFE) {
5200                 expert_add_info_format(pinfo, ti, &ei_mac_lte_context_rnti_type,
5201                       "P-RNTI indicated, but value is %u (0x%x) (must be 0x%x)",
5202                       p_mac_lte_info->rnti, p_mac_lte_info->rnti, 0xFFFE);
5203                 return 0;
5204             }
5205             break;
5206         case SI_RNTI:
5207             if (p_mac_lte_info->rnti != 0xFFFF) {
5208                 expert_add_info_format(pinfo, ti, &ei_mac_lte_context_rnti_type,
5209                       "SI-RNTI indicated, but value is %u (0x%x) (must be 0x%x)",
5210                       p_mac_lte_info->rnti, p_mac_lte_info->rnti, 0xFFFE);
5211                 return 0;
5212             }
5213             break;
5214         case RA_RNTI:
5215             if ((p_mac_lte_info->rnti < 0x0001) || (p_mac_lte_info->rnti > 0x003C)) {
5216                 expert_add_info_format(pinfo, ti, &ei_mac_lte_context_rnti_type,
5217                       "RA_RNTI indicated, but given value %u (0x%x)is out of range",
5218                       p_mac_lte_info->rnti, p_mac_lte_info->rnti);
5219                 return 0;
5220             }
5221             break;
5222         case C_RNTI:
5223         case SPS_RNTI:
5224             if ((p_mac_lte_info->rnti < 0x0001) || (p_mac_lte_info->rnti > 0xFFF3)) {
5225                 expert_add_info_format(pinfo, ti, &ei_mac_lte_context_rnti_type,
5226                       "%s indicated, but given value %u (0x%x)is out of range",
5227                       val_to_str_const(p_mac_lte_info->rntiType,  rnti_type_vals, "Unknown"),
5228                       p_mac_lte_info->rnti, p_mac_lte_info->rnti);
5229                 return 0;
5230             }
5231             break;
5232
5233         default:
5234             break;
5235     }
5236
5237     ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_predefined_frame,
5238                              tvb, 0, 0, p_mac_lte_info->isPredefinedData);
5239     if (p_mac_lte_info->isPredefinedData) {
5240         PROTO_ITEM_SET_GENERATED(ti);
5241     }
5242     else {
5243         PROTO_ITEM_SET_HIDDEN(ti);
5244     }
5245
5246     ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_length,
5247                              tvb, 0, 0, p_mac_lte_info->length);
5248     PROTO_ITEM_SET_GENERATED(ti);
5249     /* Infer uplink grant size */
5250     if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
5251         ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_ul_grant_size,
5252                                  tvb, 0, 0, p_mac_lte_info->length);
5253         PROTO_ITEM_SET_GENERATED(ti);
5254     }
5255
5256     /* Retx count goes in top-level tree to make it more visible */
5257     if (p_mac_lte_info->reTxCount) {
5258         proto_item *retx_reason_ti;
5259         retx_ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_context_retx_count,
5260                                  tvb, 0, 0, p_mac_lte_info->reTxCount);
5261         PROTO_ITEM_SET_GENERATED(retx_ti);
5262
5263         if (p_mac_lte_info->reTxCount >= global_mac_lte_retx_counter_trigger) {
5264             expert_add_info_format(pinfo, retx_ti, &ei_mac_lte_ul_mac_frame_retx,
5265                                    "UE %u: UL MAC frame ReTX no. %u",
5266                                    p_mac_lte_info->ueid, p_mac_lte_info->reTxCount);
5267         }
5268
5269         retx_reason_ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_context_retx_reason,
5270                                              tvb, 0, 0, p_mac_lte_info->isPHICHNACK);
5271         PROTO_ITEM_SET_GENERATED(retx_reason_ti);
5272     }
5273
5274     if (p_mac_lte_info->crcStatusValid) {
5275         /* Set status */
5276         ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_crc_status,
5277                                  tvb, 0, 0, p_mac_lte_info->crcStatus);
5278         PROTO_ITEM_SET_GENERATED(ti);
5279
5280         /* Report non-success */
5281         if (p_mac_lte_info->crcStatus != crc_success) {
5282             expert_add_info_format(pinfo, ti, &ei_mac_lte_context_crc_status,
5283                                    "%s Frame has CRC error problem (%s)",
5284                                    (p_mac_lte_info->direction == DIRECTION_UPLINK) ? "UL" : "DL",
5285                                    val_to_str_const(p_mac_lte_info->crcStatus,
5286                                                     crc_status_vals,
5287                                                     "Unknown"));
5288             write_pdu_label_and_info(pdu_ti, NULL, pinfo,
5289                                      "%s: <CRC %s> UEId=%u %s=%u ",
5290                                      (p_mac_lte_info->direction == DIRECTION_UPLINK) ? "UL" : "DL",
5291                                      val_to_str_const(p_mac_lte_info->crcStatus,
5292                                                     crc_status_vals,
5293                                                     "Unknown"),
5294                                      p_mac_lte_info->ueid,
5295                                      val_to_str_const(p_mac_lte_info->rntiType, rnti_type_vals,
5296                                                       "Unknown RNTI type"),
5297                                      p_mac_lte_info->rnti);
5298         }
5299     }
5300
5301     /* Carrier Id */
5302     ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_carrier_id,
5303                              tvb, 0, 0, p_mac_lte_info->carrierId);
5304     PROTO_ITEM_SET_GENERATED(ti);
5305
5306     /* May also have extra Physical layer attributes set for this frame */
5307     show_extra_phy_parameters(pinfo, tvb, mac_lte_tree, p_mac_lte_info);
5308
5309     /* Set context-info parts of tap struct */
5310     tap_info->rnti = p_mac_lte_info->rnti;
5311     tap_info->ueid = p_mac_lte_info->ueid;
5312     tap_info->rntiType = p_mac_lte_info->rntiType;
5313     tap_info->isPredefinedData = p_mac_lte_info->isPredefinedData;
5314     tap_info->isPHYRetx = (p_mac_lte_info->reTxCount >= 1);
5315     tap_info->crcStatusValid = p_mac_lte_info->crcStatusValid;
5316     tap_info->crcStatus = p_mac_lte_info->crcStatus;
5317     tap_info->direction = p_mac_lte_info->direction;
5318
5319     tap_info->time = pinfo->fd->abs_ts;
5320
5321     /* Also set total number of bytes (won't be used for UL/DL-SCH) */
5322     tap_info->single_number_of_bytes = tvb_length_remaining(tvb, offset);
5323
5324     /* If we know its predefined data, don't try to decode any further */
5325     if (p_mac_lte_info->isPredefinedData) {
5326         proto_tree_add_item(mac_lte_tree, hf_mac_lte_predefined_pdu, tvb, offset, -1, ENC_NA);
5327         write_pdu_label_and_info(pdu_ti, NULL, pinfo,
5328                                  "Predefined data (%u bytes%s)",
5329                                  p_mac_lte_info->length,
5330                                  (p_mac_lte_info->length > tvb_length_remaining(tvb, offset) ?
5331                                      " - truncated" :
5332                                      ""));
5333
5334         /* Queue tap info */
5335         if (!pinfo->flags.in_error_pkt) {
5336             tap_queue_packet(mac_lte_tap, pinfo, tap_info);
5337         }
5338
5339         return -1;
5340     }
5341
5342     /* IF CRC status failed, just do decode as raw bytes */
5343     if (!global_mac_lte_dissect_crc_failures &&
5344         (p_mac_lte_info->crcStatusValid &&
5345          (p_mac_lte_info->crcStatus != crc_success))) {
5346
5347         proto_tree_add_item(mac_lte_tree, hf_mac_lte_raw_pdu, tvb, offset, -1, ENC_NA);
5348         write_pdu_label_and_info(pdu_ti, NULL, pinfo, "Raw data (%u bytes)", tvb_length_remaining(tvb, offset));
5349
5350         /* Queue tap info.
5351            TODO: unfortunately DL retx detection won't get done if we return here... */
5352         if (!pinfo->flags.in_error_pkt) {
5353             tap_queue_packet(mac_lte_tap, pinfo, tap_info);
5354         }
5355
5356         return -1;
5357     }
5358
5359     /* Reset this counter */
5360     s_number_of_rlc_pdus_shown = 0;
5361
5362     /* Dissect the MAC PDU itself. Format depends upon RNTI type. */
5363     switch (p_mac_lte_info->rntiType) {
5364
5365         case P_RNTI:
5366             /* PCH PDU */
5367             dissect_pch(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info->direction, tap_info);
5368             break;
5369
5370         case RA_RNTI:
5371             /* RAR PDU */
5372             dissect_rar(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info, tap_info);
5373             break;
5374
5375         case C_RNTI:
5376         case SPS_RNTI:
5377             /* Can be UL-SCH or DL-SCH */
5378             dissect_ulsch_or_dlsch(tvb, pinfo, mac_lte_tree, pdu_ti, offset,
5379                                    p_mac_lte_info->direction, p_mac_lte_info, tap_info,
5380                                    retx_ti, context_tree, pdu_instance);
5381             break;
5382
5383         case SI_RNTI:
5384             /* BCH over DL-SCH */
5385             dissect_bch(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info);
5386             break;
5387
5388         case M_RNTI:
5389             /* MCH PDU */
5390             dissect_mch(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info);
5391             break;
5392
5393         case NO_RNTI:
5394             /* Must be BCH over BCH... */
5395             dissect_bch(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info);
5396             break;
5397
5398
5399         default:
5400             break;
5401     }
5402
5403     /* Queue tap info */
5404     tap_queue_packet(mac_lte_tap, pinfo, tap_info);
5405
5406     return -1;
5407 }
5408
5409
5410
5411
5412 /* Initializes the hash tables each time a new
5413  * file is loaded or re-loaded in wireshark */
5414 static void mac_lte_init_protocol(void)
5415 {
5416     /* Destroy any existing tables. */
5417     if (mac_lte_msg3_hash) {
5418         g_hash_table_destroy(mac_lte_msg3_hash);
5419     }
5420     if (mac_lte_cr_result_hash) {
5421         g_hash_table_destroy(mac_lte_cr_result_hash);
5422     }
5423
5424     if (mac_lte_dl_harq_hash) {
5425         g_hash_table_destroy(mac_lte_dl_harq_hash);
5426     }
5427     if (mac_lte_dl_harq_result_hash) {
5428         g_hash_table_destroy(mac_lte_dl_harq_result_hash);
5429     }
5430     if (mac_lte_ul_harq_hash) {
5431         g_hash_table_destroy(mac_lte_ul_harq_hash);
5432     }
5433     if (mac_lte_ul_harq_result_hash) {
5434         g_hash_table_destroy(mac_lte_ul_harq_result_hash);
5435     }
5436     if (mac_lte_ue_sr_state) {
5437         g_hash_table_destroy(mac_lte_ue_sr_state);
5438     }
5439     if (mac_lte_sr_request_hash) {
5440         g_hash_table_destroy(mac_lte_sr_request_hash);
5441     }
5442     if (mac_lte_tti_info_result_hash) {
5443         g_hash_table_destroy(mac_lte_tti_info_result_hash);
5444     }
5445     if (mac_lte_ue_channels_hash) {
5446         g_hash_table_destroy(mac_lte_ue_channels_hash);
5447     }
5448     if (mac_lte_drx_ue_state) {
5449         g_hash_table_destroy(mac_lte_drx_ue_state);
5450     }
5451     if (mac_lte_drx_frame_result) {
5452         g_hash_table_destroy(mac_lte_drx_frame_result);
5453     }
5454
5455
5456     /* Reset structs */
5457     memset(&UL_tti_info, 0, sizeof(UL_tti_info));
5458     UL_tti_info.subframe = 0xff;  /* Invalid value */
5459     memset(&DL_tti_info, 0, sizeof(DL_tti_info));
5460     DL_tti_info.subframe = 0xff;  /* Invalid value */
5461
5462     /* Now create them over */
5463     mac_lte_msg3_hash = g_hash_table_new(mac_lte_rnti_hash_func, mac_lte_rnti_hash_equal);
5464     mac_lte_cr_result_hash = g_hash_table_new(mac_lte_framenum_hash_func, mac_lte_framenum_hash_equal);
5465
5466     mac_lte_dl_harq_hash = g_hash_table_new(mac_lte_rnti_hash_func, mac_lte_rnti_hash_equal);
5467     mac_lte_dl_harq_result_hash = g_hash_table_new(mac_lte_framenum_hash_func, mac_lte_framenum_hash_equal);
5468
5469     mac_lte_ul_harq_hash = g_hash_table_new(mac_lte_rnti_hash_func, mac_lte_rnti_hash_equal);
5470     mac_lte_ul_harq_result_hash = g_hash_table_new(mac_lte_framenum_hash_func, mac_lte_framenum_hash_equal);
5471
5472     mac_lte_ue_sr_state = g_hash_table_new(mac_lte_rnti_hash_func, mac_lte_rnti_hash_equal);
5473     mac_lte_sr_request_hash = g_hash_table_new(mac_lte_framenum_hash_func, mac_lte_framenum_hash_equal);
5474
5475     mac_lte_tti_info_result_hash = g_hash_table_new(mac_lte_framenum_hash_func, mac_lte_framenum_hash_equal);
5476
5477     mac_lte_ue_channels_hash = g_hash_table_new(mac_lte_rnti_hash_func, mac_lte_rnti_hash_equal);
5478
5479     mac_lte_drx_ue_state = g_hash_table_new(mac_lte_rnti_hash_func, mac_lte_rnti_hash_equal);
5480     mac_lte_drx_frame_result = g_hash_table_new(mac_lte_framenum_instance_hash_func, mac_lte_framenum_instance_hash_equal);
5481 }
5482
5483 /* Callback used as part of configuring a channel mapping using UAT */
5484 static void* lcid_drb_mapping_copy_cb(void* dest, const void* orig, size_t len _U_)
5485 {
5486     const lcid_drb_mapping_t *o = (const lcid_drb_mapping_t *)orig;
5487     lcid_drb_mapping_t       *d = (lcid_drb_mapping_t *)dest;
5488
5489     /* Copy all items over */
5490     d->lcid  = o->lcid;
5491     d->drbid = o->drbid;
5492     d->channel_type = o->channel_type;
5493
5494     return d;
5495 }
5496
5497
5498 /*************************************************************************/
5499 /* These functions get called from outside of this module, i.e. from RRC */
5500
5501 /* Set LCID -> RLC channel mappings from signalling protocol (i.e. RRC or similar). */
5502 void set_mac_lte_channel_mapping(drb_mapping_t *drb_mapping)
5503 {
5504     ue_dynamic_drb_mappings_t *ue_mappings;
5505     guint8 lcid = 0;
5506
5507     /* Check lcid range */
5508     if (drb_mapping->lcid_present) {
5509         lcid = drb_mapping->lcid;
5510
5511         /* Ignore if LCID is out of range */
5512         if ((lcid < 3) || (lcid > 10)) {
5513             return;
5514         }
5515     }
5516
5517     /* Look for existing UE entry */
5518     ue_mappings = (ue_dynamic_drb_mappings_t *)g_hash_table_lookup(mac_lte_ue_channels_hash,
5519                                                                    GUINT_TO_POINTER((guint)drb_mapping->ueid));
5520     if (!ue_mappings) {
5521         /* If not found, create & add to table */
5522         ue_mappings = wmem_new0(wmem_file_scope(), ue_dynamic_drb_mappings_t);
5523         g_hash_table_insert(mac_lte_ue_channels_hash,
5524                             GUINT_TO_POINTER((guint)drb_mapping->ueid),
5525                             ue_mappings);
5526     }
5527
5528     /* If lcid wasn't supplied, need to try to look up from drbid */
5529     if ((lcid == 0) && (drb_mapping->drbid < 32)) {
5530         lcid = ue_mappings->drb_to_lcid_mappings[drb_mapping->drbid];
5531     }
5532     if (lcid == 0) {
5533         /* Still no lcid - give up */
5534         return;
5535     }
5536
5537     /* Set array entry */
5538     ue_mappings->mapping[lcid].valid = TRUE;
5539     ue_mappings->mapping[lcid].drbid = drb_mapping->drbid;
5540     ue_mappings->drb_to_lcid_mappings[drb_mapping->drbid] = lcid;
5541     if (drb_mapping->ul_priority_present) {
5542         ue_mappings->mapping[lcid].ul_priority = drb_mapping->ul_priority;
5543     }
5544
5545     /* Fill in available RLC info */
5546     if (drb_mapping->rlcMode_present) {
5547         switch (drb_mapping->rlcMode) {
5548             case RLC_AM_MODE:
5549                 ue_mappings->mapping[lcid].channel_type = rlcAM;
5550                 break;
5551             case RLC_UM_MODE:
5552                 if (drb_mapping->um_sn_length_present) {
5553                     if (drb_mapping->um_sn_length == 5) {
5554                         ue_mappings->mapping[lcid].channel_type = rlcUM5;
5555                     }
5556                     else {
5557                         ue_mappings->mapping[lcid].channel_type = rlcUM10;
5558                     }
5559                     break;
5560                 }
5561
5562             default:
5563                 break;
5564         }
5565     }
5566 }
5567
5568 /* Return the configured UL priority for the channel */
5569 static guint8 get_mac_lte_channel_priority(guint16 ueid, guint8 lcid,
5570                                            guint8 direction)
5571 {
5572     ue_dynamic_drb_mappings_t *ue_mappings;
5573
5574     /* Priority only affects UL */
5575     if (direction == DIRECTION_DOWNLINK) {
5576         return 0;
5577     }
5578
5579     /* Look up the mappings for this UE */
5580     ue_mappings = (ue_dynamic_drb_mappings_t *)g_hash_table_lookup(mac_lte_ue_channels_hash, GUINT_TO_POINTER((guint)ueid));
5581     if (!ue_mappings) {
5582         return 0;
5583     }
5584
5585     /* Won't report value if channel not configured */
5586     if (!ue_mappings->mapping[lcid].valid) {
5587         return 0;
5588     }
5589     else {
5590         return ue_mappings->mapping[lcid].ul_priority;
5591     }
5592 }
5593
5594 /* Configure the DRX state for this UE (from RRC) */
5595 void set_mac_lte_drx_config(guint16 ueid, drx_config_t *drx_config, packet_info *pinfo)
5596 {
5597     if (global_mac_lte_show_drx && !pinfo->fd->flags.visited) {
5598         drx_state_t *ue_state;
5599         guint32 previousFrameNum = 0;
5600
5601         /* Find or create config/timing struct for this UE */
5602         ue_state = (drx_state_t *)g_hash_table_lookup(mac_lte_drx_ue_state, GUINT_TO_POINTER((guint)ueid));
5603         if (ue_state == NULL) {
5604             ue_state = (drx_state_t *)wmem_new(wmem_file_scope(), drx_state_t);
5605             g_hash_table_insert(mac_lte_drx_ue_state, GUINT_TO_POINTER((guint)ueid), ue_state);
5606         }
5607         else {
5608             previousFrameNum = ue_state->config.frameNum;
5609         }
5610
5611         /* Clearing state when new config comes in... */
5612         init_drx_ue_state(ue_state, TRUE);
5613
5614         /* Copy in new config */
5615         ue_state->config = *drx_config;
5616         /* Remember frame when current settings set */
5617         ue_state->config.frameNum = pinfo->fd->num;
5618         /* Also remember any previous config frame number */
5619         ue_state->config.previousFrameNum = previousFrameNum;
5620     }
5621 }
5622
5623 /* Release DRX config for this UE */
5624 void set_mac_lte_drx_config_release(guint16 ueid, packet_info *pinfo)
5625 {
5626     if (global_mac_lte_show_drx && !pinfo->fd->flags.visited) {
5627         /* Find or create config struct for table entry */
5628         drx_state_t *ue_state = (drx_state_t *)g_hash_table_lookup(mac_lte_drx_ue_state, GUINT_TO_POINTER((guint)ueid));
5629         if (ue_state != NULL) {
5630             g_hash_table_remove(mac_lte_drx_ue_state, GUINT_TO_POINTER((guint)ueid));
5631             /* TODO: free entry? */
5632         }
5633     }
5634 }
5635
5636
5637
5638
5639 /* Function to be called from outside this module (e.g. in a plugin) to get per-packet data */
5640 mac_lte_info *get_mac_lte_proto_data(packet_info *pinfo)
5641 {
5642     return (mac_lte_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_mac_lte, 0);
5643 }
5644
5645 /* Function to be called from outside this module (e.g. in a plugin) to set per-packet data */
5646 void set_mac_lte_proto_data(packet_info *pinfo, mac_lte_info *p_mac_lte_info)
5647 {
5648     p_add_proto_data(wmem_file_scope(), pinfo, proto_mac_lte, 0, p_mac_lte_info);
5649 }
5650
5651 void proto_register_mac_lte(void)
5652 {
5653     static hf_register_info hf[] =
5654     {
5655         /**********************************/
5656         /* Items for decoding context     */
5657         { &hf_mac_lte_context,
5658             { "Context",
5659               "mac-lte.context", FT_STRING, BASE_NONE, NULL, 0x0,
5660               NULL, HFILL
5661             }
5662         },
5663         { &hf_mac_lte_context_radio_type,
5664             { "Radio Type",
5665               "mac-lte.radio-type", FT_UINT8, BASE_DEC, VALS(radio_type_vals), 0x0,
5666               NULL, HFILL
5667             }
5668         },
5669         { &hf_mac_lte_context_direction,
5670             { "Direction",
5671               "mac-lte.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
5672               "Direction of message", HFILL
5673             }
5674         },
5675         { &hf_mac_lte_context_rnti,
5676             { "RNTI",
5677               "mac-lte.rnti", FT_UINT16, BASE_DEC, 0, 0x0,
5678               "RNTI associated with message", HFILL
5679             }
5680         },
5681         { &hf_mac_lte_context_rnti_type,
5682             { "RNTI Type",
5683               "mac-lte.rnti-type", FT_UINT8, BASE_DEC, VALS(rnti_type_vals), 0x0,
5684               "Type of RNTI associated with message", HFILL
5685             }
5686         },
5687         { &hf_mac_lte_context_ueid,
5688             { "UEId",
5689               "mac-lte.ueid", FT_UINT16, BASE_DEC, 0, 0x0,
5690               "User Equipment Identifier associated with message", HFILL
5691             }
5692         },
5693         { &hf_mac_lte_context_sysframe_number,
5694             { "System Frame Number",
5695               "mac-lte.sfn", FT_UINT16, BASE_DEC, 0, 0x0,
5696               "System Frame Number associated with message", HFILL
5697             }
5698         },
5699         { &hf_mac_lte_context_subframe_number,
5700             { "Subframe",
5701               "mac-lte.subframe", FT_UINT16, BASE_DEC, 0, 0x0,
5702               "Subframe number associated with message", HFILL
5703             }
5704         },
5705         { &hf_mac_lte_context_grant_subframe_number,
5706             { "Grant Subframe",
5707               "mac-lte.grant-subframe", FT_UINT16, BASE_DEC, 0, 0x0,
5708               "Subframe when grant for this PDU was received", HFILL
5709             }
5710         },
5711         { &hf_mac_lte_context_predefined_frame,
5712             { "Predefined frame",
5713               "mac-lte.is-predefined-frame", FT_UINT8, BASE_DEC, VALS(predefined_frame_vals), 0x0,
5714               "Predefined test frame (or real MAC PDU)", HFILL
5715             }
5716         },
5717         { &hf_mac_lte_context_length,
5718             { "Length of frame",
5719               "mac-lte.length", FT_UINT8, BASE_DEC, 0, 0x0,
5720               "Original length of frame (including SDUs and padding)", HFILL
5721             }
5722         },
5723         { &hf_mac_lte_context_ul_grant_size,
5724             { "Uplink grant size",
5725               "mac-lte.ul-grant-size", FT_UINT8, BASE_DEC, 0, 0x0,
5726               "Uplink grant size (in bytes)", HFILL
5727             }
5728         },
5729         { &hf_mac_lte_context_bch_transport_channel,
5730             { "Transport channel",
5731               "mac-lte.bch-transport-channel", FT_UINT8, BASE_DEC, VALS(bch_transport_channel_vals), 0x0,
5732               "Transport channel BCH data was carried on", HFILL
5733             }
5734         },
5735         { &hf_mac_lte_context_retx_count,
5736             { "ReTX count",
5737               "mac-lte.retx-count", FT_UINT8, BASE_DEC, 0, 0x0,
5738               "Number of times this PDU has been retransmitted", HFILL
5739             }
5740         },
5741         { &hf_mac_lte_context_retx_reason,
5742             { "ReTX reason",
5743               "mac-lte.retx-reason", FT_UINT8, BASE_DEC, VALS(ul_retx_grant_vals), 0x0,
5744               "Type of UL ReTx grant", HFILL
5745             }
5746         },
5747         { &hf_mac_lte_context_crc_status,
5748             { "CRC Status",
5749               "mac-lte.crc-status", FT_UINT8, BASE_DEC, VALS(crc_status_vals), 0x0,
5750               "CRC Status as reported by PHY", HFILL
5751             }
5752         },
5753         { &hf_mac_lte_context_carrier_id,
5754             { "Carrier Id",
5755               "mac-lte.carrier-id", FT_UINT8, BASE_DEC, VALS(carrier_id_vals), 0x0,
5756               NULL, HFILL
5757             }
5758         },
5759         { &hf_mac_lte_context_rapid,
5760             { "RAPID",
5761               "mac-lte.preamble-sent.rapid", FT_UINT8, BASE_DEC, 0, 0x0,
5762               "RAPID sent in RACH preamble", HFILL
5763             }
5764         },
5765         { &hf_mac_lte_context_rach_attempt_number,
5766             { "RACH Attempt Number",
5767               "mac-lte.preamble-sent.attempt", FT_UINT8, BASE_DEC, 0, 0x0,
5768               NULL, HFILL
5769             }
5770         },
5771
5772         { &hf_mac_lte_ues_ul_per_tti,
5773             { "UL UE in TTI",
5774               "mac-lte.ul-tti-count", FT_UINT8, BASE_DEC, 0, 0x0,
5775               "In this TTI, this is the nth UL grant", HFILL
5776             }
5777         },
5778         { &hf_mac_lte_ues_dl_per_tti,
5779             { "DL UE in TTI",
5780               "mac-lte.dl-tti-count", FT_UINT8, BASE_DEC, 0, 0x0,
5781               "In this TTI, this is the nth DL PDU", HFILL
5782             }
5783         },
5784
5785
5786         /* Extra PHY context */
5787         { &hf_mac_lte_context_phy_ul,
5788             { "UL PHY attributes",
5789               "mac-lte.ul-phy", FT_STRING, BASE_NONE, 0, 0x0,
5790               NULL, HFILL
5791             }
5792         },
5793         { &hf_mac_lte_context_phy_ul_modulation_type,
5794             { "Modulation type",
5795               "mac-lte.ul-phy.modulation-type", FT_UINT8, BASE_DEC, VALS(modulation_type_vals), 0x0,
5796               NULL, HFILL
5797             }
5798         },
5799         { &hf_mac_lte_context_phy_ul_tbs_index,
5800             { "TBs Index",
5801               "mac-lte.ul-phy.tbs-index", FT_UINT8, BASE_DEC, 0, 0x0,
5802               NULL, HFILL
5803             }
5804         },
5805         { &hf_mac_lte_context_phy_ul_resource_block_length,
5806             { "Resource Block Length",
5807               "mac-lte.ul-phy.resource-block-length", FT_UINT8, BASE_DEC, 0, 0x0,
5808               NULL, HFILL
5809             }
5810         },
5811         { &hf_mac_lte_context_phy_ul_resource_block_start,
5812             { "Resource Block Start",
5813               "mac-lte.ul-phy.resource-block-start", FT_UINT8, BASE_DEC, 0, 0x0,
5814               NULL, HFILL
5815             }
5816         },
5817         { &hf_mac_lte_context_phy_ul_harq_id,
5818             { "HARQ Id",
5819               "mac-lte.ul-phy.harq-id", FT_UINT8, BASE_DEC, 0, 0x0,
5820               NULL, HFILL
5821             }
5822         },
5823         { &hf_mac_lte_context_phy_ul_ndi,
5824             { "NDI",
5825               "mac-lte.ul-phy.ndi", FT_UINT8, BASE_DEC, 0, 0x0,
5826               "UL New Data Indicator", HFILL
5827             }
5828         },
5829
5830         { &hf_mac_lte_context_phy_dl,
5831             { "DL PHY attributes",
5832               "mac-lte.dl-phy", FT_STRING, BASE_NONE, 0, 0x0,
5833               NULL, HFILL
5834             }
5835         },
5836         { &hf_mac_lte_context_phy_dl_dci_format,
5837             { "DCI format",
5838               "mac-lte.dl-phy.dci-format", FT_UINT8, BASE_DEC, VALS(dci_format_vals), 0x0,
5839               NULL, HFILL
5840             }
5841         },
5842         { &hf_mac_lte_context_phy_dl_resource_allocation_type,
5843             { "Resource Allocation Type",
5844               "mac-lte.dl-phy.resource-allocation-type", FT_UINT8, BASE_DEC, 0, 0x0,
5845               NULL, HFILL
5846             }
5847         },
5848         { &hf_mac_lte_context_phy_dl_aggregation_level,
5849             { "Aggregation Level",
5850               "mac-lte.dl-phy.aggregation-level", FT_UINT8, BASE_DEC, VALS(aggregation_level_vals), 0x0,
5851               NULL, HFILL
5852             }
5853         },
5854         { &hf_mac_lte_context_phy_dl_mcs_index,
5855             { "MCS Index",
5856               "mac-lte.dl-phy.mcs-index", FT_UINT8, BASE_DEC, 0, 0x0,
5857               NULL, HFILL
5858             }
5859         },
5860         { &hf_mac_lte_context_phy_dl_redundancy_version_index,
5861             { "RV Index",
5862               "mac-lte.dl-phy.rv-index", FT_UINT8, BASE_DEC, 0, 0x0,
5863               NULL, HFILL
5864             }
5865         },
5866         { &hf_mac_lte_context_phy_dl_retx,
5867             { "DL Retx",
5868               "mac-lte.dl-phy.dl-retx", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
5869               NULL, HFILL
5870             }
5871         },
5872         { &hf_mac_lte_context_phy_dl_resource_block_length,
5873             { "RB Length",
5874               "mac-lte.dl-phy.rb-length", FT_UINT8, BASE_DEC, 0, 0x0,
5875               NULL, HFILL
5876             }
5877         },
5878         { &hf_mac_lte_context_phy_dl_harq_id,
5879             { "HARQ Id",
5880               "mac-lte.dl-phy.harq-id", FT_UINT8, BASE_DEC, 0, 0x0,
5881               NULL, HFILL
5882             }
5883         },
5884         { &hf_mac_lte_context_phy_dl_ndi,
5885             { "NDI",
5886               "mac-lte.dl-phy.ndi", FT_UINT8, BASE_DEC, 0, 0x0,
5887               "New Data Indicator", HFILL
5888             }
5889         },
5890         { &hf_mac_lte_context_phy_dl_tb,
5891             { "TB",
5892               "mac-lte.dl-phy.tb", FT_UINT8, BASE_DEC, 0, 0x0,
5893               "Transport Block (antenna #)", HFILL
5894             }
5895         },
5896
5897         /* Out-of-band events */
5898         { &hf_mac_lte_oob_send_preamble,
5899             { "PRACH",
5900               "mac-lte.preamble-sent", FT_STRING, BASE_NONE, NULL, 0x0,
5901               NULL, HFILL
5902             }
5903         },
5904         { &hf_mac_lte_number_of_srs,
5905             { "Number of SRs",
5906               "mac-lte.sr-req.count", FT_UINT32, BASE_DEC, 0, 0x0,
5907               "Number of UEs doing SR in this frame", HFILL
5908             }
5909         },
5910
5911         /*******************************************/
5912         /* MAC shared channel header fields        */
5913         { &hf_mac_lte_ulsch,
5914             { "UL-SCH",
5915               "mac-lte.ulsch", FT_STRING, BASE_NONE, NULL, 0x0,
5916               NULL, HFILL
5917             }
5918         },
5919         { &hf_mac_lte_ulsch_header,
5920             { "UL-SCH Header",
5921               "mac-lte.ulsch.header", FT_STRING, BASE_NONE, NULL, 0x0,
5922               NULL, HFILL
5923             }
5924         },
5925         { &hf_mac_lte_dlsch_header,
5926             { "DL-SCH Header",
5927               "mac-lte.dlsch.header", FT_STRING, BASE_NONE, NULL, 0x0,
5928               NULL, HFILL
5929             }
5930         },
5931         { &hf_mac_lte_dlsch,
5932             { "DL-SCH",
5933               "mac-lte.dlsch", FT_STRING, BASE_NONE, NULL, 0x0,
5934               NULL, HFILL
5935             }
5936         },
5937         { &hf_mac_lte_sch_subheader,
5938             { "SCH sub-header",
5939               "mac-lte.sch.subheader", FT_STRING, BASE_NONE, NULL, 0x0,
5940               NULL, HFILL
5941             }
5942         },
5943         { &hf_mac_lte_mch,
5944             { "MCH",
5945               "mac-lte.mch", FT_STRING, BASE_NONE, NULL, 0x0,
5946               NULL, HFILL
5947             }
5948         },
5949         { &hf_mac_lte_mch_header,
5950             { "MCH Header",
5951               "mac-lte.mch.header", FT_STRING, BASE_NONE, NULL, 0x0,
5952               NULL, HFILL
5953             }
5954         },
5955         { &hf_mac_lte_mch_subheader,
5956             { "MCH sub-header",
5957               "mac-lte.mch.subheader", FT_STRING, BASE_NONE, NULL, 0x0,
5958               NULL, HFILL
5959             }
5960         },
5961         { &hf_mac_lte_sch_reserved,
5962             { "SCH reserved bits",
5963               "mac-lte.sch.reserved", FT_UINT8, BASE_HEX, NULL, 0xc0,
5964               NULL, HFILL
5965             }
5966         },
5967         { &hf_mac_lte_sch_extended,
5968             { "Extension",
5969               "mac-lte.sch.extended", FT_UINT8, BASE_HEX, 0, 0x20,
5970               "Extension - i.e. further headers after this one", HFILL
5971             }
5972         },
5973         { &hf_mac_lte_dlsch_lcid,
5974             { "LCID",
5975               "mac-lte.dlsch.lcid", FT_UINT8, BASE_HEX, VALS(dlsch_lcid_vals), 0x1f,
5976               "DL-SCH Logical Channel Identifier", HFILL
5977             }
5978         },
5979         { &hf_mac_lte_ulsch_lcid,
5980             { "LCID",
5981               "mac-lte.ulsch.lcid", FT_UINT8, BASE_HEX, VALS(ulsch_lcid_vals), 0x1f,
5982               "UL-SCH Logical Channel Identifier", HFILL
5983             }
5984         },
5985         { &hf_mac_lte_sch_format,
5986             { "Format",
5987               "mac-lte.sch.format", FT_UINT8, BASE_HEX, VALS(format_vals), 0x80,
5988               NULL, HFILL
5989             }
5990         },
5991         { &hf_mac_lte_sch_length,
5992             { "Length",
5993               "mac-lte.sch.length", FT_UINT16, BASE_DEC, 0, 0x0,
5994               "Length of MAC SDU or MAC control element", HFILL
5995             }
5996         },
5997         { &hf_mac_lte_mch_reserved,
5998             { "MCH reserved bits",
5999               "mac-lte.mch.reserved", FT_UINT8, BASE_HEX, NULL, 0xc0,
6000               NULL, HFILL
6001             }
6002         },
6003         { &hf_mac_lte_mch_extended,
6004             { "Extension",
6005               "mac-lte.mch.extended", FT_UINT8, BASE_HEX, 0, 0x20,
6006               "Extension - i.e. further headers after this one", HFILL
6007             }
6008         },
6009         { &hf_mac_lte_mch_lcid,
6010             { "LCID",
6011               "mac-lte.mch.lcid", FT_UINT8, BASE_HEX, VALS(mch_lcid_vals), 0x1f,
6012               "MCH Logical Channel Identifier", HFILL
6013             }
6014         },
6015         { &hf_mac_lte_mch_format,
6016             { "Format",
6017               "mac-lte.mch.format", FT_UINT8, BASE_HEX, VALS(format_vals), 0x80,
6018               NULL, HFILL
6019             }
6020         },
6021         { &hf_mac_lte_mch_length,
6022             { "Length",
6023               "mac-lte.mch.length", FT_UINT16, BASE_DEC, 0, 0x0,
6024               "Length of MAC SDU or MAC control element", HFILL
6025             }
6026         },
6027         { &hf_mac_lte_sch_header_only,
6028             { "MAC PDU Header only",
6029               "mac-lte.sch.header-only", FT_UINT8, BASE_DEC, VALS(header_only_vals), 0x0,
6030               NULL, HFILL
6031             }
6032         },
6033         { &hf_mac_lte_mch_header_only,
6034             { "MAC PDU Header only",
6035               "mac-lte.mch.header-only", FT_UINT8, BASE_DEC, VALS(header_only_vals), 0x0,
6036               NULL, HFILL
6037             }
6038         },
6039
6040         /********************************/
6041         /* Data                         */
6042         { &hf_mac_lte_sch_sdu,
6043             { "SDU",
6044               "mac-lte.sch.sdu", FT_BYTES, BASE_NONE, 0, 0x0,
6045               "Shared channel SDU", HFILL
6046             }
6047         },
6048         { &hf_mac_lte_mch_sdu,
6049             { "SDU",
6050               "mac-lte.mch.sdu", FT_BYTES, BASE_NONE, 0, 0x0,
6051               "Multicast channel SDU", HFILL
6052             }
6053         },
6054         { &hf_mac_lte_bch_pdu,
6055             { "BCH PDU",
6056               "mac-lte.bch.pdu", FT_BYTES, BASE_NONE, 0, 0x0,
6057               NULL, HFILL
6058             }
6059         },
6060         { &hf_mac_lte_pch_pdu,
6061             { "PCH PDU",
6062               "mac-lte.pch.pdu", FT_BYTES, BASE_NONE, 0, 0x0,
6063               NULL, HFILL
6064             }
6065         },
6066         { &hf_mac_lte_predefined_pdu,
6067             { "Predefined data",
6068               "mac-lte.predefined-data", FT_BYTES, BASE_NONE, 0, 0x0,
6069               "Predefined test data", HFILL
6070             }
6071         },
6072         { &hf_mac_lte_raw_pdu,
6073             { "Raw data",
6074               "mac-lte.raw-data", FT_BYTES, BASE_NONE, 0, 0x0,
6075               "Raw bytes of PDU (e.g. if CRC error)", HFILL
6076             }
6077         },
6078         { &hf_mac_lte_padding_data,
6079             { "Padding data",
6080               "mac-lte.padding-data", FT_BYTES, BASE_NONE, 0, 0x0,
6081               NULL, HFILL
6082             }
6083         },
6084         { &hf_mac_lte_padding_length,
6085             { "Padding length",
6086               "mac-lte.padding-length", FT_INT32, BASE_DEC, 0, 0x0,
6087               "Length of padding data not included at end of frame", HFILL
6088             }
6089         },
6090
6091
6092
6093         /*********************************/
6094         /* RAR fields                    */
6095         { &hf_mac_lte_rar,
6096             { "RAR",
6097               "mac-lte.rar", FT_NONE, BASE_NONE, NULL, 0x0,
6098               NULL, HFILL
6099             }
6100         },
6101         { &hf_mac_lte_rar_headers,
6102             { "RAR Headers",
6103               "mac-lte.rar.headers", FT_STRING, BASE_NONE, NULL, 0x0,
6104               NULL, HFILL
6105             }
6106         },
6107         { &hf_mac_lte_rar_header,
6108             { "RAR Header",
6109               "mac-lte.rar.header", FT_STRING, BASE_NONE, NULL, 0x0,
6110               NULL, HFILL
6111             }
6112         },
6113         { &hf_mac_lte_rar_extension,
6114             { "Extension",
6115               "mac-lte.rar.e", FT_UINT8, BASE_HEX, 0, 0x80,
6116               "Extension - i.e. further RAR headers after this one", HFILL
6117             }
6118         },
6119         { &hf_mac_lte_rar_t,
6120             { "Type",
6121               "mac-lte.rar.t", FT_UINT8, BASE_HEX, VALS(rar_type_vals), 0x40,
6122               "Type field indicating whether the payload is RAPID or BI", HFILL
6123             }
6124         },
6125         { &hf_mac_lte_rar_bi,
6126             { "BI",
6127               "mac-lte.rar.bi", FT_UINT8, BASE_HEX, VALS(rar_bi_vals), 0x0f,
6128               "Backoff Indicator (ms)", HFILL
6129             }
6130         },
6131         { &hf_mac_lte_rar_rapid,
6132             { "RAPID",
6133               "mac-lte.rar.rapid", FT_UINT8, BASE_HEX_DEC, 0, 0x3f,
6134               "Random Access Preamble IDentifier", HFILL
6135             }
6136         },
6137         { &hf_mac_lte_rar_no_of_rapids,
6138             { "Number of RAPIDs",
6139               "mac-lte.rar.no-of-rapids", FT_UINT8, BASE_DEC, 0, 0x0,
6140               "Number of RAPIDs in RAR PDU", HFILL
6141             }
6142         },
6143         { &hf_mac_lte_rar_reserved,
6144             { "Reserved",
6145               "mac-lte.rar.reserved", FT_UINT8, BASE_HEX, 0, 0x30,
6146               "Reserved bits in RAR header - should be 0", HFILL
6147             }
6148         },
6149
6150         { &hf_mac_lte_rar_body,
6151             { "RAR Body",
6152               "mac-lte.rar.body", FT_STRING, BASE_NONE, NULL, 0x0,
6153               NULL, HFILL
6154             }
6155         },
6156         { &hf_mac_lte_rar_reserved2,
6157             { "Reserved",
6158               "mac-lte.rar.reserved2", FT_UINT8, BASE_HEX, 0, 0x80,
6159               "Reserved bit in RAR body - should be 0", HFILL
6160             }
6161         },
6162         { &hf_mac_lte_rar_ta,
6163             { "Timing Advance",
6164               "mac-lte.rar.ta", FT_UINT16, BASE_DEC, 0, 0x7ff0,
6165               "Required adjustment to uplink transmission timing", HFILL
6166             }
6167         },
6168         { &hf_mac_lte_rar_ul_grant,
6169             { "UL Grant",
6170               "mac-lte.rar.ul-grant", FT_UINT24, BASE_DEC, 0, 0x0fffff,
6171               "Size of UL Grant", HFILL
6172             }
6173         },
6174         { &hf_mac_lte_rar_ul_grant_hopping,
6175             { "Hopping Flag",
6176               "mac-lte.rar.ul-grant.hopping", FT_UINT8, BASE_DEC, 0, 0x08,
6177               NULL, HFILL
6178             }
6179         },
6180         { &hf_mac_lte_rar_ul_grant_fsrba,
6181             { "Fixed sized resource block assignment",
6182               "mac-lte.rar.ul-grant.fsrba", FT_UINT16, BASE_DEC, 0, 0x07fe,
6183               NULL, HFILL
6184             }
6185         },
6186         { &hf_mac_lte_rar_ul_grant_tmcs,
6187             { "Truncated Modulation and coding scheme",
6188               "mac-lte.rar.ul-grant.tmcs", FT_UINT16, BASE_DEC, 0, 0x01e0,
6189               NULL, HFILL
6190             }
6191         },
6192         { &hf_mac_lte_rar_ul_grant_tcsp,
6193             { "TPC command for scheduled PUSCH",
6194               "mac-lte.rar.ul-grant.tcsp", FT_UINT8, BASE_DEC, 0, 0x01c,
6195               NULL, HFILL
6196             }
6197         },
6198         { &hf_mac_lte_rar_ul_grant_ul_delay,
6199             { "UL Delay",
6200               "mac-lte.rar.ul-grant.ul-delay", FT_UINT8, BASE_DEC, 0, 0x02,
6201               NULL, HFILL
6202             }
6203         },
6204         { &hf_mac_lte_rar_ul_grant_cqi_request,
6205             { "CQI Request",
6206               "mac-lte.rar.ul-grant.cqi-request", FT_UINT8, BASE_DEC, 0, 0x01,
6207               NULL, HFILL
6208             }
6209         },
6210         { &hf_mac_lte_rar_temporary_crnti,
6211             { "Temporary C-RNTI",
6212               "mac-lte.rar.temporary-crnti", FT_UINT16, BASE_DEC, 0, 0x0,
6213               NULL, HFILL
6214             }
6215         },
6216
6217         /**********************/
6218         /* Control PDU fields */
6219         { &hf_mac_lte_control_bsr,
6220             { "BSR",
6221               "mac-lte.control.bsr", FT_STRING, BASE_NONE, 0, 0x0,
6222               "Buffer Status Report", HFILL
6223             }
6224         },
6225         { &hf_mac_lte_control_bsr_lcg_id,
6226             { "Logical Channel Group ID",
6227               "mac-lte.control.bsr.lcg-id", FT_UINT8, BASE_DEC, 0, 0xc0,
6228               NULL, HFILL
6229             }
6230         },
6231         { &hf_mac_lte_control_short_bsr_buffer_size,
6232             { "Buffer Size",
6233               "mac-lte.control.bsr.buffer-size", FT_UINT8, BASE_DEC|BASE_EXT_STRING, &buffer_size_vals_ext, 0x3f,
6234               "Buffer Size available in all channels in group", HFILL
6235             }
6236         },
6237         { &hf_mac_lte_control_long_bsr_buffer_size_0,
6238             { "Buffer Size 0",
6239               "mac-lte.control.bsr.buffer-size-0", FT_UINT8, BASE_DEC|BASE_EXT_STRING, &buffer_size_vals_ext, 0xfc,
6240               "Buffer Size available in logical channel group 0", HFILL
6241             }
6242         },
6243         { &hf_mac_lte_control_long_bsr_buffer_size_1,
6244             { "Buffer Size 1",
6245               "mac-lte.control.bsr.buffer-size-1", FT_UINT16, BASE_DEC|BASE_EXT_STRING, &buffer_size_vals_ext, 0x03f0,
6246               "Buffer Size available in logical channel group 1", HFILL
6247             }
6248         },
6249         { &hf_mac_lte_control_long_bsr_buffer_size_2,
6250             { "Buffer Size 2",
6251               "mac-lte.control.bsr.buffer-size-2", FT_UINT16, BASE_DEC|BASE_EXT_STRING, &buffer_size_vals_ext, 0x0fc0,
6252               "Buffer Size available in logical channel group 2", HFILL
6253             }
6254         },
6255         { &hf_mac_lte_control_long_bsr_buffer_size_3,
6256             { "Buffer Size 3",
6257               "mac-lte.control.bsr.buffer-size-3", FT_UINT8, BASE_DEC|BASE_EXT_STRING, &buffer_size_vals_ext, 0x3f,
6258               "Buffer Size available in logical channel group 3", HFILL
6259             }
6260         },
6261         { &hf_mac_lte_control_short_ext_bsr_buffer_size,
6262             { "Buffer Size",
6263               "mac-lte.control.bsr.buffer-size", FT_UINT8, BASE_DEC|BASE_EXT_STRING, &ext_buffer_size_vals_ext, 0x3f,
6264               "Buffer Size available in all channels in group", HFILL
6265             }
6266         },
6267         { &hf_mac_lte_control_long_ext_bsr_buffer_size_0,
6268             { "Buffer Size 0",
6269               "mac-lte.control.bsr.buffer-size-0", FT_UINT8, BASE_DEC|BASE_EXT_STRING, &ext_buffer_size_vals_ext, 0xfc,
6270               "Buffer Size available in logical channel group 0", HFILL
6271             }
6272         },
6273         { &hf_mac_lte_control_long_ext_bsr_buffer_size_1,
6274             { "Buffer Size 1",
6275               "mac-lte.control.bsr.buffer-size-1", FT_UINT16, BASE_DEC|BASE_EXT_STRING, &ext_buffer_size_vals_ext, 0x03f0,
6276               "Buffer Size available in logical channel group 1", HFILL
6277             }
6278         },
6279         { &hf_mac_lte_control_long_ext_bsr_buffer_size_2,
6280             { "Buffer Size 2",
6281               "mac-lte.control.bsr.buffer-size-2", FT_UINT16, BASE_DEC|BASE_EXT_STRING, &ext_buffer_size_vals_ext, 0x0fc0,
6282               "Buffer Size available in logical channel group 2", HFILL
6283             }
6284         },
6285         { &hf_mac_lte_control_long_ext_bsr_buffer_size_3,
6286             { "Buffer Size 3",
6287               "mac-lte.control.bsr.buffer-size-3", FT_UINT8, BASE_DEC|BASE_EXT_STRING, &ext_buffer_size_vals_ext, 0x3f,
6288               "Buffer Size available in logical channel group 3", HFILL
6289             }
6290         },
6291         { &hf_mac_lte_control_crnti,
6292             { "C-RNTI",
6293               "mac-lte.control.crnti", FT_UINT16, BASE_DEC, 0, 0x0,
6294               "C-RNTI for the UE", HFILL
6295             }
6296         },
6297         { &hf_mac_lte_control_timing_advance,
6298             { "Timing Advance",
6299               "mac-lte.control.timing-advance", FT_STRING, BASE_NONE, 0, 0x0,
6300               NULL, HFILL
6301             }
6302         },
6303         { &hf_mac_lte_control_timing_advance_group_id,
6304             { "Timing Advance Group Identity",
6305               "mac-lte.control.timing-advance.group-id", FT_UINT8, BASE_DEC, 0, 0xc0,
6306               NULL, HFILL
6307             }
6308         },
6309         { &hf_mac_lte_control_timing_advance_command,
6310             { "Timing Advance Command",
6311               "mac-lte.control.timing-advance.command", FT_UINT8, BASE_DEC, 0, 0x3f,
6312               "Timing Advance (0-63 - see 36.213, 4.2.3)", HFILL
6313             }
6314         },
6315         { &hf_mac_lte_control_ue_contention_resolution,
6316             { "UE Contention Resolution",
6317               "mac-lte.control.ue-contention-resolution", FT_STRING, BASE_NONE, 0, 0x0,
6318               NULL, HFILL
6319             }
6320         },
6321         { &hf_mac_lte_control_ue_contention_resolution_identity,
6322             { "UE Contention Resolution Identity",
6323               "mac-lte.control.ue-contention-resolution.identity", FT_BYTES, BASE_NONE, 0, 0x0,
6324               NULL, HFILL
6325             }
6326         },
6327         { &hf_mac_lte_control_ue_contention_resolution_msg3,
6328             { "Msg3",
6329               "mac-lte.control.ue-contention-resolution.msg3", FT_FRAMENUM, BASE_NONE, 0, 0x0,
6330               NULL, HFILL
6331             }
6332         },
6333         { &hf_mac_lte_control_ue_contention_resolution_msg3_matched,
6334             { "UE Contention Resolution Matches Msg3",
6335               "mac-lte.control.ue-contention-resolution.matches-msg3", FT_BOOLEAN, BASE_NONE, 0, 0x0,
6336               NULL, HFILL
6337             }
6338         },
6339         { &hf_mac_lte_control_ue_contention_resolution_time_since_msg3,
6340             { "Time since Msg3",
6341               "mac-lte.control.ue-contention-resolution.time-since-msg3", FT_UINT32, BASE_DEC, 0, 0x0,
6342               "Time in ms since corresponding Msg3", HFILL
6343             }
6344         },
6345
6346         { &hf_mac_lte_control_power_headroom,
6347             { "Power Headroom",
6348               "mac-lte.control.power-headroom", FT_STRING, BASE_NONE, 0, 0x0,
6349               NULL, HFILL
6350             }
6351         },
6352         { &hf_mac_lte_control_power_headroom_reserved,
6353             { "Reserved",
6354               "mac-lte.control.power-headroom.reserved", FT_UINT8, BASE_DEC, 0, 0xc0,
6355               "Reserved bits, should be 0", HFILL
6356             }
6357         },
6358         { &hf_mac_lte_control_power_headroom_level,
6359             { "Power Headroom Level",
6360               "mac-lte.control.power-headroom.level", FT_UINT8, BASE_DEC|BASE_EXT_STRING,
6361                &power_headroom_vals_ext, 0x3f, "Power Headroom Level in dB", HFILL
6362             }
6363         },
6364
6365         { &hf_mac_lte_control_ext_power_headroom,
6366             { "Extended Power Headroom",
6367               "mac-lte.control.ext-power-headroom", FT_STRING, BASE_NONE,
6368               0, 0x0, NULL, HFILL
6369             }
6370         },
6371         { &hf_mac_lte_control_ext_power_headroom_c7,
6372             { "SCell Index 7 Power Headroom",
6373               "mac-lte.control.ext-power-headroom.c7", FT_BOOLEAN, 8,
6374               TFS(&mac_lte_scell_ph_vals), 0x80, NULL, HFILL
6375             }
6376         },
6377         { &hf_mac_lte_control_ext_power_headroom_c6,
6378             { "SCell Index 6 Power Headroom",
6379               "mac-lte.control.ext-power-headroom.c6", FT_BOOLEAN, 8,
6380               TFS(&mac_lte_scell_ph_vals), 0x40, NULL, HFILL
6381             }
6382         },
6383         { &hf_mac_lte_control_ext_power_headroom_c5,
6384             { "SCell Index 5 Power Headroom",
6385               "mac-lte.control.ext-power-headroom.c5", FT_BOOLEAN, 8,
6386               TFS(&mac_lte_scell_ph_vals), 0x20, NULL, HFILL
6387             }
6388         },
6389         { &hf_mac_lte_control_ext_power_headroom_c4,
6390             { "SCell Index 4 Power Headroom",
6391               "mac-lte.control.ext-power-headroom.c4", FT_BOOLEAN, 8,
6392               TFS(&mac_lte_scell_ph_vals), 0x10, NULL, HFILL
6393             }
6394         },
6395         { &hf_mac_lte_control_ext_power_headroom_c3,
6396             { "SCell Index 3 Power Headroom",
6397               "mac-lte.control.ext-power-headroom.c3", FT_BOOLEAN, 8,
6398               TFS(&mac_lte_scell_ph_vals), 0x08, NULL, HFILL
6399             }
6400         },
6401         { &hf_mac_lte_control_ext_power_headroom_c2,
6402             { "SCell Index 2 Power Headroom",
6403               "mac-lte.control.ext-power-headroom.c2", FT_BOOLEAN, 8,
6404               TFS(&mac_lte_scell_ph_vals), 0x04, NULL, HFILL
6405             }
6406         },
6407         { &hf_mac_lte_control_ext_power_headroom_c1,
6408             { "SCell Index 1 Power Headroom",
6409               "mac-lte.control.ext-power-headroom.c1", FT_BOOLEAN, 8,
6410               TFS(&mac_lte_scell_ph_vals), 0x02, NULL, HFILL
6411             }
6412         },
6413         { &hf_mac_lte_control_ext_power_headroom_reserved,
6414             { "Reserved",
6415               "mac-lte.control.ext-power-headroom.reserved", FT_UINT8, BASE_DEC,
6416               0, 0x01, "Reserved bit, should be 0", HFILL
6417             }
6418         },
6419         { &hf_mac_lte_control_ext_power_headroom_power_backoff,
6420             { "Power Backoff",
6421               "mac-lte.control.ext-power-headroom.power-backoff", FT_BOOLEAN, 8,
6422                TFS(&mac_lte_power_backoff_vals), 0x80, NULL, HFILL
6423             }
6424         },
6425         { &hf_mac_lte_control_ext_power_headroom_value,
6426             { "Power Headroom Value",
6427               "mac-lte.control.ext-power-headroom.power-headroom-value", FT_BOOLEAN, 8,
6428                TFS(&mac_lte_ph_value_vals), 0x40, NULL, HFILL
6429             }
6430         },
6431         { &hf_mac_lte_control_ext_power_headroom_level,
6432             { "Power Headroom Level",
6433               "mac-lte.control.ext-power-headroom.level", FT_UINT8, BASE_DEC|BASE_EXT_STRING,
6434                &power_headroom_vals_ext, 0x3f, "Power Headroom Level in dB", HFILL
6435             }
6436         },
6437         { &hf_mac_lte_control_ext_power_headroom_reserved2,
6438             { "Reserved",
6439               "mac-lte.control.ext-power-headroom.reserved2", FT_UINT8, BASE_DEC,
6440               0, 0xc0, "Reserved bits, should be 0", HFILL
6441             }
6442         },
6443         { &hf_mac_lte_control_ext_power_headroom_pcmaxc,
6444             { "Configured UE Transmit Power",
6445               "mac-lte.control.ext-power-headroom.pcmaxc", FT_UINT8, BASE_DEC|BASE_EXT_STRING,
6446                &pcmaxc_vals_ext, 0x3f, "Pcmax,c in dBm", HFILL
6447             }
6448         },
6449
6450         { &hf_mac_lte_control_activation_deactivation,
6451             { "Activation/Deactivation",
6452               "mac-lte.control.activation-deactivation", FT_STRING, BASE_NONE,
6453               0, 0x0, NULL, HFILL
6454             }
6455         },
6456         { &hf_mac_lte_control_activation_deactivation_c7,
6457             { "SCell Index 7 Status",
6458               "mac-lte.control.activation-deactivation.c7", FT_BOOLEAN, 8,
6459               TFS(&mac_lte_scell_status_vals), 0x80, NULL, HFILL
6460             }
6461         },
6462         { &hf_mac_lte_control_activation_deactivation_c6,
6463             { "SCell Index 6 Status",
6464               "mac-lte.control.activation-deactivation.c6", FT_BOOLEAN, 8,
6465               TFS(&mac_lte_scell_status_vals), 0x40, NULL, HFILL
6466             }
6467         },
6468         { &hf_mac_lte_control_activation_deactivation_c5,
6469             { "SCell Index 5 Status",
6470               "mac-lte.control.activation-deactivation.c5", FT_BOOLEAN, 8,
6471               TFS(&mac_lte_scell_status_vals), 0x20, NULL, HFILL
6472             }
6473         },
6474         { &hf_mac_lte_control_activation_deactivation_c4,
6475             { "SCell Index 4 Status",
6476               "mac-lte.control.activation-deactivation.c4", FT_BOOLEAN, 8,
6477               TFS(&mac_lte_scell_status_vals), 0x10, NULL, HFILL
6478             }
6479         },
6480         { &hf_mac_lte_control_activation_deactivation_c3,
6481             { "SCell Index 3 Status",
6482               "mac-lte.control.activation-deactivation.c3", FT_BOOLEAN, 8,
6483               TFS(&mac_lte_scell_status_vals), 0x08, NULL, HFILL
6484             }
6485         },
6486         { &hf_mac_lte_control_activation_deactivation_c2,
6487             { "SCell Index 2 Status",
6488               "mac-lte.control.activation-deactivation.c2", FT_BOOLEAN, 8,
6489               TFS(&mac_lte_scell_status_vals), 0x04, NULL, HFILL
6490             }
6491         },
6492         { &hf_mac_lte_control_activation_deactivation_c1,
6493             { "SCell Index 1 Status",
6494               "mac-lte.control.activation-deactivation.c1", FT_BOOLEAN, 8,
6495               TFS(&mac_lte_scell_status_vals), 0x02, NULL, HFILL
6496             }
6497         },
6498         { &hf_mac_lte_control_activation_deactivation_reserved,
6499             { "Reserved",
6500               "mac-lte.control.activation-deactivation.reserved", FT_UINT8, BASE_DEC,
6501               0, 0x01, "Reserved bit, should be 0", HFILL
6502             }
6503         },
6504
6505         { &hf_mac_lte_control_mch_scheduling_info,
6506             { "MCH Scheduling Information",
6507               "mac-lte.control.mch_scheduling_info", FT_STRING, BASE_NONE, 0, 0x0,
6508               NULL, HFILL
6509             }
6510         },
6511         { &hf_mac_lte_control_mch_scheduling_info_lcid,
6512             { "LCID",
6513               "mac-lte.control.mch_scheduling_info.lcid", FT_UINT8, BASE_HEX, VALS(mch_lcid_vals), 0xf8,
6514               "Logical Channel ID of the MTCH", HFILL
6515             }
6516         },
6517         { &hf_mac_lte_control_mch_scheduling_info_stop_mtch,
6518             { "Stop MTCH",
6519               "mac-lte.control.mch_scheduling_info.stop_mtch", FT_UINT16, BASE_DEC, 0, 0x07ff,
6520               "Ordinal number of the subframe where the corresponding MTCH stops", HFILL
6521             }
6522         },
6523
6524         /* Generated fields */
6525         { &hf_mac_lte_dl_harq_resend_original_frame,
6526             { "Frame with previous tx",
6527               "mac-lte.dlsch.retx.original-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
6528               NULL, HFILL
6529             }
6530         },
6531         { &hf_mac_lte_dl_harq_resend_time_since_previous_frame,
6532             { "Time since previous tx (ms)",
6533               "mac-lte.dlsch.retx.time-since-previous", FT_UINT16, BASE_DEC, 0, 0x0,
6534               NULL, HFILL
6535             }
6536         },
6537         { &hf_mac_lte_dl_harq_resend_next_frame,
6538             { "Frame with next tx",
6539               "mac-lte.dlsch.retx.next-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
6540               NULL, HFILL
6541             }
6542         },
6543         { &hf_mac_lte_dl_harq_resend_time_until_next_frame,
6544             { "Time until next tx (ms)",
6545               "mac-lte.dlsch.retx.time-until-next", FT_UINT16, BASE_DEC, 0, 0x0,
6546               NULL, HFILL
6547             }
6548         },
6549
6550         { &hf_mac_lte_ul_harq_resend_original_frame,
6551             { "Frame with previous tx",
6552               "mac-lte.ulsch.retx.original-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
6553               NULL, HFILL
6554             }
6555         },
6556         { &hf_mac_lte_ul_harq_resend_time_since_previous_frame,
6557             { "Time since previous tx (ms)",
6558               "mac-lte.ulsch.retx.time-since-previous", FT_UINT16, BASE_DEC, 0, 0x0,
6559               NULL, HFILL
6560             }
6561         },
6562         { &hf_mac_lte_ul_harq_resend_next_frame,
6563             { "Frame with next tx",
6564               "mac-lte.ulsch.retx.next-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
6565               NULL, HFILL
6566             }
6567         },
6568         { &hf_mac_lte_ul_harq_resend_time_until_next_frame,
6569             { "Time until next tx (ms)",
6570               "mac-lte.ulsch.retx.time-until-next", FT_UINT16, BASE_DEC, 0, 0x0,
6571               NULL, HFILL
6572             }
6573         },
6574
6575         { &hf_mac_lte_grant_answering_sr,
6576             { "First Grant Following SR from",
6577               "mac-lte.ulsch.grant-answering-sr", FT_FRAMENUM, BASE_NONE, 0, 0x0,
6578               NULL, HFILL
6579             }
6580         },
6581         { &hf_mac_lte_failure_answering_sr,
6582             { "SR which failed",
6583               "mac-lte.ulsch.failure-answering-sr", FT_FRAMENUM, BASE_NONE, 0, 0x0,
6584               NULL, HFILL
6585             }
6586         },
6587         { &hf_mac_lte_sr_leading_to_failure,
6588             { "This SR fails",
6589               "mac-lte.ulsch.failure-answering-sr-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
6590               NULL, HFILL
6591             }
6592         },
6593         { &hf_mac_lte_sr_leading_to_grant,
6594             { "This SR results in a grant here",
6595               "mac-lte.ulsch.grant-answering-sr-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
6596               NULL, HFILL
6597             }
6598         },
6599         { &hf_mac_lte_sr_time_since_request,
6600             { "Time since SR (ms)",
6601               "mac-lte.ulsch.time-since-sr", FT_UINT32, BASE_DEC, 0, 0x0,
6602               NULL, HFILL
6603             }
6604         },
6605         { &hf_mac_lte_sr_time_until_answer,
6606             { "Time until answer (ms)",
6607               "mac-lte.ulsch.time-until-sr-answer", FT_UINT32, BASE_DEC, 0, 0x0,
6608               NULL, HFILL
6609             }
6610         },
6611
6612         { &hf_mac_lte_drx_config,
6613             { "DRX Configuration",
6614               "mac-lte.drx-config", FT_STRING, BASE_NONE,
6615               0, 0x0, NULL, HFILL
6616             }
6617         },
6618         { &hf_mac_lte_drx_config_frame_num,
6619             { "Config Frame",
6620               "mac-lte.drx-config.config-frame", FT_FRAMENUM, BASE_NONE,
6621               0, 0x0, NULL, HFILL
6622             }
6623         },
6624         { &hf_mac_lte_drx_config_previous_frame_num,
6625             { "Previous Config Frame",
6626               "mac-lte.drx-config.previous-config-frame", FT_FRAMENUM, BASE_NONE,
6627               0, 0x0, NULL, HFILL
6628             }
6629         },
6630         { &hf_mac_lte_drx_config_long_cycle,
6631             { "Long cycle",
6632               "mac-lte.drx-config.long-cycle", FT_UINT16, BASE_DEC,
6633               0, 0x0, NULL, HFILL
6634             }
6635         },
6636         { &hf_mac_lte_drx_config_cycle_offset,
6637             { "Cycle offset",
6638               "mac-lte.drx-config.cycle-offset", FT_UINT16, BASE_DEC,
6639               0, 0x0, NULL, HFILL
6640             }
6641         },
6642         { &hf_mac_lte_drx_config_onduration_timer,
6643             { "OnDuration Timer",
6644               "mac-lte.drx-config.onduration-timer", FT_UINT16, BASE_DEC,
6645               0, 0x0, NULL, HFILL
6646             }
6647         },
6648         { &hf_mac_lte_drx_config_inactivity_timer,
6649             { "Inactivity Timer",
6650               "mac-lte.drx-config.inactivity-timer", FT_UINT16, BASE_DEC,
6651               0, 0x0, NULL, HFILL
6652             }
6653         },
6654         { &hf_mac_lte_drx_config_retransmission_timer,
6655             { "Retransmission Timer",
6656               "mac-lte.drx-config.retransmission-timer", FT_UINT16, BASE_DEC,
6657               0, 0x0, NULL, HFILL
6658             }
6659         },
6660         { &hf_mac_lte_drx_config_short_cycle,
6661             { "Short cycle",
6662               "mac-lte.drx-config.short-cycle", FT_UINT16, BASE_DEC,
6663               0, 0x0, NULL, HFILL
6664             }
6665         },
6666         { &hf_mac_lte_drx_config_short_cycle_timer,
6667             { "Short cycle Timer",
6668               "mac-lte.drx-config.short-cycle-timer", FT_UINT16, BASE_DEC,
6669               0, 0x0, NULL, HFILL
6670             }
6671         },
6672
6673         { &hf_mac_lte_drx_state,
6674             { "DRX State",
6675               "mac-lte.drx-state", FT_STRING, BASE_NONE,
6676               0, 0x0, NULL, HFILL
6677             }
6678         },
6679         { &hf_mac_lte_drx_state_long_cycle_offset,
6680             { "Long cycle offset",
6681               "mac-lte.drx-state.long-cycle-offset", FT_UINT16, BASE_DEC,
6682               0, 0x0, NULL, HFILL
6683             }
6684         },
6685         { &hf_mac_lte_drx_state_long_cycle_on,
6686             { "Long cycle current on",
6687               "mac-lte.drx-state.long-cycle-on", FT_BOOLEAN, BASE_NONE,
6688               0, 0x0, NULL, HFILL
6689             }
6690         },
6691         { &hf_mac_lte_drx_state_short_cycle_offset,
6692             { "Short cycle offset",
6693               "mac-lte.drx-state.short-cycle-offset", FT_UINT16, BASE_DEC,
6694               0, 0x0, NULL, HFILL
6695             }
6696         },
6697         { &hf_mac_lte_drx_state_short_cycle_on,
6698             { "Short cycle current on",
6699               "mac-lte.drx-state.short-cycle-on", FT_BOOLEAN, BASE_NONE,
6700               0, 0x0, NULL, HFILL
6701             }
6702         },
6703         { &hf_mac_lte_drx_state_inactivity_remaining,
6704             { "Inactivity remaining",
6705               "mac-lte.drx-state.inactivity-remaining", FT_UINT16, BASE_DEC,
6706               0, 0x0, NULL, HFILL
6707             }
6708         },
6709         { &hf_mac_lte_drx_state_onduration_remaining,
6710             { "Onduration remaining",
6711               "mac-lte.drx-state.onduration-remaining", FT_UINT16, BASE_DEC,
6712               0, 0x0, NULL, HFILL
6713             }
6714         },
6715         { &hf_mac_lte_drx_state_retransmission_remaining,
6716             { "Retransmission remaining",
6717               "mac-lte.drx-state.retransmission-remaining", FT_UINT16, BASE_DEC,
6718               0, 0x0, NULL, HFILL
6719             }
6720         },
6721         { &hf_mac_lte_drx_state_rtt_remaining,
6722             { "RTT remaining",
6723               "mac-lte.drx-state.rtt-remaining", FT_UINT16, BASE_DEC,
6724               0, 0x0, NULL, HFILL
6725             }
6726         },
6727         { &hf_mac_lte_drx_state_short_cycle_remaining,
6728             { "Short-cycle timer remaining",
6729               "mac-lte.drx-state.short-cycle-remaining", FT_UINT16, BASE_DEC,
6730               0, 0x0, NULL, HFILL
6731             }
6732         },
6733     };
6734
6735     static gint *ett[] =
6736     {
6737         &ett_mac_lte,
6738         &ett_mac_lte_context,
6739         &ett_mac_lte_phy_context,
6740         &ett_mac_lte_rar_headers,
6741         &ett_mac_lte_rar_header,
6742         &ett_mac_lte_rar_body,
6743         &ett_mac_lte_rar_ul_grant,
6744         &ett_mac_lte_ulsch_header,
6745         &ett_mac_lte_dlsch_header,
6746         &ett_mac_lte_mch_header,
6747         &ett_mac_lte_sch_subheader,
6748         &ett_mac_lte_mch_subheader,
6749         &ett_mac_lte_bch,
6750         &ett_mac_lte_bsr,
6751         &ett_mac_lte_pch,
6752         &ett_mac_lte_activation_deactivation,
6753         &ett_mac_lte_contention_resolution,
6754         &ett_mac_lte_timing_advance,
6755         &ett_mac_lte_power_headroom,
6756         &ett_mac_lte_extended_power_headroom,
6757         &ett_mac_lte_extended_power_headroom_cell,
6758         &ett_mac_lte_mch_scheduling_info,
6759         &ett_mac_lte_oob,
6760         &ett_mac_lte_drx_config,
6761         &ett_mac_lte_drx_state
6762     };
6763
6764     static ei_register_info ei[] = {
6765         { &ei_mac_lte_reserved_not_zero, { "mac-lte.reserved-not-zero", PI_MALFORMED, PI_ERROR, "Reserved bit not zero", EXPFILL }},
6766         { &ei_mac_lte_rar_timing_advance_not_zero_note, { "mac-lte.rar.ta.not-zero", PI_SEQUENCE, PI_NOTE, "RAR Timing advance not zero", EXPFILL }},
6767         { &ei_mac_lte_rar_timing_advance_not_zero_warn, { "mac-lte.rar.ta.not-zero", PI_SEQUENCE, PI_WARN, "RAR Timing advance not zero", EXPFILL }},
6768         { &ei_mac_lte_rar_bi_present, { "mac-lte.rar.bi.present", PI_MALFORMED, PI_ERROR, "MAC RAR PDU has > 1 Backoff Indicator subheader present", EXPFILL }},
6769         { &ei_mac_lte_rar_bi_not_first_subheader, { "mac-lte.rar.bi.not-first-subheader", PI_MALFORMED, PI_WARN, "Backoff Indicator must appear as first subheader", EXPFILL }},
6770         { &ei_mac_lte_bch_pdu, { "mac-lte.bch.pdu.uplink", PI_MALFORMED, PI_ERROR, "BCH data should not be received in Uplink!", EXPFILL }},
6771         { &ei_mac_lte_pch_pdu, { "mac-lte.pch.pdu.uplink", PI_MALFORMED, PI_ERROR, "PCH data should not be received in Uplink!", EXPFILL }},
6772         { &ei_mac_lte_orig_tx_ul_frame_not_found, { "mac-lte.orig-tx-ul-frame-not-found", PI_SEQUENCE, PI_ERROR, "Original Tx of UL frame not found", EXPFILL }},
6773         { &ei_mac_lte_ul_harq_resend_next_frame, { "mac-lte.ulsch.retx.next-frame.expert", PI_SEQUENCE, PI_WARN, "UL MAC PDU needed to be retransmitted", EXPFILL }},
6774         { &ei_mac_lte_sr_results_not_grant_or_failure_indication, { "mac-lte.sr_results-not-grant-or-failure-indication", PI_SEQUENCE, PI_ERROR, "SR results in neither a grant nor a failure indication", EXPFILL }},
6775         { &ei_mac_lte_sr_invalid_event, { "mac-lte.ulsch.sr-invalid-event", PI_SEQUENCE, PI_ERROR, "Invalid SR event for UE", EXPFILL }},
6776         { &ei_mac_lte_dlsch_lcid, { "mac-lte.dlsch.lcid.DRX-received", PI_SEQUENCE, PI_NOTE, "DRX command received for UE", EXPFILL }},
6777         { &ei_mac_lte_control_subheader_after_data_subheader, { "mac-lte.control-subheader-after-data-subheader", PI_MALFORMED, PI_ERROR, "?L-SCH Control subheaders should not appear after data subheaders", EXPFILL }},
6778         { &ei_mac_lte_control_bsr_multiple, { "mac-lte.control.bsr.multiple", PI_MALFORMED, PI_ERROR, "There shouldn't be > 1 BSR in a frame", EXPFILL }},
6779         { &ei_mac_lte_padding_data_multiple, { "mac-lte.padding-data.multiple", PI_MALFORMED, PI_WARN, "Should not see more than 2 padding subheaders in one frame", EXPFILL }},
6780         { &ei_mac_lte_padding_data_before_control_subheader, { "mac-lte.padding-data.before-control-subheader", PI_MALFORMED, PI_ERROR, "Padding should come before other control subheaders!", EXPFILL }},
6781         { &ei_mac_lte_padding_data_start_and_end, { "mac-lte.padding-data.start-and-end", PI_MALFORMED, PI_ERROR, "Padding subheaders at start and end!", EXPFILL }},
6782         { &ei_mac_lte_lcid_unexpected, { "mac-lte.lcid-unexpected", PI_MALFORMED, PI_ERROR, "?L-SCH: Unexpected LCID received", EXPFILL }},
6783         { &ei_mac_lte_too_many_subheaders, { "mac-lte.too-many-subheaders", PI_MALFORMED, PI_ERROR, "Reached too many subheaders - frame obviously malformed", EXPFILL }},
6784         { &ei_mac_lte_control_ue_contention_resolution_msg3_matched, { "mac-lte.control.ue-contention-resolution.matches-msg3.not", PI_SEQUENCE, PI_WARN, "CR body in Msg4 doesn't match Msg3 CCCH in frame X", EXPFILL }},
6785         { &ei_mac_lte_control_timing_advance_command_no_correction, { "mac-lte.control.timing-advance.command.no-correction", PI_SEQUENCE, PI_NOTE, "Timing Advance control element received (no correction needed)", EXPFILL }},
6786         { &ei_mac_lte_control_timing_advance_command_correction_needed, { "mac-lte.control.timing-advance.correction-needed", PI_SEQUENCE, PI_WARN, "Timing Advance control element received with correction needed", EXPFILL }},
6787         { &ei_mac_lte_control_element_size_invalid, { "mac-lte.control-element.size-invalid", PI_MALFORMED, PI_ERROR, "Control Element has an unexpected size", EXPFILL }},
6788         { &ei_mac_lte_bsr_warn_threshold_exceeded, { "mac-lte.bsr-warn-threshold-exceeded", PI_SEQUENCE, PI_WARN, "BSR for LCG X exceeds threshold", EXPFILL }},
6789         { &ei_mac_lte_sch_header_only, { "mac-lte.sch.header-only", PI_SEQUENCE, PI_NOTE, "MAC PDU SDUs have been omitted", EXPFILL }},
6790         { &ei_mac_lte_context_length, { "mac-lte.length.invalid", PI_MALFORMED, PI_ERROR, "MAC PDU is longer than reported length", EXPFILL }},
6791         { &ei_mac_lte_rach_preamble_sent_warn, { "mac-lte.rach-preamble-sent", PI_SEQUENCE, PI_WARN, "RACH Preamble sent", EXPFILL }},
6792         { &ei_mac_lte_rach_preamble_sent_note, { "mac-lte.rach-preamble-sent", PI_SEQUENCE, PI_NOTE, "RACH Preamble sent", EXPFILL }},
6793         { &ei_mac_lte_oob_send_sr, { "mac-lte.sr-req", PI_SEQUENCE, PI_NOTE, "Scheduling Request sent", EXPFILL }},
6794         { &ei_mac_lte_oob_sr_failure, { "mac-lte.sr-failure", PI_SEQUENCE, PI_ERROR, "Scheduling Request failed", EXPFILL }},
6795         { &ei_mac_lte_context_sysframe_number, { "mac-lte.sfn.out-of-range", PI_MALFORMED, PI_ERROR, "Sysframe number out of range", EXPFILL }},
6796         { &ei_mac_lte_context_rnti_type, { "mac-lte.rnti-type.invalid", PI_MALFORMED, PI_ERROR, "RNTI indicated, but value is not correct", EXPFILL }},
6797         { &ei_mac_lte_ul_mac_frame_retx, { "mac-lte.ul-mac-frame-retx", PI_SEQUENCE, PI_WARN, "UL MAC frame ReTX", EXPFILL }},
6798         { &ei_mac_lte_context_crc_status, { "mac-lte.crc-status.error", PI_MALFORMED, PI_ERROR, "Frame has CRC error problem", EXPFILL }},
6799     };
6800
6801     static const enum_val_t show_info_col_vals[] = {
6802         {"show-phy", "PHY Info", ShowPHYLayer},
6803         {"show-mac", "MAC Info", ShowMACLayer},
6804         {"show-rlc", "RLC Info", ShowRLCLayer},
6805         {NULL, NULL, -1}
6806     };
6807
6808     static const enum_val_t lcid_drb_source_vals[] = {
6809         {"from-static-stable",          "From static table",           FromStaticTable},
6810         {"from-configuration-protocol", "From configuration protocol", FromConfigurationProtocol},
6811         {NULL, NULL, -1}
6812     };
6813
6814
6815     module_t *mac_lte_module;
6816     expert_module_t* expert_mac_lte;
6817
6818     static uat_field_t lcid_drb_mapping_flds[] = {
6819         UAT_FLD_VS(lcid_drb_mappings, lcid, "lcid", drb_lcid_vals, "The MAC LCID"),
6820         UAT_FLD_DEC(lcid_drb_mappings, drbid,"drb id (1-32)", "Identifier of logical data channel"),
6821         UAT_FLD_VS(lcid_drb_mappings, channel_type, "RLC Channel Type", rlc_channel_type_vals, "The MAC LCID"),
6822         UAT_END_FIELDS
6823     };
6824
6825     /* Register protocol. */
6826     proto_mac_lte = proto_register_protocol("MAC-LTE", "MAC-LTE", "mac-lte");
6827     proto_register_field_array(proto_mac_lte, hf, array_length(hf));
6828     proto_register_subtree_array(ett, array_length(ett));
6829     expert_mac_lte = expert_register_protocol(proto_mac_lte);
6830     expert_register_field_array(expert_mac_lte, ei, array_length(ei));
6831
6832     /* Allow other dissectors to find this one by name. */
6833     new_register_dissector("mac-lte", dissect_mac_lte, proto_mac_lte);
6834
6835     /* Register the tap name */
6836     mac_lte_tap = register_tap("mac-lte");
6837
6838     /* Preferences */
6839     mac_lte_module = prefs_register_protocol(proto_mac_lte, NULL);
6840
6841     /* Obsolete preferences */
6842     prefs_register_obsolete_preference(mac_lte_module, "single_rar");
6843     prefs_register_obsolete_preference(mac_lte_module, "check_reserved_bits");
6844     prefs_register_obsolete_preference(mac_lte_module, "decode_rar_ul_grant");
6845     prefs_register_obsolete_preference(mac_lte_module, "show_rlc_info_column");
6846     prefs_register_obsolete_preference(mac_lte_module, "attempt_to_detect_dl_harq_resend");
6847     prefs_register_obsolete_preference(mac_lte_module, "attempt_to_track_ul_harq_resend");
6848
6849     prefs_register_uint_preference(mac_lte_module, "retx_count_warn",
6850         "Number of Re-Transmits before expert warning triggered",
6851         "Number of Re-Transmits before expert warning triggered",
6852         10, &global_mac_lte_retx_counter_trigger);
6853
6854     prefs_register_bool_preference(mac_lte_module, "attempt_rrc_decode",
6855         "Attempt to decode BCH, PCH and CCCH data using LTE RRC dissector",
6856         "Attempt to decode BCH, PCH and CCCH data using LTE RRC dissector",
6857         &global_mac_lte_attempt_rrc_decode);
6858
6859     prefs_register_bool_preference(mac_lte_module, "attempt_to_dissect_crc_failures",
6860         "Dissect frames that have failed CRC check",
6861         "Attempt to dissect frames that have failed CRC check",
6862         &global_mac_lte_dissect_crc_failures);
6863
6864     prefs_register_bool_preference(mac_lte_module, "heuristic_mac_lte_over_udp",
6865         "Try Heuristic LTE-MAC over UDP framing",
6866         "When enabled, use heuristic dissector to find MAC-LTE frames sent with "
6867         "UDP framing",
6868         &global_mac_lte_heur);
6869
6870     prefs_register_bool_preference(mac_lte_module, "attempt_to_dissect_srb_sdus",
6871         "Attempt to dissect LCID 1&2 as srb1&2",
6872         "Will call LTE RLC dissector with standard settings as per RRC spec",
6873         &global_mac_lte_attempt_srb_decode);
6874
6875     prefs_register_bool_preference(mac_lte_module, "attempt_to_dissect_mcch",
6876         "Attempt to dissect MCH LCID 0 as MCCH",
6877         "Will call LTE RLC dissector for MCH LCID 0",
6878         &global_mac_lte_attempt_mcch_decode);
6879
6880     prefs_register_bool_preference(mac_lte_module, "call_rlc_for_mtch",
6881         "Call RLC dissector MTCH LCIDs",
6882         "Call RLC dissector MTCH LCIDs",
6883         &global_mac_lte_call_rlc_for_mtch);
6884
6885     prefs_register_enum_preference(mac_lte_module, "lcid_to_drb_mapping_source",
6886         "Source of LCID -> drb channel settings",
6887         "Set whether LCID -> drb Table is taken from static table (below) or from "
6888         "info learned from control protocol (e.g. RRC)",
6889         &global_mac_lte_lcid_drb_source, lcid_drb_source_vals, FALSE);
6890
6891     lcid_drb_mappings_uat = uat_new("Static LCID -> drb Table",
6892                                     sizeof(lcid_drb_mapping_t),
6893                                     "drb_logchans",
6894                                     TRUE,
6895                                     (void**) &lcid_drb_mappings,
6896                                     &num_lcid_drb_mappings,
6897                                     UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */
6898                                     "",  /* TODO: is this ref to help manual? */
6899                                     lcid_drb_mapping_copy_cb,
6900                                     NULL,
6901                                     NULL,
6902                                     NULL,
6903                                     lcid_drb_mapping_flds );
6904
6905     prefs_register_uat_preference(mac_lte_module,
6906                                   "drb_table",
6907                                   "LCID -> DRB Mappings Table",
6908                                   "A table that maps from configurable lcids -> RLC logical channels",
6909                                   lcid_drb_mappings_uat);
6910
6911     prefs_register_uint_preference(mac_lte_module, "bsr_warn_threshold",
6912         "BSR size when warning should be issued (0 - 63)",
6913         "If any BSR report is >= this number, an expert warning will be added",
6914         10, &global_mac_lte_bsr_warn_threshold);
6915
6916     prefs_register_bool_preference(mac_lte_module, "track_sr",
6917         "Track status of SRs within UEs",
6918         "Track status of SRs, providing links between requests, failure indications and grants",
6919         &global_mac_lte_track_sr);
6920
6921     prefs_register_enum_preference(mac_lte_module, "layer_to_show",
6922         "Which layer info to show in Info column",
6923         "Can show PHY, MAC or RLC layer info in Info column",
6924         &global_mac_lte_layer_to_show, show_info_col_vals, FALSE);
6925
6926     prefs_register_bool_preference(mac_lte_module, "decode_cr_body",
6927         "Decode CR body as UL CCCH",
6928         "Attempt to decode 6 bytes of Contention Resolution body as an UL CCCH PDU",
6929         &global_mac_lte_decode_cr_body);
6930
6931     prefs_register_bool_preference(mac_lte_module, "show_drx",
6932         "Show DRX Information (Incomplete/experimental!)",
6933         "Apply DRX config and show DRX state within each UE",
6934         &global_mac_lte_show_drx);
6935
6936
6937     register_init_routine(&mac_lte_init_protocol);
6938 }
6939
6940 void proto_reg_handoff_mac_lte(void)
6941 {
6942     /* Add as a heuristic UDP dissector */
6943     heur_dissector_add("udp", dissect_mac_lte_heur, proto_mac_lte);
6944
6945     /* Look up RLC dissector handle once and for all */
6946     rlc_lte_handle = find_dissector("rlc-lte");
6947 }
6948
6949 /*
6950  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
6951  *
6952  * Local variables:
6953  * c-basic-offset: 4
6954  * tab-width: 8
6955  * indent-tabs-mode: nil
6956  * End:
6957  *
6958  * vi: set shiftwidth=4 tabstop=8 expandtab:
6959  * :indentSize=4:tabSize=8:noTabs=true:
6960  */