1 /* Routines for LTE MAC disassembly
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include <epan/packet.h>
27 #include <epan/exceptions.h>
28 #include <epan/expert.h>
29 #include <epan/prefs.h>
32 #include <epan/wmem/wmem.h>
34 #include "packet-mac-lte.h"
35 #include "packet-rlc-lte.h"
37 void proto_register_mac_lte(void);
38 void proto_reg_handoff_mac_lte(void);
41 * 3GPP TS 36.321 Evolved Universal Terrestrial Radio Access (E-UTRA)
42 * Medium Access Control (MAC) protocol specification v11.0.0
46 /* Initialize the protocol and registered fields. */
47 int proto_mac_lte = -1;
49 static int mac_lte_tap = -1;
51 static dissector_handle_t rlc_lte_handle;
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;
72 static int hf_mac_lte_context_rapid = -1;
73 static int hf_mac_lte_context_rach_attempt_number = -1;
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;
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;
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;
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;
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;
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;
128 static int hf_mac_lte_sch_header_only = -1;
129 static int hf_mac_lte_mch_header_only = -1;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
318 /* Constants and value strings */
320 static const value_string radio_type_vals[] =
328 static const value_string direction_vals[] =
330 { DIRECTION_UPLINK, "Uplink"},
331 { DIRECTION_DOWNLINK, "Downlink"},
336 static const value_string rnti_type_vals[] =
338 { NO_RNTI, "NO-RNTI"},
340 { RA_RNTI, "RA-RNTI"},
342 { SI_RNTI, "SI-RNTI"},
343 { SPS_RNTI, "SPS-RNTI"},
348 static const value_string bch_transport_channel_vals[] =
350 { SI_RNTI, "DL-SCH"},
355 static const value_string crc_status_vals[] =
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"},
366 static const value_string carrier_id_vals[] =
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"},
376 static const value_string dci_format_vals[] =
390 static const value_string aggregation_level_vals[] =
399 static const value_string modulation_type_vals[] =
407 static const true_false_string mac_lte_scell_ph_vals = {
412 static const true_false_string mac_lte_power_backoff_vals = {
417 static const true_false_string mac_lte_ph_value_vals = {
418 "Based on reference format",
419 "Based on real transmission"
422 static const true_false_string mac_lte_scell_status_vals = {
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
433 static const value_string dlsch_lcid_vals[] =
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" },
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
461 static const value_string ulsch_lcid_vals[] =
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" },
484 #define MCH_SCHEDULING_INFO_LCID 0x1e
486 static const value_string mch_lcid_vals[] =
517 { MCH_SCHEDULING_INFO_LCID, "MCH Scheduling Information"},
518 { PADDING_LCID, "Padding" },
522 static const value_string format_vals[] =
524 { 0, "Data length is < 128 bytes"},
525 { 1, "Data length is >= 128 bytes"},
530 static const value_string rar_type_vals[] =
532 { 0, "Backoff Indicator present"},
533 { 1, "RAPID present"},
538 static const value_string rar_bi_vals[] =
557 static const value_string buffer_size_vals[] =
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"},
625 static value_string_ext buffer_size_vals_ext = VALUE_STRING_EXT_INIT(buffer_size_vals);
627 static const value_string ext_buffer_size_vals[] =
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"},
695 static value_string_ext ext_buffer_size_vals_ext = VALUE_STRING_EXT_INIT(ext_buffer_size_vals);
697 static const value_string power_headroom_vals[] =
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"},
765 static value_string_ext power_headroom_vals_ext = VALUE_STRING_EXT_INIT(power_headroom_vals);
767 static const value_string pcmaxc_vals[] =
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"},
835 static value_string_ext pcmaxc_vals_ext = VALUE_STRING_EXT_INIT(pcmaxc_vals);
837 static const value_string header_only_vals[] =
839 { 0, "MAC PDU Headers and body present"},
840 { 1, "MAC PDU Headers only"},
844 static const value_string predefined_frame_vals[] =
846 { 0, "Real MAC PDU present - will dissect"},
847 { 1, "Predefined frame present - will not dissect"},
851 static const value_string ul_retx_grant_vals[] =
858 /**************************************************************************/
859 /* Preferences state */
860 /**************************************************************************/
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;
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;
869 /* Whether should attempt to dissect frames failing CRC check */
870 static gboolean global_mac_lte_dissect_crc_failures = FALSE;
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;
875 /* Whether should attempt to decode MCH LCID 0 as MCCH */
876 static gboolean global_mac_lte_attempt_mcch_decode = FALSE;
878 /* Whether should call RLC dissector to decode MTCH LCIDs */
879 static gboolean global_mac_lte_call_rlc_for_mtch = FALSE;
881 /* Where to take LCID -> DRB mappings from */
882 enum lcid_drb_source {
883 FromStaticTable, FromConfigurationProtocol
885 static gint global_mac_lte_lcid_drb_source = (gint)FromStaticTable;
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 */
890 /* Whether or not to track SRs and related frames */
891 static gboolean global_mac_lte_track_sr = TRUE;
893 /* Which layer info to show in the info column */
895 ShowPHYLayer, ShowMACLayer, ShowRLCLayer
898 /* Which layer's details to show in Info column */
899 static gint global_mac_lte_layer_to_show = (gint)ShowRLCLayer;
901 /* Whether to decode Contention Resolution body as UL CCCH */
902 static gboolean global_mac_lte_decode_cr_body = FALSE;
904 /* Whether to record config and try to show DRX state for each configured UE */
905 static gboolean global_mac_lte_show_drx = FALSE;
909 /* When showing RLC info, count PDUs so can append info column properly */
910 static guint8 s_number_of_rlc_pdus_shown = 0;
912 /***********************************************************************/
913 /* How to dissect lcid 3-10 (presume drb logical channels) */
915 static const value_string drb_lcid_vals[] = {
927 typedef enum rlc_channel_type_t {
933 } rlc_channel_type_t;
935 static const value_string rlc_channel_type_vals[] = {
937 { rlcUM5 , "UM, SN Len=5"},
938 { rlcUM10, "UM, SN Len=10"},
945 typedef struct lcid_drb_mapping_t {
948 rlc_channel_type_t channel_type;
949 } lcid_drb_mapping_t;
952 static lcid_drb_mapping_t *lcid_drb_mappings = NULL;
953 static guint num_lcid_drb_mappings = 0;
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")
960 static uat_t* lcid_drb_mappings_uat;
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 {
967 rlc_channel_type_t channel_type;
969 } dynamic_lcid_drb_mapping_t;
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;
976 static GHashTable *mac_lte_ue_channels_hash = NULL;
979 extern int proto_rlc_lte;
981 /***************************************************************/
985 /***************************************************************/
986 /* Keeping track of Msg3 bodies so they can be compared with */
987 /* Contention Resolution bodies. */
989 typedef struct Msg3Data {
996 /* This table stores (RNTI -> Msg3Data*). Will be populated when
997 Msg3 frames are first read. */
998 static GHashTable *mac_lte_msg3_hash = NULL;
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)
1006 static guint mac_lte_rnti_hash_func(gconstpointer v)
1008 return GPOINTER_TO_UINT(v);
1012 typedef enum ContentionResolutionStatus {
1016 } ContentionResolutionStatus;
1018 typedef struct ContentionResolutionResult {
1019 ContentionResolutionStatus status;
1022 } ContentionResolutionResult;
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;
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)
1035 static guint mac_lte_framenum_hash_func(gconstpointer v)
1037 return GPOINTER_TO_UINT(v);
1040 /**************************************************************************/
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 */
1050 /* Could be bigger, but more than enough to flag suspected resends */
1051 #define MAX_EXPECTED_PDU_LENGTH 2048
1053 typedef struct LastFrameData {
1057 nstime_t received_time;
1059 guint8 data[MAX_EXPECTED_PDU_LENGTH];
1062 typedef struct DLHarqBuffers {
1063 LastFrameData harqid[2][15]; /* 2 blocks (1 for each antenna) needed for DL */
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;
1071 typedef struct DLHARQResult {
1072 gboolean previousSet, nextSet;
1073 guint previousFrameNum;
1074 guint timeSincePreviousFrame;
1076 guint timeToNextFrame;
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;
1084 /**************************************************************************/
1087 /*****************************************************************/
1088 /* Keeping track of last UL frames per C-RNTI so can verify when */
1089 /* told that a frame is a retx */
1091 typedef struct ULHarqBuffers {
1092 LastFrameData harqid[8];
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;
1100 typedef struct ULHARQResult {
1101 gboolean previousSet, nextSet;
1102 guint previousFrameNum;
1103 guint timeSincePreviousFrame;
1105 guint timeToNextFrame;
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;
1113 /**************************************************************************/
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 */
1123 typedef enum SREvent {
1129 static const value_string sr_event_vals[] =
1131 { SR_Grant, "Grant"},
1132 { SR_Request, "SR Request"},
1133 { SR_Failure, "SR Failure"},
1137 typedef enum SRStatus {
1143 static const value_string sr_status_vals[] =
1145 { None, "Receiving grants"},
1146 { SR_Outstanding, "SR Request outstanding"},
1147 { SR_Failed, "SR has Failed"},
1152 typedef struct SRState {
1154 guint32 lastSRFramenum;
1155 guint32 lastGrantFramenum;
1156 nstime_t requestTime;
1160 /* This table keeps track of the SR state for each UE.
1161 (RNTI -> SRState) */
1162 static GHashTable *mac_lte_ue_sr_state = NULL;
1165 typedef enum SRResultType {
1174 typedef struct SRResult {
1177 guint32 timeDifference;
1179 /* These 2 are only used with InvalidSREvent */
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;
1188 /**************************************************************************/
1192 /**************************************************************************/
1194 /* Config for current cycle/timer state for a configured UE */
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;
1201 typedef struct drx_running_state_t
1203 gboolean firstCycleStartSet;
1205 /* Cycle information */
1206 gboolean inShortCycle;
1209 nstime_t currentTime; /* absolute time of last PDU. Used to detect whole
1210 missing SFN cycle */
1212 guint64 currentTicks;
1216 /* These timers are absolute times when these events expire */
1217 guint64 onDurationTimer;
1218 guint64 inactivityTimer;
1220 guint64 retransmissionTimer[8];
1221 guint64 shortCycleTimer;
1223 } drx_running_state_t;
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;
1234 typedef struct drx_state_key_t {
1235 guint32 frameNumber;
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;
1243 static gint mac_lte_framenum_instance_hash_equal(gconstpointer v, gconstpointer v2)
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;
1248 return ((p1->frameNumber == p2->frameNumber) &&
1249 (p1->pdu_instance == p2->pdu_instance));
1252 static guint mac_lte_framenum_instance_hash_func(gconstpointer v)
1254 const drx_state_key_t *p1 = (const drx_state_key_t*)v;
1256 /* XXX which one return ? */
1257 return p1->frameNumber + (p1->pdu_instance >> 8);
1258 return GPOINTER_TO_UINT(v);
1264 /* Initialise the UE DRX state */
1265 static void init_drx_ue_state(drx_state_t *drx_state, gboolean at_init)
1268 drx_state->state_before.inShortCycle = FALSE;
1270 drx_state->state_before.onDurationTimer = G_GUINT64_CONSTANT(0);
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);
1277 drx_state->state_before.shortCycleTimer = G_GUINT64_CONSTANT(0);
1280 typedef enum drx_timer_type_t {
1281 drx_onduration_timer,
1282 drx_inactivity_timer,
1285 drx_short_cycle_timer
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)
1291 /* Get current time in ms */
1293 guint16 timerLength;
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;
1301 case drx_inactivity_timer:
1302 pTimer = &(p_state->state_before.inactivityTimer);
1303 timerLength = p_state->config.inactivityTimer;
1306 pTimer = &(p_state->state_before.RTT[timer_id]);
1309 case drx_retx_timer:
1310 pTimer = &(p_state->state_before.retransmissionTimer[timer_id]);
1311 timerLength = p_state->config.retransmissionTimer;
1313 case drx_short_cycle_timer:
1315 pTimer = &(p_state->state_before.shortCycleTimer);
1316 timerLength = p_state->config.shortCycle * p_state->config.shortCycleTimer;
1321 *pTimer = p_state->state_before.currentTicks + timerLength;
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)
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);
1332 case drx_inactivity_timer:
1333 p_state->state_before.inactivityTimer = G_GUINT64_CONSTANT(0);
1336 p_state->state_before.RTT[timer_id] = G_GUINT64_CONSTANT(0);
1338 case drx_retx_timer:
1339 p_state->state_before.retransmissionTimer[timer_id] = G_GUINT64_CONSTANT(0);
1341 case drx_short_cycle_timer:
1342 p_state->state_before.shortCycleTimer = G_GUINT64_CONSTANT(0);
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)
1352 guint64 *pTimer = NULL;
1353 drx_running_state_t *state_to_use;
1356 state_to_use = &p_state->state_before;
1359 state_to_use = &p_state->state_after;
1363 /* Get pointer to timer value */
1364 switch (timer_type) {
1365 case drx_onduration_timer:
1366 pTimer = &(state_to_use->onDurationTimer);
1368 case drx_inactivity_timer:
1369 pTimer = &(state_to_use->inactivityTimer);
1372 pTimer = &(state_to_use->RTT[timer_id]);
1374 case drx_retx_timer:
1375 pTimer = &(state_to_use->retransmissionTimer[timer_id]);
1377 case drx_short_cycle_timer:
1378 pTimer = &(state_to_use->shortCycleTimer);
1385 /* TODO: verify using SFN/SF ? */
1386 if (state_to_use->currentTicks == *pTimer) {
1387 *time_until_expires = 0;
1391 if (state_to_use->currentTicks > *pTimer) {
1392 *time_until_expires = 0;
1395 *time_until_expires = *pTimer - state_to_use->currentTicks;
1402 /* Handling of triggers that can prompt changes in state */
1404 static void mac_lte_drx_new_ulsch_data(guint16 ueid)
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));
1409 /* Start inactivity timer */
1410 if (ue_state != NULL) {
1411 mac_lte_drx_start_timer(ue_state, drx_inactivity_timer, 0);
1415 static void mac_lte_drx_new_dlsch_data(guint16 ueid)
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));
1421 /* Start retransmission timer */
1422 if (ue_state != NULL) {
1423 mac_lte_drx_start_timer(ue_state, drx_inactivity_timer, 0);
1427 static void mac_lte_drx_dl_crc_error(guint16 ueid)
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));
1434 if (ue_state != NULL) {
1435 mac_lte_drx_start_timer(ue_state, drx_retx_timer, 0);
1439 /* A DRX control element has been received */
1440 static void mac_lte_drx_control_element_received(guint16 ueid)
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));
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);
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)
1459 guint64 time_until_expires;
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));
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;
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;
1476 ue_state->state_before.currentTicks = SFN*10 + SF;
1478 ue_state->state_before.firstCycleStartSet = TRUE;
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. */
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);
1491 while ((ue_state->state_before.currentSFN != SFN) || (ue_state->state_before.currentSF != SF)) {
1493 /* Check for timers that have expired and change state accordingly */
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);
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);
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);
1517 /* Reception of DRX command is dealt with separately at the moment... */
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);
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;
1535 ue_state->state_before.currentSFN++;
1539 ue_state->state_before.currentSF++;
1542 ue_state->state_before.currentTicks++;
1545 /* Set current time to now */
1546 ue_state->state_before.currentTime = pinfo->fd->abs_ts;
1550 /* Convenience function to get a pointer for the hash_func to work with */
1551 static gpointer get_drx_result_hash_key(guint32 frameNumber,
1553 gboolean do_persist)
1555 static drx_state_key_t key;
1556 drx_state_key_t *p_key;
1558 /* Only allocate a struct when will be adding entry */
1560 p_key = wmem_new0(wmem_file_scope(), drx_state_key_t);
1563 memset(&key, 0, sizeof(drx_state_key_t));
1567 /* Fill in details, and return pointer */
1568 p_key->frameNumber = frameNumber;
1569 p_key->pdu_instance = pdu_instance;
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)
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;
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 */
1588 /* Copy UE snapshot for this frame, and add to result table */
1589 frame_result = wmem_new(wmem_file_scope(), drx_state_t);
1591 /* Deep-copy this snapshot for this frame */
1592 *frame_result = *ue_state;
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);
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;
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)
1613 drx_state_t *frame_state;
1614 drx_running_state_t *state_to_show;
1615 guint64 time_until_expires;
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));
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;
1627 /* Show config only if 'before */
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);
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);
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);
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);
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);
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);
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);
1685 /*************************************/
1686 /* Create state subtree */
1687 drx_state_ti = proto_tree_add_string_format(tree, hf_mac_lte_drx_state,
1689 (before_event) ? "DRX State Before" : "DRX State After");
1690 /* Get appropriate state pointer to use below */
1692 state_to_show = &frame_state->state_before;
1695 state_to_show = &frame_state->state_after;
1698 drx_state_tree = proto_item_add_subtree(drx_state_ti, ett_mac_lte_drx_state);
1699 PROTO_ITEM_SET_GENERATED(drx_state_ti);
1701 /* Show cycle information */
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);
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;
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);
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);
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! */
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);
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);
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);
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);
1780 /**************************************************************************/
1784 /* Forward declarations */
1785 int dissect_mac_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void*);
1787 static guint8 get_mac_lte_channel_priority(guint16 ueid _U_, guint8 lcid,
1791 /* Heuristic dissection */
1792 static gboolean global_mac_lte_heur = FALSE;
1794 static void call_with_catch_all(dissector_handle_t handle, tvbuff_t* tvb, packet_info *pinfo, proto_tree *tree)
1796 /* Call it (catch exceptions so that stats will be updated) */
1798 call_dissector_only(handle, tvb, pinfo, tree, NULL);
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,
1810 gint offset = *p_offset;
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++);
1817 if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
1818 p_mac_lte_info->detailed_phy_info.ul_info.present = FALSE;
1821 p_mac_lte_info->detailed_phy_info.dl_info.present = FALSE;
1824 p_mac_lte_info->rntiType = tvb_get_guint8(tvb, offset++);
1826 /* Initialize RNTI with a default value in case optional field is not present */
1827 switch (p_mac_lte_info->rntiType) {
1829 p_mac_lte_info->rnti = 0xFFFD;
1832 p_mac_lte_info->rnti = 0xFFFE;
1835 p_mac_lte_info->rnti = 0xFFFF;
1840 p_mac_lte_info->rnti = 0x0001;
1846 /* Read optional fields */
1847 while (tag != MAC_LTE_PAYLOAD_TAG) {
1848 /* Process next tag */
1849 tag = tvb_get_guint8(tvb, offset++);
1851 case MAC_LTE_RNTI_TAG:
1852 p_mac_lte_info->rnti = tvb_get_ntohs(tvb, offset);
1855 case MAC_LTE_UEID_TAG:
1856 p_mac_lte_info->ueid = tvb_get_ntohs(tvb, offset);
1859 case MAC_LTE_FRAME_SUBFRAME_TAG:
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;
1867 case MAC_LTE_PREDEFINED_DATA_TAG:
1868 p_mac_lte_info->isPredefinedData = tvb_get_guint8(tvb, offset);
1871 case MAC_LTE_RETX_TAG:
1872 p_mac_lte_info->reTxCount = tvb_get_guint8(tvb, offset);
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);
1881 case MAC_LTE_EXT_BSR_SIZES_TAG:
1882 p_mac_lte_info->isExtendedBSRSizes = TRUE;
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);
1888 p_mac_lte_info->rach_attempt_number = tvb_get_guint8(tvb, offset);
1891 case MAC_LTE_CARRIER_ID_TAG:
1892 p_mac_lte_info->carrierId =
1893 (mac_lte_carrier_id)tvb_get_guint8(tvb, offset);
1896 case MAC_LTE_PHY_TAG:
1900 len = tvb_get_guint8(tvb, offset++);
1902 if (p_mac_lte_info->direction == DIRECTION_DOWNLINK) {
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);
1909 p_mac_lte_info->detailed_phy_info.dl_info.resource_allocation_type =
1910 tvb_get_guint8(tvb, offset);
1912 p_mac_lte_info->detailed_phy_info.dl_info.aggregation_level =
1913 tvb_get_guint8(tvb, offset);
1915 p_mac_lte_info->detailed_phy_info.dl_info.mcs_index =
1916 tvb_get_guint8(tvb, offset);
1918 p_mac_lte_info->detailed_phy_info.dl_info.redundancy_version_index =
1919 tvb_get_guint8(tvb, offset);
1921 p_mac_lte_info->detailed_phy_info.dl_info.resource_block_length =
1922 tvb_get_guint8(tvb, offset);
1924 p_mac_lte_info->detailed_phy_info.dl_info.harq_id =
1925 tvb_get_guint8(tvb, offset);
1927 p_mac_lte_info->detailed_phy_info.dl_info.ndi =
1928 tvb_get_guint8(tvb, offset);
1930 p_mac_lte_info->detailed_phy_info.dl_info.transport_block =
1931 tvb_get_guint8(tvb, offset);
1933 p_mac_lte_info->dl_retx =
1934 (mac_lte_dl_retx)tvb_get_guint8(tvb, offset);
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);
1942 p_mac_lte_info->detailed_phy_info.ul_info.tbs_index =
1943 tvb_get_guint8(tvb, offset);
1945 p_mac_lte_info->detailed_phy_info.ul_info.resource_block_length =
1946 tvb_get_guint8(tvb, offset);
1948 p_mac_lte_info->detailed_phy_info.ul_info.resource_block_start =
1949 tvb_get_guint8(tvb, offset);
1951 p_mac_lte_info->detailed_phy_info.ul_info.harq_id =
1952 tvb_get_guint8(tvb, offset);
1954 p_mac_lte_info->detailed_phy_info.ul_info.ndi =
1955 tvb_get_guint8(tvb, offset);
1958 offset = offset1 + len;
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);
1969 /* It must be a recognised tag */
1974 /* Pass out where offset is now */
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_)
1985 struct mac_lte_info *p_mac_lte_info;
1987 gboolean infoAlreadySet = FALSE;
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!
1994 if (!global_mac_lte_heur) {
1998 /* Do this again on re-dissection to re-discover offset of actual PDU */
2000 /* Needs to be at least as long as:
2001 - the signature string
2002 - fixed header bytes
2004 - at least one byte of MAC PDU payload */
2005 if (tvb_length_remaining(tvb, offset) < (gint)(strlen(MAC_LTE_START_STRING)+3+2)) {
2009 /* OK, compare with signature string */
2010 if (tvb_strneql(tvb, offset, MAC_LTE_START_STRING, strlen(MAC_LTE_START_STRING)) != 0) {
2013 offset += (gint)strlen(MAC_LTE_START_STRING);
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;
2023 infoAlreadySet = TRUE;
2026 /* Dissect the fields to populate p_mac_lte */
2027 if (!dissect_mac_lte_context_fields(p_mac_lte_info, tvb, &offset)) {
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);
2037 /**************************************/
2038 /* OK, now dissect as MAC LTE */
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);
2048 /* Write the given formatted text to:
2049 - the info column (if pinfo != NULL)
2050 - 1 or 2 other labels (optional)
2052 static void write_pdu_label_and_info(proto_item *ti1, proto_item *ti2,
2053 packet_info *pinfo, const char *format, ...)
2055 #define MAX_INFO_BUFFER 256
2056 static char info_buffer[MAX_INFO_BUFFER];
2059 if ((ti1 == NULL) && (ti2 == NULL) && (pinfo == NULL)) {
2063 va_start(ap, format);
2064 g_vsnprintf(info_buffer, MAX_INFO_BUFFER, format, ap);
2067 /* Add to indicated places */
2068 if (pinfo != NULL) {
2069 col_append_str(pinfo->cinfo, COL_INFO, info_buffer);
2072 proto_item_append_text(ti1, "%s", info_buffer);
2075 proto_item_append_text(ti2, "%s", info_buffer);
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)
2083 if ((ti1 == NULL) && (ti2 == NULL) && (pinfo == NULL)) {
2087 /* Add to indicated places */
2088 if (pinfo != NULL) {
2089 col_append_str(pinfo->cinfo, COL_INFO, info_buffer);
2092 proto_item_append_text(ti1, "%s", info_buffer);
2095 proto_item_append_text(ti2, "%s", info_buffer);
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)
2106 proto_tree *phy_tree;
2109 if (global_mac_lte_layer_to_show == ShowPHYLayer) {
2110 /* Clear the info column */
2111 col_clear(pinfo->cinfo, COL_INFO);
2114 if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
2115 if (p_mac_lte_info->detailed_phy_info.ul_info.present) {
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);
2124 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_modulation_type,
2126 p_mac_lte_info->detailed_phy_info.ul_info.modulation_type);
2127 PROTO_ITEM_SET_GENERATED(ti);
2129 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_tbs_index,
2131 p_mac_lte_info->detailed_phy_info.ul_info.tbs_index);
2132 PROTO_ITEM_SET_GENERATED(ti);
2134 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_resource_block_length,
2136 p_mac_lte_info->detailed_phy_info.ul_info.resource_block_length);
2137 PROTO_ITEM_SET_GENERATED(ti);
2139 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_resource_block_start,
2141 p_mac_lte_info->detailed_phy_info.ul_info.resource_block_start);
2142 PROTO_ITEM_SET_GENERATED(ti);
2144 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_harq_id,
2146 p_mac_lte_info->detailed_phy_info.ul_info.harq_id);
2147 PROTO_ITEM_SET_GENERATED(ti);
2149 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_ndi,
2151 p_mac_lte_info->detailed_phy_info.ul_info.ndi);
2152 PROTO_ITEM_SET_GENERATED(ti);
2155 proto_item_append_text(phy_ti, " (");
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);
2168 proto_item_append_text(phy_ti, ")");
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);
2177 if (p_mac_lte_info->detailed_phy_info.dl_info.present) {
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);
2186 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_dci_format,
2188 p_mac_lte_info->detailed_phy_info.dl_info.dci_format);
2189 PROTO_ITEM_SET_GENERATED(ti);
2191 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_resource_allocation_type,
2193 p_mac_lte_info->detailed_phy_info.dl_info.resource_allocation_type);
2194 PROTO_ITEM_SET_GENERATED(ti);
2196 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_aggregation_level,
2198 p_mac_lte_info->detailed_phy_info.dl_info.aggregation_level);
2199 PROTO_ITEM_SET_GENERATED(ti);
2201 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_mcs_index,
2203 p_mac_lte_info->detailed_phy_info.dl_info.mcs_index);
2204 PROTO_ITEM_SET_GENERATED(ti);
2206 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_redundancy_version_index,
2208 p_mac_lte_info->detailed_phy_info.dl_info.redundancy_version_index);
2209 PROTO_ITEM_SET_GENERATED(ti);
2211 ti = proto_tree_add_boolean(phy_tree, hf_mac_lte_context_phy_dl_retx,
2213 p_mac_lte_info->dl_retx);
2214 PROTO_ITEM_SET_GENERATED(ti);
2216 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_resource_block_length,
2218 p_mac_lte_info->detailed_phy_info.dl_info.resource_block_length);
2219 PROTO_ITEM_SET_GENERATED(ti);
2221 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_harq_id,
2223 p_mac_lte_info->detailed_phy_info.dl_info.harq_id);
2224 PROTO_ITEM_SET_GENERATED(ti);
2226 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_ndi,
2228 p_mac_lte_info->detailed_phy_info.dl_info.ndi);
2229 PROTO_ITEM_SET_GENERATED(ti);
2231 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_tb,
2233 p_mac_lte_info->detailed_phy_info.dl_info.transport_block);
2234 PROTO_ITEM_SET_GENERATED(ti);
2237 proto_item_append_text(phy_ti, " (");
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, ")");
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);
2266 /* Dissect a single Random Access Reponse body */
2267 static gint dissect_rar_entry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2269 gint offset, guint8 rapid)
2272 guint start_body_offset = offset;
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;
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);
2288 /* Dissect an RAR entry */
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
2354 proto_item_set_len(rar_body_ti, offset-start_body_offset);
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)
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;
2371 proto_tree *rar_headers_tree;
2373 proto_item *rar_headers_ti;
2374 proto_item *padding_length_ti;
2375 int start_headers_offset = offset;
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);
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);
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);
2392 /***************************/
2393 /* Read the header entries */
2395 int start_header_offset = offset;
2396 proto_tree *rar_header_tree;
2397 proto_item *rar_header_ti;
2399 guint8 first_byte = tvb_get_guint8(tvb, offset);
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);
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);
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);
2415 if (type_value == 0) {
2416 /* Backoff Indicator (BI) case */
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);
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);
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);
2438 backoff_indicator_seen = TRUE;
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 "));
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);
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);
2456 proto_item_append_text(rar_header_ti, "(RAPID=%u)", rapids[number_of_rars]);
2463 /* Finalise length of header tree selection */
2464 proto_item_set_len(rar_header_ti, offset - start_header_offset);
2466 } while (extension && number_of_rars < MAX_RAR_PDUS);
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 "));
2477 proto_item_append_text(rar_headers_ti, ")");
2480 /* Set length for headers root */
2481 proto_item_set_len(rar_headers_ti, offset-start_headers_offset);
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]);
2490 /* Update TAP info */
2491 tap_info->number_of_rars += number_of_rars;
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);
2498 padding_length_ti = proto_tree_add_int(tree, hf_mac_lte_padding_length,
2500 p_mac_lte_info->length - offset);
2501 PROTO_ITEM_SET_GENERATED(padding_length_ti);
2503 /* Update padding bytes in stats */
2504 tap_info->padding_bytes += (p_mac_lte_info->length - offset);
2508 /* Dissect BCH PDU */
2509 static void dissect_bch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2511 int offset, mac_lte_info *p_mac_lte_info)
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,
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);
2527 /****************************************/
2528 /* Whole frame is BCH data */
2531 ti = proto_tree_add_item(tree, hf_mac_lte_bch_pdu,
2532 tvb, offset, -1, ENC_NA);
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);
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");
2544 protocol_handle = find_dissector("lte_rrc.bcch_bch");
2547 /* Hide raw view of bytes */
2548 PROTO_ITEM_SET_HIDDEN(ti);
2550 call_with_catch_all(protocol_handle, rrc_tvb, pinfo, tree);
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);
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)
2566 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
2567 "PCH PDU (%u bytes) ",
2568 tvb_length_remaining(tvb, offset));
2570 /****************************************/
2571 /* Whole frame is PCH data */
2573 /* Always show as raw data */
2574 ti = proto_tree_add_item(tree, hf_mac_lte_pch_pdu,
2575 tvb, offset, -1, ENC_NA);
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;
2581 if (global_mac_lte_attempt_rrc_decode) {
2583 /* Attempt to decode payload using LTE RRC dissector */
2584 tvbuff_t *rrc_tvb = tvb_new_subset_remaining(tvb, offset);
2586 /* Get appropriate dissector handle */
2587 dissector_handle_t protocol_handle = find_dissector("lte_rrc.pcch");
2589 /* Hide raw view of bytes */
2590 PROTO_ITEM_SET_HIDDEN(ti);
2592 /* Call it (catch exceptions so that stats will be updated) */
2593 call_with_catch_all(protocol_handle, rrc_tvb, pinfo, tree);
2596 /* Check that this *is* downlink! */
2597 if (direction == DIRECTION_UPLINK) {
2598 expert_add_info(pinfo, ti, &ei_mac_lte_pch_pdu);
2603 /* Does this header entry correspond to a fixed-sized control element? */
2604 static int is_fixed_sized_control_element(guint8 lcid, guint8 direction)
2606 if (direction == DIRECTION_UPLINK) {
2609 case POWER_HEADROOM_REPORT_LCID:
2611 case TRUNCATED_BSR_LCID:
2612 case SHORT_BSR_LCID:
2621 /* Assume Downlink */
2623 case ACTIVATION_DEACTIVATION_LCID:
2624 case UE_CONTENTION_RESOLUTION_IDENTITY_LCID:
2625 case TIMING_ADVANCE_LCID:
2626 case DRX_COMMAND_LCID:
2636 /* Is this a BSR report header? */
2637 static int is_bsr_lcid(guint8 lcid)
2639 return ((lcid == TRUNCATED_BSR_LCID) ||
2640 (lcid == SHORT_BSR_LCID) ||
2641 (lcid == LONG_BSR_LCID));
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,
2648 int offset, guint16 data_length,
2649 guint8 mode, guint8 direction, guint16 ueid,
2650 guint16 channelType, guint16 channelId,
2651 guint8 UMSequenceNumberLength,
2654 tvbuff_t *rb_tvb = tvb_new_subset(tvb, offset, data_length, data_length);
2655 struct rlc_lte_info *p_rlc_lte_info;
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);
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;
2673 /* Store info in packet */
2674 p_add_proto_data(wmem_file_scope(), pinfo, proto_rlc_lte, 0, p_rlc_lte_info);
2676 if (global_mac_lte_layer_to_show != ShowRLCLayer) {
2677 /* Don't want these columns replaced */
2678 col_set_writable(pinfo->cinfo, FALSE);
2681 /* Clear info column before first RLC PDU */
2682 if (s_number_of_rlc_pdus_shown == 0) {
2683 col_clear(pinfo->cinfo, COL_INFO);
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);
2691 s_number_of_rlc_pdus_shown++;
2693 /* Call it (catch exceptions so that stats will be updated) */
2694 call_with_catch_all(rlc_lte_handle, rb_tvb, pinfo, tree);
2696 /* Let columns be written to again */
2697 col_set_writable(pinfo->cinfo, TRUE);
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)
2705 DLHARQResult *result = NULL;
2706 DLHARQResult *original_result = NULL;
2708 /* If don't have detailed DL PHy info, just give up */
2709 if (!p_mac_lte_info->detailed_phy_info.dl_info.present) {
2713 /* TDD may not work... */
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;
2720 DLHarqBuffers *ueData;
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;
2726 /* Check harq-id bounds, give up if invalid */
2727 if ((harq_id >= 15) || (transport_block > 1)) {
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));
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) {
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;
2749 /* Round difference to nearest millisecond */
2750 gint total_gap = (seconds_between_packets*1000) +
2751 ((nseconds_between_packets+500000) / 1000000);
2753 /* Expect to be within (say) 8-13 subframes since previous */
2754 if ((total_gap >= 8) && (total_gap <= 13)) {
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);
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);
2769 original_result->nextSet = TRUE;
2770 original_result->nextFrameNum = pinfo->fd->num;
2771 original_result->timeToNextFrame = total_gap;
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);
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;
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));
2797 /***************************************************/
2798 /* Show link back to original frame (if available) */
2799 if (result != NULL) {
2800 if (result->previousSet) {
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);
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);
2811 if (result->nextSet) {
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);
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);
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)
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);
2831 if (p_mac_lte_info == NULL) {
2835 if (direction == DIRECTION_UPLINK) {
2836 /* For UL, retx count is stored in per-packet struct */
2837 return (p_mac_lte_info->reTxCount > 0);
2840 /* Use answer if told directly */
2841 if (p_mac_lte_info->dl_retx == dl_retx_yes) {
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);
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)
2860 ULHARQResult *result = NULL;
2862 /* If don't have detailed DL PHY info, just give up */
2863 if (!p_mac_lte_info->detailed_phy_info.ul_info.present) {
2867 /* Give up if harqid is out of range */
2868 if (p_mac_lte_info->detailed_phy_info.ul_info.harq_id >= 8) {
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;
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) {
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;
2896 /* Round to nearest ms */
2897 gint total_gap = (seconds_between_packets*1000) +
2898 ((nseconds_between_packets+500000) / 1000000);
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;
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);
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);
2918 original_result->nextSet = TRUE;
2919 original_result->nextFrameNum = pinfo->fd->num;
2920 original_result->timeToNextFrame = total_gap;
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);
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;
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));
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;
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);
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);
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);
2967 /* Show link forward to any known next Tx */
2968 if ((result != NULL) && result->nextSet) {
2969 proto_item *next_ti, *gap_ti;
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);
2976 PROTO_ITEM_SET_GENERATED(next_ti);
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);
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)
2990 result = (SRResult *)g_hash_table_lookup(mac_lte_sr_request_hash, GUINT_TO_POINTER(frameNum));
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);
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)
3005 SRResult *result = NULL;
3007 SRResult *resultForSRFrame = NULL;
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];
3019 rnti = p_mac_lte_info->rnti;
3020 ueid = p_mac_lte_info->ueid;
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);
3032 /* First time through - update state with new info */
3033 if (!pinfo->fd->flags.visited) {
3034 guint32 timeSinceRequest;
3036 /* Store time of request */
3037 if (event == SR_Request) {
3038 state->requestTime = pinfo->fd->abs_ts;
3041 switch (state->status) {
3045 /* Got another grant - fine */
3048 state->lastGrantFramenum = pinfo->fd->num;
3052 /* Sent an SR - fine */
3055 state->status = SR_Outstanding;
3056 state->lastSRFramenum = pinfo->fd->num;
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;
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));
3075 /* Got grant we were waiting for, so state goes to None */
3078 state->status = None;
3080 /* Set result info */
3081 result = GetSRResult(pinfo->fd->num, TRUE);
3082 result->type = GrantAnsweringSR;
3083 result->frameNum = state->lastSRFramenum;
3084 result->timeDifference = timeSinceRequest;
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;
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;
3102 /* We sent an SR but it failed */
3105 state->status = SR_Failed;
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;
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;
3125 /* Got a grant, presumably after a subsequent RACH - fine */
3128 state->status = None;
3132 /* Tried another SR after previous one failed.
3133 Presumably a subsequent RACH was tried in-between... */
3135 state->status = SR_Outstanding;
3137 result = GetSRResult(pinfo->fd->num, TRUE);
3138 result->status = SR_Outstanding;
3139 result->event = SR_Request;
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;
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",
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);
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);
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);
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);
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",
3211 val_to_str_const(result->status, sr_status_vals, "Unknown"),
3212 val_to_str_const(result->event, sr_event_vals, "Unknown"));
3218 /********************************************************/
3219 /* Count number of UEs/TTI (in both directions) */
3220 /********************************************************/
3222 /* For keeping track during first pass */
3223 typedef struct tti_info_t {
3225 nstime_t ttiStartTime;
3229 static tti_info_t UL_tti_info;
3230 static tti_info_t DL_tti_info;
3232 /* For associating with frame and displaying */
3233 typedef struct TTIInfoResult_t {
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;
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)
3245 gboolean same_tti = FALSE;
3246 tti_info_t *tti_info;
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;
3254 /* Set tti_info based upon direction */
3255 if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
3256 tti_info = &UL_tti_info;
3259 tti_info = &DL_tti_info;
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;
3269 /* Round difference to nearest microsecond */
3270 gint total_us_gap = (seconds_between_packets*1000000) +
3271 ((nseconds_between_packets+500) / 1000);
3273 if (total_us_gap < 1000) {
3278 /* Update global state */
3280 tti_info->subframe = p_mac_lte_info->subframeNumber;
3281 tti_info->ttiStartTime = pinfo->fd->abs_ts;
3282 tti_info->ues_in_tti = 1;
3285 tti_info->ues_in_tti++;
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);
3294 return tti_info->ues_in_tti;
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)
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);
3315 /* Lookup channel details for lcid */
3316 static void lookup_rlc_channel_from_lcid(guint16 ueid,
3318 rlc_channel_type_t *rlc_channel_type,
3319 guint8 *UM_seqnum_length,
3322 /* Zero params (in case no match is found) */
3323 *rlc_channel_type = rlcRaw;
3324 *UM_seqnum_length = 0;
3327 if (global_mac_lte_lcid_drb_source == (int)FromStaticTable) {
3329 /* Look up in static (UAT) table */
3331 for (m=0; m < num_lcid_drb_mappings; m++) {
3332 if (lcid == lcid_drb_mappings[m].lcid) {
3334 *rlc_channel_type = lcid_drb_mappings[m].channel_type;
3336 /* Set UM_seqnum_length */
3337 switch (*rlc_channel_type) {
3339 *UM_seqnum_length = 5;
3342 *UM_seqnum_length = 10;
3349 *drb_id = lcid_drb_mappings[m].drbid;
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));
3361 /* Look up setting gleaned from configuration protocol */
3362 if (!ue_mappings->mapping[lcid].valid) {
3366 *rlc_channel_type = ue_mappings->mapping[lcid].channel_type;
3368 /* Set UM_seqnum_length */
3369 switch (*rlc_channel_type) {
3371 *UM_seqnum_length = 5;
3374 *UM_seqnum_length = 10;
3381 *drb_id = ue_mappings->mapping[lcid].drbid;
3387 #define MAX_HEADERS_IN_PDU 1024
3389 /* UL-SCH and DL-SCH formats have much in common, so handle them in a common
3391 static void dissect_ulsch_or_dlsch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
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,
3401 proto_item *truncated_ti;
3402 proto_item *padding_length_ti;
3403 proto_item *hidden_root_ti;
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];
3410 proto_item *pdu_header_ti;
3411 proto_tree *pdu_header_tree;
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;
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);
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);
3431 tap_info->raw_length = p_mac_lte_info->length;
3433 /******************************************************/
3434 /* DRX information */
3436 /* Update DRX state of UE */
3437 if (global_mac_lte_show_drx) {
3438 if (!pinfo->fd->flags.visited) {
3440 /* Update UE state to this subframe (but before this event is processed) */
3441 update_drx_info(pinfo, p_mac_lte_info);
3443 /* Store 'before' snapshot of UE state for this frame */
3444 set_drx_info(pinfo, p_mac_lte_info, TRUE, pdu_instance);
3447 /* Show current DRX state in tree as 'before' */
3448 show_drx_info(pinfo, tree, tvb, p_mac_lte_info, TRUE, pdu_instance);
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);
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);
3462 else if (p_mac_lte_info->reTxCount == 0) {
3463 mac_lte_drx_new_dlsch_data(p_mac_lte_info->ueid);
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);
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) {
3479 TrackSRInfo(SR_Grant, pinfo, tree, tvb, p_mac_lte_info, 0, NULL);
3482 /* Add hidden item to filter on */
3483 hidden_root_ti = proto_tree_add_string_format(tree,
3484 (direction == DIRECTION_UPLINK) ?
3490 PROTO_ITEM_SET_HIDDEN(hidden_root_ti);
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,
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);
3506 /************************************************************************/
3507 /* Dissect each sub-header. */
3511 proto_item *pdu_subheader_ti;
3512 proto_tree *pdu_subheader_tree;
3513 proto_item *lcid_ti;
3515 gint offset_start_subheader = offset;
3516 guint8 first_byte = tvb_get_guint8(tvb, offset);
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,
3525 pdu_subheader_tree = proto_item_add_subtree(pdu_subheader_ti,
3526 ett_mac_lte_sch_subheader);
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');
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);
3543 /* LCID. Has different meaning depending upon direction. */
3544 lcids[number_of_headers] = first_byte & 0x1f;
3545 if (direction == DIRECTION_UPLINK) {
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,
3551 val_to_str_const(lcids[number_of_headers],
3552 ulsch_lcid_vals, "(Unknown LCID)"));
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,
3560 val_to_str_const(lcids[number_of_headers],
3561 dlsch_lcid_vals, "(Unknown LCID)"));
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);
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;
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');
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);
3593 have_seen_bsr = TRUE;
3596 /* Should not see padding after non-padding control... */
3597 if ((lcids[number_of_headers] > 10) &&
3598 (lcids[number_of_headers] == PADDING_LCID) &&
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);
3606 if (have_seen_non_padding_control) {
3607 expert_add_info(pinfo, lcid_ti, &ei_mac_lte_padding_data_before_control_subheader);
3611 /* Also flag if we have final padding but also padding subheaders
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);
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;
3626 /********************************************************************/
3627 /* Length field follows if not the last header or for a fixed-sized
3631 if (is_fixed_sized_control_element(lcids[number_of_headers], direction)) {
3632 pdu_lengths[number_of_headers] = 0;
3635 pdu_lengths[number_of_headers] = -1;
3639 /* Not the last one */
3640 if (!is_fixed_sized_control_element(lcids[number_of_headers], direction) &&
3641 (lcids[number_of_headers] != PADDING_LCID)) {
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);
3650 /* Now read length field itself */
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);
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);
3664 pdu_lengths[number_of_headers] = (gint16)length;
3667 pdu_lengths[number_of_headers] = 0;
3672 /* Close off description in info column */
3673 switch (pdu_lengths[number_of_headers]) {
3675 write_pdu_label_and_info_literal(pdu_ti, NULL, pinfo, ") ");
3678 write_pdu_label_and_info_literal(pdu_ti, NULL, pinfo, ":remainder) ");
3681 write_pdu_label_and_info(pdu_ti, NULL, pinfo, ":%u bytes) ",
3682 pdu_lengths[number_of_headers]);
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) ?
3694 switch (pdu_lengths[number_of_headers]) {
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,
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,
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,
3716 pdu_lengths[number_of_headers]);
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]);
3730 /* Set length of this subheader */
3731 proto_item_set_len(pdu_subheader_ti, offset - offset_start_subheader);
3733 number_of_headers++;
3734 } while ((number_of_headers < MAX_HEADERS_IN_PDU) && extension);
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);
3745 /* Append summary to overall PDU header root */
3746 proto_item_append_text(pdu_header_ti, " [%u subheaders]",
3749 /* And set its length to offset */
3750 proto_item_set_len(pdu_header_ti, offset);
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);
3758 tap_info->isPHYRetx = (p_mac_lte_info->dl_retx == dl_retx_yes);
3762 /************************************************************************/
3763 /* Dissect SDUs / control elements / padding. */
3764 /************************************************************************/
3766 /* Dissect control element bodies first */
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]]++;
3776 /* Process what should be a valid control PDU type */
3777 if (direction == DIRECTION_DOWNLINK) {
3779 /****************************/
3780 /* DL-SCH Control PDUs */
3782 case ACTIVATION_DEACTIVATION_LCID:
3785 proto_tree *ad_tree;
3789 /* Create AD root */
3790 ad_ti = proto_tree_add_string_format(tree,
3791 hf_mac_lte_control_activation_deactivation,
3794 "Activation/Deactivation");
3795 ad_tree = proto_item_add_subtree(ad_ti, ett_mac_lte_activation_deactivation);
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");
3821 case UE_CONTENTION_RESOLUTION_IDENTITY_LCID:
3824 proto_tree *cr_tree;
3826 ContentionResolutionResult *crResult;
3828 /* Create CR root */
3829 cr_ti = proto_tree_add_string_format(tree,
3830 hf_mac_lte_control_ue_contention_resolution,
3833 "Contention Resolution");
3834 cr_tree = proto_item_add_subtree(cr_ti, ett_mac_lte_contention_resolution);
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);
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) {
3851 /* Need to set result by looking for and comparing with Msg3 */
3853 guint msg3Key = p_mac_lte_info->rnti;
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);
3860 msg3Data = (Msg3Data *)g_hash_table_lookup(mac_lte_msg3_hash, GUINT_TO_POINTER(msg3Key));
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;
3868 /* Compare the 6 bytes */
3869 if (tvb_memeql(tvb, offset, msg3Data->data, 6) == 0) {
3870 crResult->status = Msg3Match;
3873 crResult->status = Msg3NoMatch;
3877 crResult->status = NoMsg3;
3881 /* Now show CR result in tree */
3882 switch (crResult->status) {
3884 proto_item_append_text(cr_ti, " (no corresponding Msg3 found!)");
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);
3895 ti = proto_tree_add_boolean(cr_tree, hf_mac_lte_control_ue_contention_resolution_msg3_matched,
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);
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);
3910 ti = proto_tree_add_boolean(cr_tree, hf_mac_lte_control_ue_contention_resolution_msg3_matched,
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);
3924 case TIMING_ADVANCE_LCID:
3927 proto_item *ta_value_ti;
3928 proto_tree *ta_tree;
3931 /* Create TA root */
3932 ta_ti = proto_tree_add_string_format(tree,
3933 hf_mac_lte_control_timing_advance,
3937 ta_tree = proto_item_add_subtree(ta_ti, ett_mac_lte_timing_advance);
3940 proto_tree_add_item(ta_tree, hf_mac_lte_control_timing_advance_group_id,
3941 tvb, offset, 1, ENC_BIG_ENDIAN);
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);
3948 if (ta_value == 31) {
3949 expert_add_info(pinfo, ta_value_ti, &ei_mac_lte_control_timing_advance_command_no_correction);
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",
3955 (ta_value < 31) ? "-ve" : "+ve");
3960 case DRX_COMMAND_LCID:
3962 mac_lte_drx_control_element_received(p_mac_lte_info->ueid);
3965 /* No payload (in this position) */
3966 tap_info->padding_bytes++;
3975 /**********************************/
3976 /* UL-SCH Control PDUs */
3978 case EXTENDED_POWER_HEADROOM_REPORT_LCID:
3980 proto_item *ephr_ti;
3981 proto_tree *ephr_tree;
3983 proto_tree *ephr_cell_tree;
3984 proto_item *ephr_cell_ti;
3985 guint8 scell_bitmap;
3989 guint32 curr_offset = offset;
3990 guint32 computed_header_offset;
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);
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],
4002 "Extended Power Headroom");
4003 ephr_tree = proto_item_add_subtree(ephr_ti, ett_mac_lte_extended_power_headroom);
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");
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)) {
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++;
4042 computed_header_offset++;
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++;
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];
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"));
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);
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);
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"));
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];
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"));
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);
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);
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"));
4129 offset += pdu_lengths[n];
4132 case POWER_HEADROOM_REPORT_LCID:
4135 proto_tree *phr_tree;
4140 /* Create PHR root */
4141 phr_ti = proto_tree_add_string_format(tree,
4142 hf_mac_lte_control_power_headroom,
4146 phr_tree = proto_item_add_subtree(phr_ti, ett_mac_lte_power_headroom);
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);
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);
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"));
4171 proto_tree_add_item(tree, hf_mac_lte_control_crnti,
4172 tvb, offset, 2, ENC_BIG_ENDIAN);
4175 case TRUNCATED_BSR_LCID:
4176 case SHORT_BSR_LCID:
4178 proto_tree *bsr_tree;
4180 proto_item *buffer_size_ti;
4184 value_string_ext *p_vs_ext;
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;
4190 hfindex = hf_mac_lte_control_short_bsr_buffer_size;
4191 p_vs_ext = &buffer_size_vals_ext;
4194 bsr_ti = proto_tree_add_string_format(tree,
4195 hf_mac_lte_control_bsr,
4199 bsr_tree = proto_item_add_subtree(bsr_ti, ett_mac_lte_bsr);
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);
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);
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,
4216 val_to_str_ext_const(buffer_size, p_vs_ext, "Unknown"));
4220 proto_item_append_text(bsr_ti, " (lcgid=%u %s)",
4222 val_to_str_ext_const(buffer_size, &buffer_size_vals_ext, "Unknown"));
4227 proto_tree *bsr_tree;
4229 proto_item *buffer_size_ti;
4230 guint8 buffer_size[4];
4232 value_string_ext *p_vs_ext;
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;
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;
4248 bsr_ti = proto_tree_add_string_format(tree,
4249 hf_mac_lte_control_bsr,
4253 bsr_tree = proto_item_add_subtree(bsr_ti, ett_mac_lte_bsr);
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,
4264 val_to_str_ext_const(buffer_size[0], p_vs_ext, "Unknown"));
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);
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,
4277 val_to_str_ext_const(buffer_size[1], p_vs_ext, "Unknown"));
4281 buffer_size_ti = proto_tree_add_item(bsr_tree, hfindex[2],
4282 tvb, offset, 2, ENC_BIG_ENDIAN);
4284 buffer_size[2] = ((tvb_get_guint8(tvb, offset) & 0x0f) << 2) | ((tvb_get_guint8(tvb, offset+1) & 0xc0) >> 6);
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,
4291 val_to_str_ext_const(buffer_size[2], p_vs_ext, "Unknown"));
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;
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,
4304 val_to_str_ext_const(buffer_size[3], p_vs_ext, "Unknown"));
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"));
4316 /* No payload, in this position */
4317 tap_info->padding_bytes++;
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,
4331 PROTO_ITEM_SET_GENERATED(truncated_ti);
4332 expert_add_info(pinfo, truncated_ti, &ei_mac_lte_sch_header_only);
4336 PROTO_ITEM_SET_HIDDEN(truncated_ti);
4340 /* Now process remaining bodies, which should all be data */
4341 for (; n < number_of_headers; n++) {
4343 /* Data SDUs treated identically for Uplink or downlink channels */
4345 const guint8 *pdu_data;
4346 volatile guint16 data_length;
4349 gboolean rlc_called_for_sdu = FALSE;
4351 /* Break out if meet padding */
4352 if (lcids[n] == PADDING_LCID) {
4356 /* Work out length */
4357 data_length = (pdu_lengths[n] == -1) ?
4358 tvb_length_remaining(tvb, offset) :
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) ?
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));
4378 /* Look for previous entry for this UE */
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);
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;
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);
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");
4402 protocol_handle = find_dissector("lte_rrc.dl_ccch");
4405 /* Hide raw view of bytes */
4406 PROTO_ITEM_SET_HIDDEN(sdu_ti);
4407 rlc_called_for_sdu = TRUE;
4409 call_with_catch_all(protocol_handle, rrc_tvb, pinfo, tree);
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));
4422 /* Hide raw view of bytes */
4423 PROTO_ITEM_SET_HIDDEN(sdu_ti);
4424 rlc_called_for_sdu = TRUE;
4428 else if ((lcids[n] >= 2) && (lcids[n] <= 10)) {
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;
4434 guint8 priority = get_mac_lte_channel_priority(p_mac_lte_info->ueid,
4435 lcids[n], direction);
4437 lookup_rlc_channel_from_lcid(p_mac_lte_info->ueid,
4443 /* Dissect according to channel type */
4444 switch (rlc_channel_type) {
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,
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,
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,
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,
4470 /* Nothing to do! */
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;
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]);
4488 g_snprintf(buff+(i*2), 4, "...");
4492 proto_item_append_text(sdu_ti, "%s", buff);
4495 offset += data_length;
4497 /* Update tap byte count for this channel */
4498 tap_info->bytes_for_lcid[lcids[n]] += data_length;
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);
4508 padding_length_ti = proto_tree_add_int(tree, hf_mac_lte_padding_length,
4510 p_mac_lte_info->length - offset);
4511 PROTO_ITEM_SET_GENERATED(padding_length_ti);
4513 /* Update padding bytes in stats */
4514 tap_info->padding_bytes += (p_mac_lte_info->length - offset);
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);
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);
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);
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);
4550 /* Show current DRX state in tree as 'after' */
4551 show_drx_info(pinfo, tree, tvb, p_mac_lte_info, FALSE, pdu_instance);
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)
4560 proto_item *truncated_ti;
4561 proto_item *padding_length_ti;
4562 proto_item *hidden_root_ti;
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];
4569 proto_item *pdu_header_ti, *sched_info_ti = NULL;
4570 proto_tree *pdu_header_tree;
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;
4578 write_pdu_label_and_info_literal(pdu_ti, NULL, pinfo, "MCH: ");
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);
4585 /* Add PDU block header subtree */
4586 pdu_header_ti = proto_tree_add_string_format(tree, hf_mac_lte_mch_header,
4590 pdu_header_tree = proto_item_add_subtree(pdu_header_ti, ett_mac_lte_mch_header);
4593 /************************************************************************/
4594 /* Dissect each sub-header. */
4598 proto_item *pdu_subheader_ti;
4599 proto_tree *pdu_subheader_tree;
4600 proto_item *lcid_ti;
4602 gint offset_start_subheader = offset;
4603 guint8 first_byte = tvb_get_guint8(tvb, offset);
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,
4612 pdu_subheader_tree = proto_item_add_subtree(pdu_subheader_ti,
4613 ett_mac_lte_mch_subheader);
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");
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);
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;
4636 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
4638 val_to_str_const(lcids[number_of_headers],
4639 mch_lcid_vals, "(Unknown LCID)"));
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;
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");
4657 /* Should not see padding after non-padding control... */
4658 if ((lcids[number_of_headers] > 28) &&
4659 (lcids[number_of_headers] == PADDING_LCID) &&
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);
4667 if (have_seen_non_padding_control) {
4668 expert_add_info(pinfo, lcid_ti, &ei_mac_lte_padding_data_before_control_subheader);
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;
4680 /********************************************************************/
4681 /* Length field follows if not the last header or for a fixed-sized
4685 pdu_lengths[number_of_headers] = -1;
4688 /* Not the last one */
4689 if (lcids[number_of_headers] != PADDING_LCID) {
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);
4698 /* Now read length field itself */
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);
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);
4712 pdu_lengths[number_of_headers] = (gint16)length;
4715 pdu_lengths[number_of_headers] = 0;
4720 /* Close off description in info column */
4721 switch (pdu_lengths[number_of_headers]) {
4723 write_pdu_label_and_info_literal(pdu_ti, NULL, pinfo, ") ");
4726 write_pdu_label_and_info_literal(pdu_ti, NULL, pinfo, ":remainder) ");
4729 write_pdu_label_and_info(pdu_ti, NULL, pinfo, ":%u bytes) ",
4730 pdu_lengths[number_of_headers]);
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"));
4739 switch (pdu_lengths[number_of_headers]) {
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],
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],
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],
4761 pdu_lengths[number_of_headers]);
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]);
4773 /* Set length of this subheader */
4774 proto_item_set_len(pdu_subheader_ti, offset - offset_start_subheader);
4776 number_of_headers++;
4777 } while ((number_of_headers < MAX_HEADERS_IN_PDU) && extension);
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);
4788 /* Append summary to overall PDU header root */
4789 proto_item_append_text(pdu_header_ti, " (%u subheaders)",
4792 /* And set its length to offset */
4793 proto_item_set_len(pdu_header_ti, offset);
4796 /************************************************************************/
4797 /* Dissect SDUs / control elements / padding. */
4798 /************************************************************************/
4800 /* Dissect control element bodies first */
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) {
4808 /* Process what should be a valid control PDU type */
4810 case MCH_SCHEDULING_INFO_LCID:
4812 guint32 curr_offset = offset;
4814 guint16 stop_mtch_val;
4815 proto_item *mch_sched_info_ti, *ti;
4816 proto_tree *mch_sched_info_tree;
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);
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");
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],
4831 "MCH Scheduling Information");
4832 mch_sched_info_tree = proto_item_add_subtree(mch_sched_info_ti, ett_mac_lte_mch_scheduling_info);
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)");
4843 else if (stop_mtch_val == 2047) {
4844 proto_item_append_text(ti, " (MTCH is not scheduled)");
4849 offset += pdu_lengths[n];
4853 /* No payload (in this position) */
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,
4867 PROTO_ITEM_SET_GENERATED(truncated_ti);
4868 expert_add_info(pinfo, truncated_ti, &ei_mac_lte_sch_header_only);
4872 PROTO_ITEM_SET_HIDDEN(truncated_ti);
4876 /* Now process remaining bodies, which should all be data */
4877 for (; n < number_of_headers; n++) {
4880 const guint8 *pdu_data;
4881 volatile guint16 data_length;
4885 /* Break out if meet padding */
4886 if (lcids[n] == PADDING_LCID) {
4890 /* Work out length */
4891 data_length = (pdu_lengths[n] == -1) ?
4892 tvb_length_remaining(tvb, offset) :
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);
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"),
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]);
4917 g_snprintf(buff+(i*2), 4, "...");
4921 proto_item_append_text(sdu_ti, "%s", buff);
4924 offset += data_length;
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);
4933 padding_length_ti = proto_tree_add_int(tree, hf_mac_lte_padding_length,
4935 p_mac_lte_info->length - offset);
4936 PROTO_ITEM_SET_GENERATED(padding_length_ti);
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);
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);
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);
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)
4970 int dissect_mac_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
4972 proto_tree *mac_lte_tree;
4974 proto_tree *context_tree;
4975 proto_item *context_ti;
4976 proto_item *retx_ti = NULL;
4979 struct mac_lte_info *p_mac_lte_info;
4981 guint pdu_instance = GPOINTER_TO_UINT(data);
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));
4986 /* Set protocol name */
4987 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MAC-LTE");
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);
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);
4997 /* Can't dissect anything without it... */
4998 if (p_mac_lte_info == NULL) {
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);
5006 /* Clear info column */
5007 col_clear(pinfo->cinfo, COL_INFO);
5010 /*****************************************/
5011 /* Show context information */
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);
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);
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);
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);
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;
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);
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);
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);
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);
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);
5067 case ltemac_send_sr:
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);
5074 for (n=0; n < p_mac_lte_info->number_of_srs; n++) {
5076 proto_tree *sr_tree;
5078 /* SR event is subtree */
5079 sr_ti = proto_tree_add_expert_format(mac_lte_tree, pinfo, &ei_mac_lte_oob_send_sr,
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);
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);
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);
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]);
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]);
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]);
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);
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);
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);
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);
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);
5145 /* Our work here is done */
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);
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);
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);
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);
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);
5188 /* Check that RNTI value is consistent with given RNTI type */
5189 switch (p_mac_lte_info->rntiType) {
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);
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);
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);
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);
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);
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);
5243 PROTO_ITEM_SET_HIDDEN(ti);
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);
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);
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);
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);
5274 if (p_mac_lte_info->crcStatusValid) {
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);
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,
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,
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);
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);
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);
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;
5319 tap_info->time = pinfo->fd->abs_ts;
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);
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) ?
5334 /* Queue tap info */
5335 if (!pinfo->flags.in_error_pkt) {
5336 tap_queue_packet(mac_lte_tap, pinfo, tap_info);
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))) {
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));
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);
5359 /* Reset this counter */
5360 s_number_of_rlc_pdus_shown = 0;
5362 /* Dissect the MAC PDU itself. Format depends upon RNTI type. */
5363 switch (p_mac_lte_info->rntiType) {
5367 dissect_pch(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info->direction, tap_info);
5372 dissect_rar(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info, tap_info);
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);
5384 /* BCH over DL-SCH */
5385 dissect_bch(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info);
5390 dissect_mch(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info);
5394 /* Must be BCH over BCH... */
5395 dissect_bch(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info);
5403 /* Queue tap info */
5404 tap_queue_packet(mac_lte_tap, pinfo, tap_info);
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)
5416 /* Destroy any existing tables. */
5417 if (mac_lte_msg3_hash) {
5418 g_hash_table_destroy(mac_lte_msg3_hash);
5420 if (mac_lte_cr_result_hash) {
5421 g_hash_table_destroy(mac_lte_cr_result_hash);
5424 if (mac_lte_dl_harq_hash) {
5425 g_hash_table_destroy(mac_lte_dl_harq_hash);
5427 if (mac_lte_dl_harq_result_hash) {
5428 g_hash_table_destroy(mac_lte_dl_harq_result_hash);
5430 if (mac_lte_ul_harq_hash) {
5431 g_hash_table_destroy(mac_lte_ul_harq_hash);
5433 if (mac_lte_ul_harq_result_hash) {
5434 g_hash_table_destroy(mac_lte_ul_harq_result_hash);
5436 if (mac_lte_ue_sr_state) {
5437 g_hash_table_destroy(mac_lte_ue_sr_state);
5439 if (mac_lte_sr_request_hash) {
5440 g_hash_table_destroy(mac_lte_sr_request_hash);
5442 if (mac_lte_tti_info_result_hash) {
5443 g_hash_table_destroy(mac_lte_tti_info_result_hash);
5445 if (mac_lte_ue_channels_hash) {
5446 g_hash_table_destroy(mac_lte_ue_channels_hash);
5448 if (mac_lte_drx_ue_state) {
5449 g_hash_table_destroy(mac_lte_drx_ue_state);
5451 if (mac_lte_drx_frame_result) {
5452 g_hash_table_destroy(mac_lte_drx_frame_result);
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 */
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);
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);
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);
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);
5475 mac_lte_tti_info_result_hash = g_hash_table_new(mac_lte_framenum_hash_func, mac_lte_framenum_hash_equal);
5477 mac_lte_ue_channels_hash = g_hash_table_new(mac_lte_rnti_hash_func, mac_lte_rnti_hash_equal);
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);
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_)
5486 const lcid_drb_mapping_t *o = (const lcid_drb_mapping_t *)orig;
5487 lcid_drb_mapping_t *d = (lcid_drb_mapping_t *)dest;
5489 /* Copy all items over */
5491 d->drbid = o->drbid;
5492 d->channel_type = o->channel_type;
5498 /*************************************************************************/
5499 /* These functions get called from outside of this module, i.e. from RRC */
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)
5504 ue_dynamic_drb_mappings_t *ue_mappings;
5507 /* Check lcid range */
5508 if (drb_mapping->lcid_present) {
5509 lcid = drb_mapping->lcid;
5511 /* Ignore if LCID is out of range */
5512 if ((lcid < 3) || (lcid > 10)) {
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));
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),
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];
5533 /* Still no lcid - give up */
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;
5545 /* Fill in available RLC info */
5546 if (drb_mapping->rlcMode_present) {
5547 switch (drb_mapping->rlcMode) {
5549 ue_mappings->mapping[lcid].channel_type = rlcAM;
5552 if (drb_mapping->um_sn_length_present) {
5553 if (drb_mapping->um_sn_length == 5) {
5554 ue_mappings->mapping[lcid].channel_type = rlcUM5;
5557 ue_mappings->mapping[lcid].channel_type = rlcUM10;
5568 /* Return the configured UL priority for the channel */
5569 static guint8 get_mac_lte_channel_priority(guint16 ueid, guint8 lcid,
5572 ue_dynamic_drb_mappings_t *ue_mappings;
5574 /* Priority only affects UL */
5575 if (direction == DIRECTION_DOWNLINK) {
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));
5585 /* Won't report value if channel not configured */
5586 if (!ue_mappings->mapping[lcid].valid) {
5590 return ue_mappings->mapping[lcid].ul_priority;
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)
5597 if (global_mac_lte_show_drx && !pinfo->fd->flags.visited) {
5598 drx_state_t *ue_state;
5599 guint32 previousFrameNum = 0;
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);
5608 previousFrameNum = ue_state->config.frameNum;
5611 /* Clearing state when new config comes in... */
5612 init_drx_ue_state(ue_state, TRUE);
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;
5623 /* Release DRX config for this UE */
5624 void set_mac_lte_drx_config_release(guint16 ueid, packet_info *pinfo)
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? */
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)
5642 return (mac_lte_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_mac_lte, 0);
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)
5648 p_add_proto_data(wmem_file_scope(), pinfo, proto_mac_lte, 0, p_mac_lte_info);
5651 void proto_register_mac_lte(void)
5653 static hf_register_info hf[] =
5655 /**********************************/
5656 /* Items for decoding context */
5657 { &hf_mac_lte_context,
5659 "mac-lte.context", FT_STRING, BASE_NONE, NULL, 0x0,
5663 { &hf_mac_lte_context_radio_type,
5665 "mac-lte.radio-type", FT_UINT8, BASE_DEC, VALS(radio_type_vals), 0x0,
5669 { &hf_mac_lte_context_direction,
5671 "mac-lte.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
5672 "Direction of message", HFILL
5675 { &hf_mac_lte_context_rnti,
5677 "mac-lte.rnti", FT_UINT16, BASE_DEC, 0, 0x0,
5678 "RNTI associated with message", HFILL
5681 { &hf_mac_lte_context_rnti_type,
5683 "mac-lte.rnti-type", FT_UINT8, BASE_DEC, VALS(rnti_type_vals), 0x0,
5684 "Type of RNTI associated with message", HFILL
5687 { &hf_mac_lte_context_ueid,
5689 "mac-lte.ueid", FT_UINT16, BASE_DEC, 0, 0x0,
5690 "User Equipment Identifier associated with message", HFILL
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
5699 { &hf_mac_lte_context_subframe_number,
5701 "mac-lte.subframe", FT_UINT16, BASE_DEC, 0, 0x0,
5702 "Subframe number associated with message", HFILL
5705 { &hf_mac_lte_context_grant_subframe_number,
5707 "mac-lte.grant-subframe", FT_UINT16, BASE_DEC, 0, 0x0,
5708 "Subframe when grant for this PDU was received", HFILL
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
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
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
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
5735 { &hf_mac_lte_context_retx_count,
5737 "mac-lte.retx-count", FT_UINT8, BASE_DEC, 0, 0x0,
5738 "Number of times this PDU has been retransmitted", HFILL
5741 { &hf_mac_lte_context_retx_reason,
5743 "mac-lte.retx-reason", FT_UINT8, BASE_DEC, VALS(ul_retx_grant_vals), 0x0,
5744 "Type of UL ReTx grant", HFILL
5747 { &hf_mac_lte_context_crc_status,
5749 "mac-lte.crc-status", FT_UINT8, BASE_DEC, VALS(crc_status_vals), 0x0,
5750 "CRC Status as reported by PHY", HFILL
5753 { &hf_mac_lte_context_carrier_id,
5755 "mac-lte.carrier-id", FT_UINT8, BASE_DEC, VALS(carrier_id_vals), 0x0,
5759 { &hf_mac_lte_context_rapid,
5761 "mac-lte.preamble-sent.rapid", FT_UINT8, BASE_DEC, 0, 0x0,
5762 "RAPID sent in RACH preamble", HFILL
5765 { &hf_mac_lte_context_rach_attempt_number,
5766 { "RACH Attempt Number",
5767 "mac-lte.preamble-sent.attempt", FT_UINT8, BASE_DEC, 0, 0x0,
5772 { &hf_mac_lte_ues_ul_per_tti,
5774 "mac-lte.ul-tti-count", FT_UINT8, BASE_DEC, 0, 0x0,
5775 "In this TTI, this is the nth UL grant", HFILL
5778 { &hf_mac_lte_ues_dl_per_tti,
5780 "mac-lte.dl-tti-count", FT_UINT8, BASE_DEC, 0, 0x0,
5781 "In this TTI, this is the nth DL PDU", HFILL
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,
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,
5799 { &hf_mac_lte_context_phy_ul_tbs_index,
5801 "mac-lte.ul-phy.tbs-index", FT_UINT8, BASE_DEC, 0, 0x0,
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,
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,
5817 { &hf_mac_lte_context_phy_ul_harq_id,
5819 "mac-lte.ul-phy.harq-id", FT_UINT8, BASE_DEC, 0, 0x0,
5823 { &hf_mac_lte_context_phy_ul_ndi,
5825 "mac-lte.ul-phy.ndi", FT_UINT8, BASE_DEC, 0, 0x0,
5826 "UL New Data Indicator", HFILL
5830 { &hf_mac_lte_context_phy_dl,
5831 { "DL PHY attributes",
5832 "mac-lte.dl-phy", FT_STRING, BASE_NONE, 0, 0x0,
5836 { &hf_mac_lte_context_phy_dl_dci_format,
5838 "mac-lte.dl-phy.dci-format", FT_UINT8, BASE_DEC, VALS(dci_format_vals), 0x0,
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,
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,
5854 { &hf_mac_lte_context_phy_dl_mcs_index,
5856 "mac-lte.dl-phy.mcs-index", FT_UINT8, BASE_DEC, 0, 0x0,
5860 { &hf_mac_lte_context_phy_dl_redundancy_version_index,
5862 "mac-lte.dl-phy.rv-index", FT_UINT8, BASE_DEC, 0, 0x0,
5866 { &hf_mac_lte_context_phy_dl_retx,
5868 "mac-lte.dl-phy.dl-retx", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
5872 { &hf_mac_lte_context_phy_dl_resource_block_length,
5874 "mac-lte.dl-phy.rb-length", FT_UINT8, BASE_DEC, 0, 0x0,
5878 { &hf_mac_lte_context_phy_dl_harq_id,
5880 "mac-lte.dl-phy.harq-id", FT_UINT8, BASE_DEC, 0, 0x0,
5884 { &hf_mac_lte_context_phy_dl_ndi,
5886 "mac-lte.dl-phy.ndi", FT_UINT8, BASE_DEC, 0, 0x0,
5887 "New Data Indicator", HFILL
5890 { &hf_mac_lte_context_phy_dl_tb,
5892 "mac-lte.dl-phy.tb", FT_UINT8, BASE_DEC, 0, 0x0,
5893 "Transport Block (antenna #)", HFILL
5897 /* Out-of-band events */
5898 { &hf_mac_lte_oob_send_preamble,
5900 "mac-lte.preamble-sent", FT_STRING, BASE_NONE, NULL, 0x0,
5904 { &hf_mac_lte_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
5911 /*******************************************/
5912 /* MAC shared channel header fields */
5913 { &hf_mac_lte_ulsch,
5915 "mac-lte.ulsch", FT_STRING, BASE_NONE, NULL, 0x0,
5919 { &hf_mac_lte_ulsch_header,
5921 "mac-lte.ulsch.header", FT_STRING, BASE_NONE, NULL, 0x0,
5925 { &hf_mac_lte_dlsch_header,
5927 "mac-lte.dlsch.header", FT_STRING, BASE_NONE, NULL, 0x0,
5931 { &hf_mac_lte_dlsch,
5933 "mac-lte.dlsch", FT_STRING, BASE_NONE, NULL, 0x0,
5937 { &hf_mac_lte_sch_subheader,
5939 "mac-lte.sch.subheader", FT_STRING, BASE_NONE, NULL, 0x0,
5945 "mac-lte.mch", FT_STRING, BASE_NONE, NULL, 0x0,
5949 { &hf_mac_lte_mch_header,
5951 "mac-lte.mch.header", FT_STRING, BASE_NONE, NULL, 0x0,
5955 { &hf_mac_lte_mch_subheader,
5957 "mac-lte.mch.subheader", FT_STRING, BASE_NONE, NULL, 0x0,
5961 { &hf_mac_lte_sch_reserved,
5962 { "SCH reserved bits",
5963 "mac-lte.sch.reserved", FT_UINT8, BASE_HEX, NULL, 0xc0,
5967 { &hf_mac_lte_sch_extended,
5969 "mac-lte.sch.extended", FT_UINT8, BASE_HEX, 0, 0x20,
5970 "Extension - i.e. further headers after this one", HFILL
5973 { &hf_mac_lte_dlsch_lcid,
5975 "mac-lte.dlsch.lcid", FT_UINT8, BASE_HEX, VALS(dlsch_lcid_vals), 0x1f,
5976 "DL-SCH Logical Channel Identifier", HFILL
5979 { &hf_mac_lte_ulsch_lcid,
5981 "mac-lte.ulsch.lcid", FT_UINT8, BASE_HEX, VALS(ulsch_lcid_vals), 0x1f,
5982 "UL-SCH Logical Channel Identifier", HFILL
5985 { &hf_mac_lte_sch_format,
5987 "mac-lte.sch.format", FT_UINT8, BASE_HEX, VALS(format_vals), 0x80,
5991 { &hf_mac_lte_sch_length,
5993 "mac-lte.sch.length", FT_UINT16, BASE_DEC, 0, 0x0,
5994 "Length of MAC SDU or MAC control element", HFILL
5997 { &hf_mac_lte_mch_reserved,
5998 { "MCH reserved bits",
5999 "mac-lte.mch.reserved", FT_UINT8, BASE_HEX, NULL, 0xc0,
6003 { &hf_mac_lte_mch_extended,
6005 "mac-lte.mch.extended", FT_UINT8, BASE_HEX, 0, 0x20,
6006 "Extension - i.e. further headers after this one", HFILL
6009 { &hf_mac_lte_mch_lcid,
6011 "mac-lte.mch.lcid", FT_UINT8, BASE_HEX, VALS(mch_lcid_vals), 0x1f,
6012 "MCH Logical Channel Identifier", HFILL
6015 { &hf_mac_lte_mch_format,
6017 "mac-lte.mch.format", FT_UINT8, BASE_HEX, VALS(format_vals), 0x80,
6021 { &hf_mac_lte_mch_length,
6023 "mac-lte.mch.length", FT_UINT16, BASE_DEC, 0, 0x0,
6024 "Length of MAC SDU or MAC control element", HFILL
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,
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,
6040 /********************************/
6042 { &hf_mac_lte_sch_sdu,
6044 "mac-lte.sch.sdu", FT_BYTES, BASE_NONE, 0, 0x0,
6045 "Shared channel SDU", HFILL
6048 { &hf_mac_lte_mch_sdu,
6050 "mac-lte.mch.sdu", FT_BYTES, BASE_NONE, 0, 0x0,
6051 "Multicast channel SDU", HFILL
6054 { &hf_mac_lte_bch_pdu,
6056 "mac-lte.bch.pdu", FT_BYTES, BASE_NONE, 0, 0x0,
6060 { &hf_mac_lte_pch_pdu,
6062 "mac-lte.pch.pdu", FT_BYTES, BASE_NONE, 0, 0x0,
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
6072 { &hf_mac_lte_raw_pdu,
6074 "mac-lte.raw-data", FT_BYTES, BASE_NONE, 0, 0x0,
6075 "Raw bytes of PDU (e.g. if CRC error)", HFILL
6078 { &hf_mac_lte_padding_data,
6080 "mac-lte.padding-data", FT_BYTES, BASE_NONE, 0, 0x0,
6084 { &hf_mac_lte_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
6093 /*********************************/
6097 "mac-lte.rar", FT_NONE, BASE_NONE, NULL, 0x0,
6101 { &hf_mac_lte_rar_headers,
6103 "mac-lte.rar.headers", FT_STRING, BASE_NONE, NULL, 0x0,
6107 { &hf_mac_lte_rar_header,
6109 "mac-lte.rar.header", FT_STRING, BASE_NONE, NULL, 0x0,
6113 { &hf_mac_lte_rar_extension,
6115 "mac-lte.rar.e", FT_UINT8, BASE_HEX, 0, 0x80,
6116 "Extension - i.e. further RAR headers after this one", HFILL
6119 { &hf_mac_lte_rar_t,
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
6125 { &hf_mac_lte_rar_bi,
6127 "mac-lte.rar.bi", FT_UINT8, BASE_HEX, VALS(rar_bi_vals), 0x0f,
6128 "Backoff Indicator (ms)", HFILL
6131 { &hf_mac_lte_rar_rapid,
6133 "mac-lte.rar.rapid", FT_UINT8, BASE_HEX_DEC, 0, 0x3f,
6134 "Random Access Preamble IDentifier", HFILL
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
6143 { &hf_mac_lte_rar_reserved,
6145 "mac-lte.rar.reserved", FT_UINT8, BASE_HEX, 0, 0x30,
6146 "Reserved bits in RAR header - should be 0", HFILL
6150 { &hf_mac_lte_rar_body,
6152 "mac-lte.rar.body", FT_STRING, BASE_NONE, NULL, 0x0,
6156 { &hf_mac_lte_rar_reserved2,
6158 "mac-lte.rar.reserved2", FT_UINT8, BASE_HEX, 0, 0x80,
6159 "Reserved bit in RAR body - should be 0", HFILL
6162 { &hf_mac_lte_rar_ta,
6164 "mac-lte.rar.ta", FT_UINT16, BASE_DEC, 0, 0x7ff0,
6165 "Required adjustment to uplink transmission timing", HFILL
6168 { &hf_mac_lte_rar_ul_grant,
6170 "mac-lte.rar.ul-grant", FT_UINT24, BASE_DEC, 0, 0x0fffff,
6171 "Size of UL Grant", HFILL
6174 { &hf_mac_lte_rar_ul_grant_hopping,
6176 "mac-lte.rar.ul-grant.hopping", FT_UINT8, BASE_DEC, 0, 0x08,
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,
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,
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,
6198 { &hf_mac_lte_rar_ul_grant_ul_delay,
6200 "mac-lte.rar.ul-grant.ul-delay", FT_UINT8, BASE_DEC, 0, 0x02,
6204 { &hf_mac_lte_rar_ul_grant_cqi_request,
6206 "mac-lte.rar.ul-grant.cqi-request", FT_UINT8, BASE_DEC, 0, 0x01,
6210 { &hf_mac_lte_rar_temporary_crnti,
6211 { "Temporary C-RNTI",
6212 "mac-lte.rar.temporary-crnti", FT_UINT16, BASE_DEC, 0, 0x0,
6217 /**********************/
6218 /* Control PDU fields */
6219 { &hf_mac_lte_control_bsr,
6221 "mac-lte.control.bsr", FT_STRING, BASE_NONE, 0, 0x0,
6222 "Buffer Status Report", HFILL
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,
6231 { &hf_mac_lte_control_short_bsr_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
6237 { &hf_mac_lte_control_long_bsr_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
6243 { &hf_mac_lte_control_long_bsr_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
6249 { &hf_mac_lte_control_long_bsr_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
6255 { &hf_mac_lte_control_long_bsr_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
6261 { &hf_mac_lte_control_short_ext_bsr_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
6267 { &hf_mac_lte_control_long_ext_bsr_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
6273 { &hf_mac_lte_control_long_ext_bsr_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
6279 { &hf_mac_lte_control_long_ext_bsr_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
6285 { &hf_mac_lte_control_long_ext_bsr_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
6291 { &hf_mac_lte_control_crnti,
6293 "mac-lte.control.crnti", FT_UINT16, BASE_DEC, 0, 0x0,
6294 "C-RNTI for the UE", HFILL
6297 { &hf_mac_lte_control_timing_advance,
6299 "mac-lte.control.timing-advance", FT_STRING, BASE_NONE, 0, 0x0,
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,
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
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,
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,
6327 { &hf_mac_lte_control_ue_contention_resolution_msg3,
6329 "mac-lte.control.ue-contention-resolution.msg3", FT_FRAMENUM, BASE_NONE, 0, 0x0,
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,
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
6346 { &hf_mac_lte_control_power_headroom,
6348 "mac-lte.control.power-headroom", FT_STRING, BASE_NONE, 0, 0x0,
6352 { &hf_mac_lte_control_power_headroom_reserved,
6354 "mac-lte.control.power-headroom.reserved", FT_UINT8, BASE_DEC, 0, 0xc0,
6355 "Reserved bits, should be 0", HFILL
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
6365 { &hf_mac_lte_control_ext_power_headroom,
6366 { "Extended Power Headroom",
6367 "mac-lte.control.ext-power-headroom", FT_STRING, BASE_NONE,
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
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
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
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
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
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
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
6413 { &hf_mac_lte_control_ext_power_headroom_reserved,
6415 "mac-lte.control.ext-power-headroom.reserved", FT_UINT8, BASE_DEC,
6416 0, 0x01, "Reserved bit, should be 0", HFILL
6419 { &hf_mac_lte_control_ext_power_headroom_power_backoff,
6421 "mac-lte.control.ext-power-headroom.power-backoff", FT_BOOLEAN, 8,
6422 TFS(&mac_lte_power_backoff_vals), 0x80, NULL, HFILL
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
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
6437 { &hf_mac_lte_control_ext_power_headroom_reserved2,
6439 "mac-lte.control.ext-power-headroom.reserved2", FT_UINT8, BASE_DEC,
6440 0, 0xc0, "Reserved bits, should be 0", HFILL
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
6450 { &hf_mac_lte_control_activation_deactivation,
6451 { "Activation/Deactivation",
6452 "mac-lte.control.activation-deactivation", FT_STRING, BASE_NONE,
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
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
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
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
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
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
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
6498 { &hf_mac_lte_control_activation_deactivation_reserved,
6500 "mac-lte.control.activation-deactivation.reserved", FT_UINT8, BASE_DEC,
6501 0, 0x01, "Reserved bit, should be 0", HFILL
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,
6511 { &hf_mac_lte_control_mch_scheduling_info_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
6517 { &hf_mac_lte_control_mch_scheduling_info_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
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,
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,
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,
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,
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,
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,
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,
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,
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,
6581 { &hf_mac_lte_failure_answering_sr,
6582 { "SR which failed",
6583 "mac-lte.ulsch.failure-answering-sr", FT_FRAMENUM, BASE_NONE, 0, 0x0,
6587 { &hf_mac_lte_sr_leading_to_failure,
6589 "mac-lte.ulsch.failure-answering-sr-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
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,
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,
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,
6612 { &hf_mac_lte_drx_config,
6613 { "DRX Configuration",
6614 "mac-lte.drx-config", FT_STRING, BASE_NONE,
6618 { &hf_mac_lte_drx_config_frame_num,
6620 "mac-lte.drx-config.config-frame", FT_FRAMENUM, BASE_NONE,
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,
6630 { &hf_mac_lte_drx_config_long_cycle,
6632 "mac-lte.drx-config.long-cycle", FT_UINT16, BASE_DEC,
6636 { &hf_mac_lte_drx_config_cycle_offset,
6638 "mac-lte.drx-config.cycle-offset", FT_UINT16, BASE_DEC,
6642 { &hf_mac_lte_drx_config_onduration_timer,
6643 { "OnDuration Timer",
6644 "mac-lte.drx-config.onduration-timer", FT_UINT16, BASE_DEC,
6648 { &hf_mac_lte_drx_config_inactivity_timer,
6649 { "Inactivity Timer",
6650 "mac-lte.drx-config.inactivity-timer", FT_UINT16, BASE_DEC,
6654 { &hf_mac_lte_drx_config_retransmission_timer,
6655 { "Retransmission Timer",
6656 "mac-lte.drx-config.retransmission-timer", FT_UINT16, BASE_DEC,
6660 { &hf_mac_lte_drx_config_short_cycle,
6662 "mac-lte.drx-config.short-cycle", FT_UINT16, BASE_DEC,
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,
6673 { &hf_mac_lte_drx_state,
6675 "mac-lte.drx-state", FT_STRING, BASE_NONE,
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,
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,
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,
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,
6703 { &hf_mac_lte_drx_state_inactivity_remaining,
6704 { "Inactivity remaining",
6705 "mac-lte.drx-state.inactivity-remaining", FT_UINT16, BASE_DEC,
6709 { &hf_mac_lte_drx_state_onduration_remaining,
6710 { "Onduration remaining",
6711 "mac-lte.drx-state.onduration-remaining", FT_UINT16, BASE_DEC,
6715 { &hf_mac_lte_drx_state_retransmission_remaining,
6716 { "Retransmission remaining",
6717 "mac-lte.drx-state.retransmission-remaining", FT_UINT16, BASE_DEC,
6721 { &hf_mac_lte_drx_state_rtt_remaining,
6723 "mac-lte.drx-state.rtt-remaining", FT_UINT16, BASE_DEC,
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,
6735 static gint *ett[] =
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,
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,
6760 &ett_mac_lte_drx_config,
6761 &ett_mac_lte_drx_state
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 }},
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},
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},
6815 module_t *mac_lte_module;
6816 expert_module_t* expert_mac_lte;
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"),
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));
6832 /* Allow other dissectors to find this one by name. */
6833 new_register_dissector("mac-lte", dissect_mac_lte, proto_mac_lte);
6835 /* Register the tap name */
6836 mac_lte_tap = register_tap("mac-lte");
6839 mac_lte_module = prefs_register_protocol(proto_mac_lte, NULL);
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");
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);
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);
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);
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 "
6868 &global_mac_lte_heur);
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);
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);
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);
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);
6891 lcid_drb_mappings_uat = uat_new("Static LCID -> drb Table",
6892 sizeof(lcid_drb_mapping_t),
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,
6903 lcid_drb_mapping_flds );
6905 prefs_register_uat_preference(mac_lte_module,
6907 "LCID -> DRB Mappings Table",
6908 "A table that maps from configurable lcids -> RLC logical channels",
6909 lcid_drb_mappings_uat);
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);
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);
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);
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);
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);
6937 register_init_routine(&mac_lte_init_protocol);
6940 void proto_reg_handoff_mac_lte(void)
6942 /* Add as a heuristic UDP dissector */
6943 heur_dissector_add("udp", dissect_mac_lte_heur, proto_mac_lte);
6945 /* Look up RLC dissector handle once and for all */
6946 rlc_lte_handle = find_dissector("rlc-lte");
6950 * Editor modelines - http://www.wireshark.org/tools/modelines.html
6955 * indent-tabs-mode: nil
6958 * vi: set shiftwidth=4 tabstop=8 expandtab:
6959 * :indentSize=4:tabSize=8:noTabs=true: