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"
39 * 3GPP TS 36.321 Evolved Universal Terrestrial Radio Access (E-UTRA)
40 * Medium Access Control (MAC) protocol specification v11.0.0
44 /* Initialize the protocol and registered fields. */
45 int proto_mac_lte
= -1;
47 static int mac_lte_tap
= -1;
49 static dissector_handle_t rlc_lte_handle
;
51 /* Decoding context */
52 static int hf_mac_lte_context
= -1;
53 static int hf_mac_lte_context_radio_type
= -1;
54 static int hf_mac_lte_context_direction
= -1;
55 static int hf_mac_lte_context_rnti
= -1;
56 static int hf_mac_lte_context_rnti_type
= -1;
57 static int hf_mac_lte_context_ueid
= -1;
58 static int hf_mac_lte_context_sysframe_number
= -1;
59 static int hf_mac_lte_context_subframe_number
= -1;
60 static int hf_mac_lte_context_grant_subframe_number
= -1;
61 static int hf_mac_lte_context_predefined_frame
= -1;
62 static int hf_mac_lte_context_length
= -1;
63 static int hf_mac_lte_context_ul_grant_size
= -1;
64 static int hf_mac_lte_context_bch_transport_channel
= -1;
65 static int hf_mac_lte_context_retx_count
= -1;
66 static int hf_mac_lte_context_retx_reason
= -1;
67 static int hf_mac_lte_context_crc_status
= -1;
68 static int hf_mac_lte_context_carrier_id
= -1;
70 static int hf_mac_lte_context_rapid
= -1;
71 static int hf_mac_lte_context_rach_attempt_number
= -1;
73 /* Inferred context */
74 static int hf_mac_lte_ues_ul_per_tti
= -1;
75 static int hf_mac_lte_ues_dl_per_tti
= -1;
78 /* Extra PHY context */
79 static int hf_mac_lte_context_phy_ul
= -1;
80 static int hf_mac_lte_context_phy_ul_modulation_type
= -1;
81 static int hf_mac_lte_context_phy_ul_tbs_index
= -1;
82 static int hf_mac_lte_context_phy_ul_resource_block_length
= -1;
83 static int hf_mac_lte_context_phy_ul_resource_block_start
= -1;
84 static int hf_mac_lte_context_phy_ul_harq_id
= -1;
85 static int hf_mac_lte_context_phy_ul_ndi
= -1;
87 static int hf_mac_lte_context_phy_dl
= -1;
88 static int hf_mac_lte_context_phy_dl_dci_format
= -1;
89 static int hf_mac_lte_context_phy_dl_resource_allocation_type
= -1;
90 static int hf_mac_lte_context_phy_dl_aggregation_level
= -1;
91 static int hf_mac_lte_context_phy_dl_mcs_index
= -1;
92 static int hf_mac_lte_context_phy_dl_redundancy_version_index
= -1;
93 static int hf_mac_lte_context_phy_dl_retx
= -1;
94 static int hf_mac_lte_context_phy_dl_resource_block_length
= -1;
95 static int hf_mac_lte_context_phy_dl_crc_status
= -1;
96 static int hf_mac_lte_context_phy_dl_harq_id
= -1;
97 static int hf_mac_lte_context_phy_dl_ndi
= -1;
98 static int hf_mac_lte_context_phy_dl_tb
= -1;
101 /* Out-of-band events */
102 static int hf_mac_lte_oob_send_preamble
= -1;
103 static int hf_mac_lte_number_of_srs
= -1;
105 /* MAC SCH/MCH header fields */
106 static int hf_mac_lte_ulsch
= -1;
107 static int hf_mac_lte_ulsch_header
= -1;
108 static int hf_mac_lte_dlsch
= -1;
109 static int hf_mac_lte_dlsch_header
= -1;
110 static int hf_mac_lte_sch_subheader
= -1;
111 static int hf_mac_lte_mch
= -1;
112 static int hf_mac_lte_mch_header
= -1;
113 static int hf_mac_lte_mch_subheader
= -1;
115 static int hf_mac_lte_sch_reserved
= -1;
116 static int hf_mac_lte_dlsch_lcid
= -1;
117 static int hf_mac_lte_ulsch_lcid
= -1;
118 static int hf_mac_lte_sch_extended
= -1;
119 static int hf_mac_lte_sch_format
= -1;
120 static int hf_mac_lte_sch_length
= -1;
121 static int hf_mac_lte_mch_reserved
= -1;
122 static int hf_mac_lte_mch_lcid
= -1;
123 static int hf_mac_lte_mch_extended
= -1;
124 static int hf_mac_lte_mch_format
= -1;
125 static int hf_mac_lte_mch_length
= -1;
127 static int hf_mac_lte_sch_header_only
= -1;
128 static int hf_mac_lte_mch_header_only
= -1;
131 static int hf_mac_lte_sch_sdu
= -1;
132 static int hf_mac_lte_mch_sdu
= -1;
133 static int hf_mac_lte_bch_pdu
= -1;
134 static int hf_mac_lte_pch_pdu
= -1;
135 static int hf_mac_lte_predefined_pdu
= -1;
136 static int hf_mac_lte_raw_pdu
= -1;
137 static int hf_mac_lte_padding_data
= -1;
138 static int hf_mac_lte_padding_length
= -1;
142 static int hf_mac_lte_rar
= -1;
143 static int hf_mac_lte_rar_headers
= -1;
144 static int hf_mac_lte_rar_header
= -1;
145 static int hf_mac_lte_rar_extension
= -1;
146 static int hf_mac_lte_rar_t
= -1;
147 static int hf_mac_lte_rar_bi
= -1;
148 static int hf_mac_lte_rar_rapid
= -1;
149 static int hf_mac_lte_rar_no_of_rapids
= -1;
150 static int hf_mac_lte_rar_reserved
= -1;
151 static int hf_mac_lte_rar_body
= -1;
152 static int hf_mac_lte_rar_reserved2
= -1;
153 static int hf_mac_lte_rar_ta
= -1;
154 static int hf_mac_lte_rar_ul_grant
= -1;
155 static int hf_mac_lte_rar_ul_grant_hopping
= -1;
156 static int hf_mac_lte_rar_ul_grant_fsrba
= -1;
157 static int hf_mac_lte_rar_ul_grant_tmcs
= -1;
158 static int hf_mac_lte_rar_ul_grant_tcsp
= -1;
159 static int hf_mac_lte_rar_ul_grant_ul_delay
= -1;
160 static int hf_mac_lte_rar_ul_grant_cqi_request
= -1;
161 static int hf_mac_lte_rar_temporary_crnti
= -1;
163 /* Common channel control values */
164 static int hf_mac_lte_control_bsr
= -1;
165 static int hf_mac_lte_control_bsr_lcg_id
= -1;
166 static int hf_mac_lte_control_short_bsr_buffer_size
= -1;
167 static int hf_mac_lte_control_long_bsr_buffer_size_0
= -1;
168 static int hf_mac_lte_control_long_bsr_buffer_size_1
= -1;
169 static int hf_mac_lte_control_long_bsr_buffer_size_2
= -1;
170 static int hf_mac_lte_control_long_bsr_buffer_size_3
= -1;
171 static int hf_mac_lte_control_short_ext_bsr_buffer_size
= -1;
172 static int hf_mac_lte_control_long_ext_bsr_buffer_size_0
= -1;
173 static int hf_mac_lte_control_long_ext_bsr_buffer_size_1
= -1;
174 static int hf_mac_lte_control_long_ext_bsr_buffer_size_2
= -1;
175 static int hf_mac_lte_control_long_ext_bsr_buffer_size_3
= -1;
176 static int hf_mac_lte_control_crnti
= -1;
177 static int hf_mac_lte_control_timing_advance
= -1;
178 static int hf_mac_lte_control_timing_advance_group_id
= -1;
179 static int hf_mac_lte_control_timing_advance_command
= -1;
180 static int hf_mac_lte_control_ue_contention_resolution
= -1;
181 static int hf_mac_lte_control_ue_contention_resolution_identity
= -1;
182 static int hf_mac_lte_control_ue_contention_resolution_msg3
= -1;
183 static int hf_mac_lte_control_ue_contention_resolution_msg3_matched
= -1;
184 static int hf_mac_lte_control_ue_contention_resolution_time_since_msg3
= -1;
185 static int hf_mac_lte_control_power_headroom
= -1;
186 static int hf_mac_lte_control_power_headroom_reserved
= -1;
187 static int hf_mac_lte_control_power_headroom_level
= -1;
188 static int hf_mac_lte_control_ext_power_headroom
= -1;
189 static int hf_mac_lte_control_ext_power_headroom_c7
= -1;
190 static int hf_mac_lte_control_ext_power_headroom_c6
= -1;
191 static int hf_mac_lte_control_ext_power_headroom_c5
= -1;
192 static int hf_mac_lte_control_ext_power_headroom_c4
= -1;
193 static int hf_mac_lte_control_ext_power_headroom_c3
= -1;
194 static int hf_mac_lte_control_ext_power_headroom_c2
= -1;
195 static int hf_mac_lte_control_ext_power_headroom_c1
= -1;
196 static int hf_mac_lte_control_ext_power_headroom_reserved
= -1;
197 static int hf_mac_lte_control_ext_power_headroom_power_backoff
= -1;
198 static int hf_mac_lte_control_ext_power_headroom_value
= -1;
199 static int hf_mac_lte_control_ext_power_headroom_level
= -1;
200 static int hf_mac_lte_control_ext_power_headroom_reserved2
= -1;
201 static int hf_mac_lte_control_ext_power_headroom_pcmaxc
= -1;
202 static int hf_mac_lte_control_activation_deactivation
= -1;
203 static int hf_mac_lte_control_activation_deactivation_c7
= -1;
204 static int hf_mac_lte_control_activation_deactivation_c6
= -1;
205 static int hf_mac_lte_control_activation_deactivation_c5
= -1;
206 static int hf_mac_lte_control_activation_deactivation_c4
= -1;
207 static int hf_mac_lte_control_activation_deactivation_c3
= -1;
208 static int hf_mac_lte_control_activation_deactivation_c2
= -1;
209 static int hf_mac_lte_control_activation_deactivation_c1
= -1;
210 static int hf_mac_lte_control_activation_deactivation_reserved
= -1;
211 static int hf_mac_lte_control_mch_scheduling_info
= -1;
212 static int hf_mac_lte_control_mch_scheduling_info_lcid
= -1;
213 static int hf_mac_lte_control_mch_scheduling_info_stop_mtch
= -1;
215 static int hf_mac_lte_dl_harq_resend_original_frame
= -1;
216 static int hf_mac_lte_dl_harq_resend_time_since_previous_frame
= -1;
217 static int hf_mac_lte_dl_harq_resend_next_frame
= -1;
218 static int hf_mac_lte_dl_harq_resend_time_until_next_frame
= -1;
220 static int hf_mac_lte_ul_harq_resend_original_frame
= -1;
221 static int hf_mac_lte_ul_harq_resend_time_since_previous_frame
= -1;
222 static int hf_mac_lte_ul_harq_resend_next_frame
= -1;
223 static int hf_mac_lte_ul_harq_resend_time_until_next_frame
= -1;
225 static int hf_mac_lte_grant_answering_sr
= -1;
226 static int hf_mac_lte_failure_answering_sr
= -1;
227 static int hf_mac_lte_sr_leading_to_failure
= -1;
228 static int hf_mac_lte_sr_leading_to_grant
= -1;
229 static int hf_mac_lte_sr_time_since_request
= -1;
230 static int hf_mac_lte_sr_time_until_answer
= -1;
232 static int hf_mac_lte_drx_config
= -1;
233 static int hf_mac_lte_drx_config_frame_num
= -1;
234 static int hf_mac_lte_drx_config_previous_frame_num
= -1;
235 static int hf_mac_lte_drx_config_long_cycle
= -1;
236 static int hf_mac_lte_drx_config_cycle_offset
= -1;
237 static int hf_mac_lte_drx_config_onduration_timer
= -1;
238 static int hf_mac_lte_drx_config_inactivity_timer
= -1;
239 static int hf_mac_lte_drx_config_retransmission_timer
= -1;
240 static int hf_mac_lte_drx_config_short_cycle
= -1;
241 static int hf_mac_lte_drx_config_short_cycle_timer
= -1;
243 static int hf_mac_lte_drx_state
= -1;
244 static int hf_mac_lte_drx_state_long_cycle_offset
= -1;
245 static int hf_mac_lte_drx_state_long_cycle_on
= -1;
246 static int hf_mac_lte_drx_state_short_cycle_offset
= -1;
247 static int hf_mac_lte_drx_state_short_cycle_on
= -1;
248 static int hf_mac_lte_drx_state_inactivity_remaining
= -1;
249 static int hf_mac_lte_drx_state_onduration_remaining
= -1;
250 static int hf_mac_lte_drx_state_retransmission_remaining
= -1;
251 static int hf_mac_lte_drx_state_rtt_remaining
= -1;
252 static int hf_mac_lte_drx_state_short_cycle_remaining
= -1;
255 static int ett_mac_lte
= -1;
256 static int ett_mac_lte_context
= -1;
257 static int ett_mac_lte_phy_context
= -1;
258 static int ett_mac_lte_ulsch_header
= -1;
259 static int ett_mac_lte_dlsch_header
= -1;
260 static int ett_mac_lte_mch_header
= -1;
261 static int ett_mac_lte_sch_subheader
= -1;
262 static int ett_mac_lte_mch_subheader
= -1;
263 static int ett_mac_lte_rar_headers
= -1;
264 static int ett_mac_lte_rar_header
= -1;
265 static int ett_mac_lte_rar_body
= -1;
266 static int ett_mac_lte_rar_ul_grant
= -1;
267 static int ett_mac_lte_bsr
= -1;
268 static int ett_mac_lte_bch
= -1;
269 static int ett_mac_lte_pch
= -1;
270 static int ett_mac_lte_activation_deactivation
= -1;
271 static int ett_mac_lte_contention_resolution
= -1;
272 static int ett_mac_lte_timing_advance
= -1;
273 static int ett_mac_lte_power_headroom
= -1;
274 static int ett_mac_lte_extended_power_headroom
= -1;
275 static int ett_mac_lte_extended_power_headroom_cell
= -1;
276 static int ett_mac_lte_mch_scheduling_info
= -1;
277 static int ett_mac_lte_oob
= -1;
278 static int ett_mac_lte_drx_config
= -1;
279 static int ett_mac_lte_drx_state
= -1;
281 static expert_field ei_mac_lte_context_rnti_type
= EI_INIT
;
282 static expert_field ei_mac_lte_lcid_unexpected
= EI_INIT
;
283 static expert_field ei_mac_lte_ul_mac_frame_retx
= EI_INIT
;
284 static expert_field ei_mac_lte_oob_sr_failure
= EI_INIT
;
285 static expert_field ei_mac_lte_control_timing_advance_command_correction_needed
= EI_INIT
;
286 static expert_field ei_mac_lte_sch_header_only
= EI_INIT
;
287 static expert_field ei_mac_lte_control_timing_advance_command_no_correction
= EI_INIT
;
288 static expert_field ei_mac_lte_rar_timing_advance_not_zero_note
= EI_INIT
;
289 static expert_field ei_mac_lte_padding_data_start_and_end
= EI_INIT
;
290 static expert_field ei_mac_lte_bch_pdu
= EI_INIT
;
291 static expert_field ei_mac_lte_rach_preamble_sent_note
= EI_INIT
;
292 static expert_field ei_mac_lte_pch_pdu
= EI_INIT
;
293 static expert_field ei_mac_lte_ul_harq_resend_next_frame
= EI_INIT
;
294 static expert_field ei_mac_lte_control_bsr_multiple
= EI_INIT
;
295 static expert_field ei_mac_lte_padding_data_multiple
= EI_INIT
;
296 static expert_field ei_mac_lte_context_sysframe_number
= EI_INIT
;
297 static expert_field ei_mac_lte_rar_bi_present
= EI_INIT
;
298 static expert_field ei_mac_lte_control_element_size_invalid
= EI_INIT
;
299 static expert_field ei_mac_lte_bsr_warn_threshold_exceeded
= EI_INIT
;
300 static expert_field ei_mac_lte_too_many_subheaders
= EI_INIT
;
301 static expert_field ei_mac_lte_oob_send_sr
= EI_INIT
;
302 static expert_field ei_mac_lte_orig_tx_ul_frame_not_found
= EI_INIT
;
303 static expert_field ei_mac_lte_control_ue_contention_resolution_msg3_matched
= EI_INIT
;
304 static expert_field ei_mac_lte_sr_results_not_grant_or_failure_indication
= EI_INIT
;
305 static expert_field ei_mac_lte_context_crc_status
= EI_INIT
;
306 static expert_field ei_mac_lte_sr_invalid_event
= EI_INIT
;
307 static expert_field ei_mac_lte_control_subheader_after_data_subheader
= EI_INIT
;
308 static expert_field ei_mac_lte_rar_bi_not_first_subheader
= EI_INIT
;
309 static expert_field ei_mac_lte_context_length
= EI_INIT
;
310 static expert_field ei_mac_lte_reserved_not_zero
= EI_INIT
;
311 static expert_field ei_mac_lte_rar_timing_advance_not_zero_warn
= EI_INIT
;
312 static expert_field ei_mac_lte_dlsch_lcid
= EI_INIT
;
313 static expert_field ei_mac_lte_padding_data_before_control_subheader
= EI_INIT
;
314 static expert_field ei_mac_lte_rach_preamble_sent_warn
= EI_INIT
;
317 /* Constants and value strings */
319 static const value_string radio_type_vals
[] =
327 static const value_string direction_vals
[] =
329 { DIRECTION_UPLINK
, "Uplink"},
330 { DIRECTION_DOWNLINK
, "Downlink"},
335 static const value_string rnti_type_vals
[] =
337 { NO_RNTI
, "NO-RNTI"},
339 { RA_RNTI
, "RA-RNTI"},
341 { SI_RNTI
, "SI-RNTI"},
342 { SPS_RNTI
, "SPS-RNTI"},
347 static const value_string bch_transport_channel_vals
[] =
349 { SI_RNTI
, "DL-SCH"},
354 static const value_string crc_status_vals
[] =
356 { crc_success
, "OK"},
357 { crc_fail
, "Failed"},
358 { crc_high_code_rate
, "High Code Rate"},
359 { crc_pdsch_lost
, "PDSCH Lost"},
360 { crc_duplicate_nonzero_rv
, "Duplicate_nonzero_rv"},
361 { crc_false_dci
, "False DCI"},
365 static const value_string carrier_id_vals
[] =
367 { carrier_id_primary
, "Primary"},
368 { carrier_id_secondary_1
, "Secondary-1"},
369 { carrier_id_secondary_2
, "Secondary-2"},
370 { carrier_id_secondary_3
, "Secondary-3"},
371 { carrier_id_secondary_4
, "Secondary-4"},
375 static const value_string dci_format_vals
[] =
389 static const value_string aggregation_level_vals
[] =
398 static const value_string modulation_type_vals
[] =
406 static const true_false_string mac_lte_scell_ph_vals
= {
411 static const true_false_string mac_lte_power_backoff_vals
= {
416 static const true_false_string mac_lte_ph_value_vals
= {
417 "Based on reference format",
418 "Based on real transmission"
421 static const true_false_string mac_lte_scell_status_vals
= {
426 #define ACTIVATION_DEACTIVATION_LCID 0x1b
427 #define UE_CONTENTION_RESOLUTION_IDENTITY_LCID 0x1c
428 #define TIMING_ADVANCE_LCID 0x1d
429 #define DRX_COMMAND_LCID 0x1e
430 #define PADDING_LCID 0x1f
432 static const value_string dlsch_lcid_vals
[] =
445 { ACTIVATION_DEACTIVATION_LCID
, "Activation/Deactivation"},
446 { UE_CONTENTION_RESOLUTION_IDENTITY_LCID
, "UE Contention Resolution Identity"},
447 { TIMING_ADVANCE_LCID
, "Timing Advance"},
448 { DRX_COMMAND_LCID
, "DRX Command"},
449 { PADDING_LCID
, "Padding" },
453 #define EXTENDED_POWER_HEADROOM_REPORT_LCID 0x19
454 #define POWER_HEADROOM_REPORT_LCID 0x1a
455 #define CRNTI_LCID 0x1b
456 #define TRUNCATED_BSR_LCID 0x1c
457 #define SHORT_BSR_LCID 0x1d
458 #define LONG_BSR_LCID 0x1e
460 static const value_string ulsch_lcid_vals
[] =
473 { EXTENDED_POWER_HEADROOM_REPORT_LCID
, "Extended Power Headroom Report"},
474 { POWER_HEADROOM_REPORT_LCID
, "Power Headroom Report"},
475 { CRNTI_LCID
, "C-RNTI"},
476 { TRUNCATED_BSR_LCID
, "Truncated BSR"},
477 { SHORT_BSR_LCID
, "Short BSR"},
478 { LONG_BSR_LCID
, "Long BSR"},
479 { PADDING_LCID
, "Padding" },
483 #define MCH_SCHEDULING_INFO_LCID 0x1e
485 static const value_string mch_lcid_vals
[] =
516 { MCH_SCHEDULING_INFO_LCID
, "MCH Scheduling Information"},
517 { PADDING_LCID
, "Padding" },
521 static const value_string format_vals
[] =
523 { 0, "Data length is < 128 bytes"},
524 { 1, "Data length is >= 128 bytes"},
529 static const value_string rar_type_vals
[] =
531 { 0, "Backoff Indicator present"},
532 { 1, "RAPID present"},
537 static const value_string rar_bi_vals
[] =
556 static const value_string buffer_size_vals
[] =
559 { 1, "0 < BS <= 10"},
560 { 2, "10 < BS <= 12"},
561 { 3, "12 < BS <= 14"},
562 { 4, "14 < BS <= 17"},
563 { 5, "17 < BS <= 19"},
564 { 6, "19 < BS <= 22"},
565 { 7, "22 < BS <= 26"},
566 { 8, "26 < BS <= 31"},
567 { 9, "31 < BS <= 36"},
568 { 10, "36 < BS <= 42"},
569 { 11, "42 < BS <= 49"},
570 { 12, "49 < BS <= 57"},
571 { 13, "47 < BS <= 67"},
572 { 14, "67 < BS <= 78"},
573 { 15, "78 < BS <= 91"},
574 { 16, "91 < BS <= 107"},
575 { 17, "107 < BS <= 125"},
576 { 18, "125 < BS <= 146"},
577 { 19, "146 < BS <= 171"},
578 { 20, "171 < BS <= 200"},
579 { 21, "200 < BS <= 234"},
580 { 22, "234 < BS <= 274"},
581 { 23, "274 < BS <= 321"},
582 { 24, "321 < BS <= 376"},
583 { 25, "376 < BS <= 440"},
584 { 26, "440 < BS <= 515"},
585 { 27, "515 < BS <= 603"},
586 { 28, "603 < BS <= 706"},
587 { 29, "706 < BS <= 826"},
588 { 30, "826 < BS <= 967"},
589 { 31, "967 < BS <= 1132"},
590 { 32, "1132 < BS <= 1326"},
591 { 33, "1326 < BS <= 1552"},
592 { 34, "1552 < BS <= 1817"},
593 { 35, "1817 < BS <= 2127"},
594 { 36, "2127 < BS <= 2490"},
595 { 37, "2490 < BS <= 2915"},
596 { 38, "2915 < BS <= 3413"},
597 { 39, "3413 < BS <= 3995"},
598 { 40, "3995 < BS <= 4677"},
599 { 41, "4677 < BS <= 5476"},
600 { 42, "5476 < BS <= 6411"},
601 { 43, "6411 < BS <= 7505"},
602 { 44, "7505 < BS <= 8787"},
603 { 45, "8787 < BS <= 10276"},
604 { 46, "10287 < BS <= 12043"},
605 { 47, "12043 < BS <= 14099"},
606 { 48, "14099 < BS <= 16507"},
607 { 49, "16507 < BS <= 19325"},
608 { 50, "19325 < BS <= 22624"},
609 { 51, "22624 < BS <= 26487"},
610 { 52, "26487 < BS <= 31009"},
611 { 53, "31009 < BS <= 36304"},
612 { 54, "36304 < BS <= 42502"},
613 { 55, "42502 < BS <= 49759"},
614 { 56, "49759 < BS <= 58255"},
615 { 57, "58255 < BS <= 68201"},
616 { 58, "68201 < BS <= 79846"},
617 { 59, "79846 < BS <= 93479"},
618 { 60, "93479 < BS <= 109439"},
619 { 61, "109439 < BS <= 128125"},
620 { 62, "128125 < BS <= 150000"},
621 { 63, "BS > 150000"},
624 static value_string_ext buffer_size_vals_ext
= VALUE_STRING_EXT_INIT(buffer_size_vals
);
626 static const value_string ext_buffer_size_vals
[] =
629 { 1, "0 < BS <= 10"},
630 { 2, "10 < BS <= 13"},
631 { 3, "13 < BS <= 16"},
632 { 4, "16 < BS <= 19"},
633 { 5, "19 < BS <= 23"},
634 { 6, "23 < BS <= 29"},
635 { 7, "29 < BS <= 35"},
636 { 8, "35 < BS <= 43"},
637 { 9, "43 < BS <= 53"},
638 { 10, "53 < BS <= 65"},
639 { 11, "65 < BS <= 80"},
640 { 12, "80 < BS <= 98"},
641 { 13, "98 < BS <= 120"},
642 { 14, "120 < BS <= 147"},
643 { 15, "147 < BS <= 181"},
644 { 16, "181 < BS <= 223"},
645 { 17, "223 < BS <= 274"},
646 { 18, "274 < BS <= 337"},
647 { 19, "337 < BS <= 414"},
648 { 20, "414 < BS <= 509"},
649 { 21, "509 < BS <= 625"},
650 { 22, "625 < BS <= 769"},
651 { 23, "769 < BS <= 945"},
652 { 24, "945 < BS <= 1162"},
653 { 25, "1162 < BS <= 1429"},
654 { 26, "1429 < BS <= 1757"},
655 { 27, "1757 < BS <= 2161"},
656 { 28, "2161 < BS <= 2657"},
657 { 29, "2657 < BS <= 3267"},
658 { 30, "3267 < BS <= 4017"},
659 { 31, "4017 < BS <= 4940"},
660 { 32, "4940 < BS <= 6074"},
661 { 33, "6074 < BS <= 7469"},
662 { 34, "7469 < BS <= 9185"},
663 { 35, "9185 < BS <= 11294"},
664 { 36, "11294 < BS <= 13888"},
665 { 37, "13888 < BS <= 17077"},
666 { 38, "17077 < BS <= 20999"},
667 { 39, "20999 < BS <= 25822"},
668 { 40, "25822 < BS <= 31752"},
669 { 41, "31752 < BS <= 39045"},
670 { 42, "39045 < BS <= 48012"},
671 { 43, "48012 < BS <= 59039"},
672 { 44, "59039 < BS <= 72598"},
673 { 45, "72598 < BS <= 89272"},
674 { 46, "89272 < BS <= 109774"},
675 { 47, "109774 < BS <= 134986"},
676 { 48, "134986 < BS <= 165989"},
677 { 49, "165989 < BS <= 204111"},
678 { 50, "204111 < BS <= 250990"},
679 { 51, "250990 < BS <= 308634"},
680 { 52, "308634 < BS <= 379519"},
681 { 53, "379519 < BS <= 466683"},
682 { 54, "466683 < BS <= 573866"},
683 { 55, "573866 < BS <= 705666"},
684 { 56, "705666 < BS <= 867737"},
685 { 57, "867737 < BS <= 1067031"},
686 { 58, "1067031 < BS <= 1312097"},
687 { 59, "1312097 < BS <= 1613447"},
688 { 60, "1613447 < BS <= 1984009"},
689 { 61, "1984009 < BS <= 2439678"},
690 { 62, "2439678 < BS <= 3000000"},
691 { 63, "BS > 3000000"},
694 static value_string_ext ext_buffer_size_vals_ext
= VALUE_STRING_EXT_INIT(ext_buffer_size_vals
);
696 static const value_string power_headroom_vals
[] =
698 { 0, "-23 <= PH < -22"},
699 { 1, "-22 <= PH < -21"},
700 { 2, "-21 <= PH < -20"},
701 { 3, "-20 <= PH < -19"},
702 { 4, "-19 <= PH < -18"},
703 { 5, "-18 <= PH < -17"},
704 { 6, "-17 <= PH < -16"},
705 { 7, "-16 <= PH < -15"},
706 { 8, "-15 <= PH < -14"},
707 { 9, "-14 <= PH < -13"},
708 { 10, "-13 <= PH < -12"},
709 { 11, "-12 <= PH < -11"},
710 { 12, "-11 <= PH < -10"},
711 { 13, "-10 <= PH < -9"},
712 { 14, "-9 <= PH < -8"},
713 { 15, "-8 <= PH < -7"},
714 { 16, "-7 <= PH < -6"},
715 { 17, "-6 <= PH < -5"},
716 { 18, "-5 <= PH < -4"},
717 { 19, "-4 <= PH < -3"},
718 { 20, "-3 <= PH < -2"},
719 { 21, "-2 <= PH < -1"},
720 { 22, "-1 <= PH < 0"},
721 { 23, "0 <= PH < 1"},
722 { 24, "1 <= PH < 2"},
723 { 25, "2 <= PH < 3"},
724 { 26, "3 <= PH < 4"},
725 { 27, "4 <= PH < 5"},
726 { 28, "5 <= PH < 6"},
727 { 29, "6 <= PH < 7"},
728 { 30, "7 <= PH < 8"},
729 { 31, "8 <= PH < 9"},
730 { 32, "9 <= PH < 10"},
731 { 33, "10 <= PH < 11"},
732 { 34, "11 <= PH < 12"},
733 { 35, "12 <= PH < 13"},
734 { 36, "13 <= PH < 14"},
735 { 37, "14 <= PH < 15"},
736 { 38, "15 <= PH < 16"},
737 { 39, "16 <= PH < 17"},
738 { 40, "17 <= PH < 18"},
739 { 41, "18 <= PH < 19"},
740 { 42, "19 <= PH < 20"},
741 { 43, "20 <= PH < 21"},
742 { 44, "21 <= PH < 22"},
743 { 45, "22 <= PH < 23"},
744 { 46, "23 <= PH < 24"},
745 { 47, "24 <= PH < 25"},
746 { 48, "25 <= PH < 26"},
747 { 49, "26 <= PH < 27"},
748 { 50, "27 <= PH < 28"},
749 { 51, "28 <= PH < 29"},
750 { 52, "29 <= PH < 30"},
751 { 53, "30 <= PH < 31"},
752 { 54, "31 <= PH < 32"},
753 { 55, "32 <= PH < 33"},
754 { 56, "33 <= PH < 34"},
755 { 57, "34 <= PH < 35"},
756 { 58, "34 <= PH < 36"},
757 { 59, "36 <= PH < 37"},
758 { 60, "37 <= PH < 38"},
759 { 61, "38 <= PH < 39"},
760 { 62, "39 <= PH < 40"},
764 static value_string_ext power_headroom_vals_ext
= VALUE_STRING_EXT_INIT(power_headroom_vals
);
766 static const value_string pcmaxc_vals
[] =
768 { 0, "Pcmax,c < -29"},
769 { 1, "-29 <= Pcmax,c < -28"},
770 { 2, "-28 <= Pcmax,c < -27"},
771 { 3, "-27 <= Pcmax,c < -26"},
772 { 4, "-26 <= Pcmax,c < -25"},
773 { 5, "-25 <= Pcmax,c < -24"},
774 { 6, "-24 <= Pcmax,c < -23"},
775 { 7, "-23 <= Pcmax,c < -22"},
776 { 8, "-22 <= Pcmax,c < -21"},
777 { 9, "-21 <= Pcmax,c < -20"},
778 { 10, "-20 <= Pcmax,c < -19"},
779 { 11, "-19 <= Pcmax,c < -18"},
780 { 12, "-18 <= Pcmax,c < -17"},
781 { 13, "-17 <= Pcmax,c < -16"},
782 { 14, "-16 <= Pcmax,c < -15"},
783 { 15, "-15 <= Pcmax,c < -14"},
784 { 16, "-14 <= Pcmax,c < -13"},
785 { 17, "-13 <= Pcmax,c < -12"},
786 { 18, "-12 <= Pcmax,c < -11"},
787 { 19, "-11 <= Pcmax,c < -10"},
788 { 20, "-10 <= Pcmax,c < -9"},
789 { 21, "-9 <= Pcmax,c < -8"},
790 { 22, "-8 <= Pcmax,c < -7"},
791 { 23, "-7 <= Pcmax,c < -6"},
792 { 24, "-6 <= Pcmax,c < -5"},
793 { 25, "-5 <= Pcmax,c < -4"},
794 { 26, "-4 <= Pcmax,c < -3"},
795 { 27, "-3 <= Pcmax,c < -2"},
796 { 28, "-2 <= Pcmax,c < -1"},
797 { 29, "-1 <= Pcmax,c < 0"},
798 { 30, "0 <= Pcmax,c < 1"},
799 { 31, "1 <= Pcmax,c < 2"},
800 { 32, "2 <= Pcmax,c < 3"},
801 { 33, "3 <= Pcmax,c < 4"},
802 { 34, "4 <= Pcmax,c < 5"},
803 { 35, "5 <= Pcmax,c < 6"},
804 { 36, "6 <= Pcmax,c < 7"},
805 { 37, "7 <= Pcmax,c < 8"},
806 { 38, "8 <= Pcmax,c < 9"},
807 { 39, "9 <= Pcmax,c < 10"},
808 { 40, "10 <= Pcmax,c < 11"},
809 { 41, "11 <= Pcmax,c < 12"},
810 { 42, "12 <= Pcmax,c < 13"},
811 { 43, "13 <= Pcmax,c < 14"},
812 { 44, "14 <= Pcmax,c < 15"},
813 { 45, "15 <= Pcmax,c < 16"},
814 { 46, "16 <= Pcmax,c < 17"},
815 { 47, "17 <= Pcmax,c < 18"},
816 { 48, "18 <= Pcmax,c < 19"},
817 { 49, "19 <= Pcmax,c < 20"},
818 { 50, "20 <= Pcmax,c < 21"},
819 { 51, "21 <= Pcmax,c < 22"},
820 { 52, "22 <= Pcmax,c < 23"},
821 { 53, "23 <= Pcmax,c < 24"},
822 { 54, "24 <= Pcmax,c < 25"},
823 { 55, "25 <= Pcmax,c < 26"},
824 { 56, "26 <= Pcmax,c < 27"},
825 { 57, "27 <= Pcmax,c < 28"},
826 { 58, "28 <= Pcmax,c < 29"},
827 { 59, "29 <= Pcmax,c < 30"},
828 { 60, "30 <= Pcmax,c < 31"},
829 { 61, "31 <= Pcmax,c < 32"},
830 { 62, "32 <= Pcmax,c < 33"},
831 { 63, "33 <= Pcmax,c"},
834 static value_string_ext pcmaxc_vals_ext
= VALUE_STRING_EXT_INIT(pcmaxc_vals
);
836 static const value_string header_only_vals
[] =
838 { 0, "MAC PDU Headers and body present"},
839 { 1, "MAC PDU Headers only"},
843 static const value_string predefined_frame_vals
[] =
845 { 0, "Real MAC PDU present - will dissect"},
846 { 1, "Predefined frame present - will not dissect"},
850 static const value_string ul_retx_grant_vals
[] =
857 /**************************************************************************/
858 /* Preferences state */
859 /**************************************************************************/
861 /* If this PDU has been NACK'd (by HARQ) more than a certain number of times,
862 we trigger an expert warning. */
863 static gint global_mac_lte_retx_counter_trigger
= 3;
865 /* By default try to decode transparent data (BCH, PCH and CCCH) data using LTE RRC dissector */
866 static gboolean global_mac_lte_attempt_rrc_decode
= TRUE
;
868 /* Whether should attempt to dissect frames failing CRC check */
869 static gboolean global_mac_lte_dissect_crc_failures
= FALSE
;
871 /* Whether should attempt to decode lcid 1&2 SDUs as srb1/2 (i.e. AM RLC) */
872 static gboolean global_mac_lte_attempt_srb_decode
= TRUE
;
874 /* Whether should attempt to decode MCH LCID 0 as MCCH */
875 static gboolean global_mac_lte_attempt_mcch_decode
= FALSE
;
877 /* Whether should call RLC dissector to decode MTCH LCIDs */
878 static gboolean global_mac_lte_call_rlc_for_mtch
= FALSE
;
880 /* Where to take LCID -> DRB mappings from */
881 enum lcid_drb_source
{
882 FromStaticTable
, FromConfigurationProtocol
884 static gint global_mac_lte_lcid_drb_source
= (gint
)FromStaticTable
;
886 /* Threshold for warning in expert info about high BSR values */
887 static gint global_mac_lte_bsr_warn_threshold
= 50; /* default is 19325 -> 22624 */
889 /* Whether or not to track SRs and related frames */
890 static gboolean global_mac_lte_track_sr
= TRUE
;
892 /* Which layer info to show in the info column */
894 ShowPHYLayer
, ShowMACLayer
, ShowRLCLayer
897 /* Which layer's details to show in Info column */
898 static gint global_mac_lte_layer_to_show
= (gint
)ShowRLCLayer
;
900 /* Whether to decode Contention Resolution body as UL CCCH */
901 static gboolean global_mac_lte_decode_cr_body
= FALSE
;
903 /* Whether to record config and try to show DRX state for each configured UE */
904 static gboolean global_mac_lte_show_drx
= FALSE
;
908 /* When showing RLC info, count PDUs so can append info column properly */
909 static guint8 s_number_of_rlc_pdus_shown
= 0;
911 /***********************************************************************/
912 /* How to dissect lcid 3-10 (presume drb logical channels) */
914 static const value_string drb_lcid_vals
[] = {
926 typedef enum rlc_channel_type_t
{
932 } rlc_channel_type_t
;
934 static const value_string rlc_channel_type_vals
[] = {
936 { rlcUM5
, "UM, SN Len=5"},
937 { rlcUM10
, "UM, SN Len=10"},
944 typedef struct lcid_drb_mapping_t
{
947 rlc_channel_type_t channel_type
;
948 } lcid_drb_mapping_t
;
951 static lcid_drb_mapping_t
*lcid_drb_mappings
= NULL
;
952 static guint num_lcid_drb_mappings
= 0;
954 UAT_VS_DEF(lcid_drb_mappings
, lcid
, lcid_drb_mapping_t
, guint16
, 3, "LCID 3")
955 UAT_DEC_CB_DEF(lcid_drb_mappings
, drbid
, lcid_drb_mapping_t
)
956 UAT_VS_DEF(lcid_drb_mappings
, channel_type
, lcid_drb_mapping_t
, rlc_channel_type_t
, rlcAM
, "AM")
959 static uat_t
* lcid_drb_mappings_uat
;
961 /* Dynamic mappings (set by configuration protocol)
962 LCID is the index into the array of these */
963 typedef struct dynamic_lcid_drb_mapping_t
{
966 rlc_channel_type_t channel_type
;
968 } dynamic_lcid_drb_mapping_t
;
970 typedef struct ue_dynamic_drb_mappings_t
{
971 dynamic_lcid_drb_mapping_t mapping
[11]; /* Index is LCID */
972 guint8 drb_to_lcid_mappings
[32]; /* Also map drbid -> lcid */
973 } ue_dynamic_drb_mappings_t
;
975 static GHashTable
*mac_lte_ue_channels_hash
= NULL
;
978 extern int proto_rlc_lte
;
980 /***************************************************************/
984 /***************************************************************/
985 /* Keeping track of Msg3 bodies so they can be compared with */
986 /* Contention Resolution bodies. */
988 typedef struct Msg3Data
{
995 /* This table stores (RNTI -> Msg3Data*). Will be populated when
996 Msg3 frames are first read. */
997 static GHashTable
*mac_lte_msg3_hash
= NULL
;
999 /* Hash table functions for mac_lte_msg3_hash. Hash is just the (RNTI) key */
1000 static gint
mac_lte_rnti_hash_equal(gconstpointer v
, gconstpointer v2
)
1005 static guint
mac_lte_rnti_hash_func(gconstpointer v
)
1007 return GPOINTER_TO_UINT(v
);
1011 typedef enum ContentionResolutionStatus
{
1015 } ContentionResolutionStatus
;
1017 typedef struct ContentionResolutionResult
{
1018 ContentionResolutionStatus status
;
1021 } ContentionResolutionResult
;
1024 /* This table stores (CRFrameNum -> CRResult). It is assigned during the first
1025 pass and used thereafter */
1026 static GHashTable
*mac_lte_cr_result_hash
= NULL
;
1028 /* Hash table functions for mac_lte_cr_result_hash. Hash is just the (framenum) key */
1029 static gint
mac_lte_framenum_hash_equal(gconstpointer v
, gconstpointer v2
)
1034 static guint
mac_lte_framenum_hash_func(gconstpointer v
)
1036 return GPOINTER_TO_UINT(v
);
1039 /**************************************************************************/
1043 /****************************************************************/
1044 /* Keeping track of last DL frames per C-RNTI so can guess when */
1045 /* there has been a HARQ retransmission */
1046 /* TODO: this should be simplified now that harq-id & ndi are */
1049 /* Could be bigger, but more than enough to flag suspected resends */
1050 #define MAX_EXPECTED_PDU_LENGTH 2048
1052 typedef struct LastFrameData
{
1056 nstime_t received_time
;
1058 guint8 data
[MAX_EXPECTED_PDU_LENGTH
];
1061 typedef struct DLHarqBuffers
{
1062 LastFrameData harqid
[2][15]; /* 2 blocks (1 for each antenna) needed for DL */
1066 /* This table stores (RNTI -> DLHARQBuffers*). Will be populated when
1067 DL frames are first read. */
1068 static GHashTable
*mac_lte_dl_harq_hash
= NULL
;
1070 typedef struct DLHARQResult
{
1071 gboolean previousSet
, nextSet
;
1072 guint previousFrameNum
;
1073 guint timeSincePreviousFrame
;
1075 guint timeToNextFrame
;
1079 /* This table stores (FrameNumber -> *DLHARQResult). It is assigned during the first
1080 pass and used thereafter */
1081 static GHashTable
*mac_lte_dl_harq_result_hash
= NULL
;
1083 /**************************************************************************/
1086 /*****************************************************************/
1087 /* Keeping track of last UL frames per C-RNTI so can verify when */
1088 /* told that a frame is a retx */
1090 typedef struct ULHarqBuffers
{
1091 LastFrameData harqid
[8];
1095 /* This table stores (RNTI -> ULHarqBuffers*). Will be populated when
1096 UL frames are first read. */
1097 static GHashTable
*mac_lte_ul_harq_hash
= NULL
;
1099 typedef struct ULHARQResult
{
1100 gboolean previousSet
, nextSet
;
1101 guint previousFrameNum
;
1102 guint timeSincePreviousFrame
;
1104 guint timeToNextFrame
;
1108 /* This table stores (FrameNum -> ULHARQResult). It is assigned during the first
1109 pass and used thereafter */
1110 static GHashTable
*mac_lte_ul_harq_result_hash
= NULL
;
1112 /**************************************************************************/
1115 /**************************************************************************/
1116 /* Tracking of Scheduling Requests (SRs). */
1117 /* Keep track of: */
1118 /* - last grant before SR */
1119 /* - SR failures following request */
1120 /* - grant following SR */
1122 typedef enum SREvent
{
1128 static const value_string sr_event_vals
[] =
1130 { SR_Grant
, "Grant"},
1131 { SR_Request
, "SR Request"},
1132 { SR_Failure
, "SR Failure"},
1136 typedef enum SRStatus
{
1142 static const value_string sr_status_vals
[] =
1144 { None
, "Receiving grants"},
1145 { SR_Outstanding
, "SR Request outstanding"},
1146 { SR_Failed
, "SR has Failed"},
1151 typedef struct SRState
{
1153 guint32 lastSRFramenum
;
1154 guint32 lastGrantFramenum
;
1155 nstime_t requestTime
;
1159 /* This table keeps track of the SR state for each UE.
1160 (RNTI -> SRState) */
1161 static GHashTable
*mac_lte_ue_sr_state
= NULL
;
1164 typedef enum SRResultType
{
1173 typedef struct SRResult
{
1176 guint32 timeDifference
;
1178 /* These 2 are only used with InvalidSREvent */
1183 /* Entries in this table are created during the first pass
1184 It maps (SRFrameNum -> SRResult) */
1185 static GHashTable
*mac_lte_sr_request_hash
= NULL
;
1187 /**************************************************************************/
1191 /**************************************************************************/
1193 /* Config for current cycle/timer state for a configured UE */
1196 /* Entries in this table are maintained during the first pass
1197 It maps (UEId -> drx_state_t). */
1198 static GHashTable
*mac_lte_drx_ue_state
= NULL
;
1200 typedef struct drx_running_state_t
1202 /* Need time reference point to work out timers, as SFN may wrap */
1203 gboolean firstCycleStartSet
;
1204 nstime_t firstCycleStart
;
1206 /* Cycle information */
1207 gboolean inShortCycle
;
1210 nstime_t currentTime
; /* absolute time of last PDU */
1214 gboolean inOnDuration
;
1215 guint64 onDurationTimer
;
1216 guint64 inactivityTimer
;
1218 guint64 retransmissionTimer
[8];
1219 guint64 shortCycleTimer
;
1221 } drx_running_state_t
;
1223 /* Have 2 states for each PDU. One for before the PDU/event, and one after.
1224 Only then can show if we don't think it should have been active at that point... */
1225 typedef struct drx_state_t
{
1226 drx_config_t config
;
1227 drx_running_state_t state_before
;
1228 drx_running_state_t state_after
;
1232 /* Entries in this table are written during the first pass
1233 It maps (Framenum -> drx_state_t), so state at that point may be shown */
1234 static GHashTable
*mac_lte_drx_frame_result
= NULL
;
1236 /* Initialise the UE DRX state */
1237 static void init_drx_ue_state(drx_state_t
*drx_state
, gboolean at_init
)
1240 drx_state
->state_before
.inShortCycle
= FALSE
;
1242 drx_state
->state_before
.onDurationTimer
= G_GUINT64_CONSTANT(0);
1244 drx_state
->state_before
.inactivityTimer
= G_GUINT64_CONSTANT(0);
1245 for (i
=0; i
< 8; i
++) {
1246 drx_state
->state_before
.RTT
[i
] = G_GUINT64_CONSTANT(0);
1247 drx_state
->state_before
.retransmissionTimer
[i
] = G_GUINT64_CONSTANT(0);
1249 drx_state
->state_before
.shortCycleTimer
= G_GUINT64_CONSTANT(0);
1252 typedef enum drx_timer_type_t
{
1253 drx_onduration_timer
,
1254 drx_inactivity_timer
,
1257 drx_short_cycle_timer
1260 /* Start the specified timer. Use the time period in the config */
1261 static void mac_lte_drx_start_timer(drx_state_t
*p_state
, drx_timer_type_t timer_type
, guint8 timer_id
)
1263 /* Get current time in ms */
1264 /* TODO: should this be relative to firstCycleStart to avoid overflowing? */
1265 guint64 currentTime
= (p_state
->state_before
.currentTime
.secs
* 1000) + (p_state
->state_before
.currentTime
.nsecs
/ 1000000);
1268 guint16 timerLength
;
1270 /* Get pointer to timer value, and fetch from config how much to add to it */
1271 switch (timer_type
) {
1272 case drx_onduration_timer
:
1273 pTimer
= &(p_state
->state_before
.onDurationTimer
);
1274 timerLength
= p_state
->config
.onDurationTimer
;
1276 case drx_inactivity_timer
:
1277 pTimer
= &(p_state
->state_before
.inactivityTimer
);
1278 timerLength
= p_state
->config
.inactivityTimer
;
1281 pTimer
= &(p_state
->state_before
.RTT
[timer_id
]);
1284 case drx_retx_timer
:
1285 pTimer
= &(p_state
->state_before
.retransmissionTimer
[timer_id
]);
1286 timerLength
= p_state
->config
.retransmissionTimer
;
1288 case drx_short_cycle_timer
:
1290 pTimer
= &(p_state
->state_before
.shortCycleTimer
);
1291 timerLength
= p_state
->config
.shortCycle
* p_state
->config
.shortCycleTimer
;
1296 *pTimer
= currentTime
+ timerLength
;
1299 /* Stop the specified timer. */
1300 static void mac_lte_drx_stop_timer(drx_state_t
*p_state
, drx_timer_type_t timer_type
, guint8 timer_id
)
1302 /* Set indicated timer value to 0 */
1303 switch (timer_type
) {
1304 case drx_onduration_timer
:
1305 p_state
->state_before
.onDurationTimer
= G_GUINT64_CONSTANT(0);
1307 case drx_inactivity_timer
:
1308 p_state
->state_before
.inactivityTimer
= G_GUINT64_CONSTANT(0);
1311 p_state
->state_before
.RTT
[timer_id
] = G_GUINT64_CONSTANT(0);
1313 case drx_retx_timer
:
1314 p_state
->state_before
.retransmissionTimer
[timer_id
] = G_GUINT64_CONSTANT(0);
1316 case drx_short_cycle_timer
:
1317 p_state
->state_before
.shortCycleTimer
= G_GUINT64_CONSTANT(0);
1322 /* Has the specified timer expired? */
1323 static gboolean
mac_lte_drx_has_timer_expired(drx_state_t
*p_state
, drx_timer_type_t timer_type
, guint8 timer_id
,
1324 gboolean before_event
,
1325 guint64
*time_until_expires
)
1327 guint64
*pTimer
= NULL
;
1328 drx_running_state_t
*state_to_use
;
1329 guint64 currentTime
;
1332 state_to_use
= &p_state
->state_before
;
1335 state_to_use
= &p_state
->state_after
;
1339 /* Get current time in ms */
1340 /* TODO: should this be relative to firstCycleStart to avoid overflowing? */
1341 currentTime
= (state_to_use
->currentTime
.secs
* 1000) + (state_to_use
->currentTime
.nsecs
/ 1000000);
1343 /* Get pointer to timer value */
1344 switch (timer_type
) {
1345 case drx_onduration_timer
:
1346 pTimer
= &(state_to_use
->onDurationTimer
);
1348 case drx_inactivity_timer
:
1349 pTimer
= &(state_to_use
->inactivityTimer
);
1352 pTimer
= &(state_to_use
->RTT
[timer_id
]);
1354 case drx_retx_timer
:
1355 pTimer
= &(state_to_use
->retransmissionTimer
[timer_id
]);
1357 case drx_short_cycle_timer
:
1358 pTimer
= &(state_to_use
->shortCycleTimer
);
1365 /* TODO: verify using SFN/SF ? */
1366 if (currentTime
>= *pTimer
) {
1370 *time_until_expires
= *pTimer
- currentTime
;
1376 /* Handling of triggers that can prompt changes in state */
1378 static void mac_lte_drx_new_ulsch_data(guint16 ueid
)
1380 /* Look up state of this UE */
1381 drx_state_t
*ue_state
= (drx_state_t
*)g_hash_table_lookup(mac_lte_drx_ue_state
, GUINT_TO_POINTER((guint
)ueid
));
1383 /* Start inactivity timer */
1384 if (ue_state
!= NULL
) {
1385 mac_lte_drx_start_timer(ue_state
, drx_inactivity_timer
, 0);
1389 static void mac_lte_drx_new_dlsch_data(guint16 ueid
)
1391 /* Look up state of this UE */
1392 drx_state_t
*ue_state
= (drx_state_t
*)g_hash_table_lookup(mac_lte_drx_ue_state
,
1393 GUINT_TO_POINTER((guint
)ueid
));
1395 /* Start retransmission timer */
1396 if (ue_state
!= NULL
) {
1397 mac_lte_drx_start_timer(ue_state
, drx_inactivity_timer
, 0);
1401 static void mac_lte_drx_dl_crc_error(guint16 ueid
)
1403 /* Look up state of this UE */
1404 drx_state_t
*ue_state
= (drx_state_t
*)g_hash_table_lookup(mac_lte_drx_ue_state
,
1405 GUINT_TO_POINTER((guint
)ueid
));
1408 if (ue_state
!= NULL
) {
1409 mac_lte_drx_start_timer(ue_state
, drx_retx_timer
, 0);
1413 /* A DRX control element has been received */
1414 static void mac_lte_drx_control_element_received(guint16 ueid
)
1416 /* Look up state of this UE */
1417 drx_state_t
*ue_state
= (drx_state_t
*)g_hash_table_lookup(mac_lte_drx_ue_state
,
1418 GUINT_TO_POINTER((guint
)ueid
));
1421 if (ue_state
!= NULL
) {
1422 mac_lte_drx_stop_timer(ue_state
, drx_onduration_timer
, 0);
1423 mac_lte_drx_stop_timer(ue_state
, drx_inactivity_timer
, 0);
1428 /* Update the DRX state of the UE based on previous info and current time.
1429 This is called every time a UE with DRX configured has an UL or DL PDU */
1430 static void update_drx_info(packet_info
*pinfo
, mac_lte_info
*p_mac_lte_info
)
1433 guint64 time_until_expires
;
1435 /* Look up state of this UE */
1436 drx_state_t
*ue_state
= (drx_state_t
*)g_hash_table_lookup(mac_lte_drx_ue_state
,
1437 GUINT_TO_POINTER((guint
)p_mac_lte_info
->ueid
));
1439 if (ue_state
!= NULL
) {
1440 guint16 SFN
= p_mac_lte_info
->sysframeNumber
;
1441 guint16 SF
= p_mac_lte_info
->subframeNumber
;
1443 /* Make sure the first time reference has been set */
1444 if (!ue_state
->state_before
.firstCycleStartSet
) {
1445 guint16 subframes
= SFN
*10 + SF
;
1447 /* Set firstCycleStart to be the previous SFN=0, SF=0 */
1448 if (pinfo
->fd
->abs_ts
.nsecs
> ((subframes
% 1000)*1000)) {
1449 ue_state
->state_before
.firstCycleStart
.secs
= pinfo
->fd
->abs_ts
.secs
- (subframes
/1000);
1450 ue_state
->state_before
.firstCycleStart
.nsecs
= pinfo
->fd
->abs_ts
.nsecs
- (subframes
*1000);
1453 ue_state
->state_before
.firstCycleStart
.secs
= pinfo
->fd
->abs_ts
.secs
- (subframes
/1000) - 1;
1454 ue_state
->state_before
.firstCycleStart
.nsecs
= 1000000 + pinfo
->fd
->abs_ts
.nsecs
- (subframes
*1000);
1456 ue_state
->state_before
.firstCycleStartSet
= TRUE
;
1458 /* Set current time to now */
1459 ue_state
->state_before
.currentSFN
= SFN
;
1460 ue_state
->state_before
.currentSF
= SF
;
1463 /* Will loop around these checks, once for each subframe between previous
1464 currentTime for this UE, and the time now!!! */
1465 /* It *should* be possible to just deal with the elapsed time all at once,
1466 but much harder to get right, so loop. */
1468 /* If > ~10s since last PDU, just zero all timers (except onDuration) */
1469 if ((pinfo
->fd
->abs_ts
.secs
- ue_state
->state_before
.currentTime
.secs
) >= 9) {
1470 init_drx_ue_state(ue_state
, FALSE
);
1473 while ((ue_state
->state_before
.currentSFN
!= SFN
) || (ue_state
->state_before
.currentSF
!= SF
)) {
1475 /* Check for timers that have expired and change state accordingly */
1477 /* See if onDuration timer should be started */
1478 guint16 subframes
= SFN
*10 + SF
;
1479 if (!ue_state
->state_before
.inShortCycle
) {
1480 if ((subframes
% ue_state
->config
.longCycle
) == ue_state
->config
.onDurationTimer
) {
1481 mac_lte_drx_start_timer(ue_state
, drx_onduration_timer
, 0);
1482 ue_state
->state_before
.inOnDuration
= TRUE
;
1486 if ((subframes
% ue_state
->config
.shortCycle
) == (ue_state
->config
.onDurationTimer
% ue_state
->config
.shortCycle
)) {
1487 mac_lte_drx_start_timer(ue_state
, drx_onduration_timer
, 0);
1488 ue_state
->state_before
.inOnDuration
= TRUE
;
1492 /* See if onDuration has expired */
1493 if (mac_lte_drx_has_timer_expired(ue_state
, drx_onduration_timer
, 0, TRUE
, &time_until_expires
)) {
1494 ue_state
->state_before
.inOnDuration
= FALSE
;
1497 /* Check for HARQ RTT Timer expiring.
1498 In practice only one could expire in any given subframe... */
1499 for (harq_id
= 0 ; harq_id
< 8; harq_id
++) {
1500 if (mac_lte_drx_has_timer_expired(ue_state
, drx_rtt_timer
, harq_id
, TRUE
, &time_until_expires
)) {
1501 /* Start the Retransmission timer */
1502 mac_lte_drx_start_timer(ue_state
, drx_retx_timer
, harq_id
);
1506 /* Reception of DRX command is dealt with separately at the moment... */
1508 /* Inactivity timer expired */
1509 if (mac_lte_drx_has_timer_expired(ue_state
, drx_inactivity_timer
, 0, TRUE
, &time_until_expires
)) {
1510 if (ue_state
->config
.shortCycleConfigured
) {
1511 ue_state
->state_before
.inShortCycle
= TRUE
;
1512 mac_lte_drx_start_timer(ue_state
, drx_short_cycle_timer
, 0);
1517 /* Move subframe along by one */
1518 if (ue_state
->state_before
.currentSF
== 9) {
1519 ue_state
->state_before
.currentSF
= 0;
1520 if (ue_state
->state_before
.currentSFN
== 1023) {
1521 ue_state
->state_before
.currentSFN
= 0;
1524 ue_state
->state_before
.currentSFN
++;
1528 ue_state
->state_before
.currentSF
++;
1532 /* Set current time to now */
1533 ue_state
->state_before
.currentTime
= pinfo
->fd
->abs_ts
;
1537 /* Set DRX information to display for the current MAC frame.
1538 Only called on first pass through frames. */
1539 static void set_drx_info(packet_info
*pinfo
, mac_lte_info
*p_mac_lte_info
, gboolean before_event
)
1541 /* Look up state of this UE */
1542 drx_state_t
*ue_state
= (drx_state_t
*)g_hash_table_lookup(mac_lte_drx_ue_state
,
1543 GUINT_TO_POINTER((guint
)p_mac_lte_info
->ueid
));
1544 drx_state_t
*frame_result
;
1546 if (ue_state
!= NULL
) {
1547 /* Should only need to allocate frame_result and add to the result table when
1548 before PDU is processed */
1550 /* Copy UE snapshot for this frame, and add to result table */
1551 frame_result
= wmem_new(wmem_file_scope(), drx_state_t
);
1553 /* Deep-copy this snapshot for this frame */
1554 *frame_result
= *ue_state
;
1556 /* And store in table */
1557 g_hash_table_insert(mac_lte_drx_frame_result
, GUINT_TO_POINTER(pinfo
->fd
->num
), frame_result
);
1560 /* After update, so just copy ue_state 'state' info after part of frame */
1561 frame_result
= (drx_state_t
*)g_hash_table_lookup(mac_lte_drx_frame_result
,
1562 GUINT_TO_POINTER(pinfo
->fd
->num
));
1563 if (frame_result
!= NULL
) {
1564 /* Deep-copy updated state from UE */
1565 frame_result
->state_after
= ue_state
->state_before
;
1571 /* Show DRX information associated with this MAC frame */
1572 static void show_drx_info(packet_info
*pinfo
, proto_tree
*tree
, tvbuff_t
*tvb
,
1573 mac_lte_info
*p_mac_lte_info
, gboolean before_event
)
1575 drx_state_t
*frame_state
;
1576 drx_running_state_t
*state_to_show
;
1577 guint64 time_until_expires
;
1580 /* Look up entry by frame number in result table */
1581 frame_state
= (drx_state_t
*)g_hash_table_lookup(mac_lte_drx_frame_result
,
1582 GUINT_TO_POINTER(pinfo
->fd
->num
));
1584 /* Show available information */
1585 if (frame_state
!= NULL
) {
1586 proto_tree
*drx_config_tree
, *drx_state_tree
;
1587 proto_item
*drx_config_ti
, *drx_state_ti
, *ti
;
1589 /* Show config only if 'before */
1591 /************************************/
1592 /* Create config subtree */
1593 drx_config_ti
= proto_tree_add_string_format(tree
, hf_mac_lte_drx_config
,
1594 tvb
, 0, 0, "", "DRX Config");
1595 drx_config_tree
= proto_item_add_subtree(drx_config_ti
, ett_mac_lte_drx_config
);
1596 PROTO_ITEM_SET_GENERATED(drx_config_ti
);
1598 /* Link back to configuration (RRC) frame */
1599 ti
= proto_tree_add_uint(drx_config_tree
, hf_mac_lte_drx_config_frame_num
, tvb
,
1600 0, 0, frame_state
->config
.frameNum
);
1601 PROTO_ITEM_SET_GENERATED(ti
);
1603 /* Link back to any previous config frame (only from current config frame) */
1604 if ((frame_state
->config
.frameNum
== pinfo
->fd
->num
) &&
1605 (frame_state
->config
.previousFrameNum
!= 0)) {
1606 ti
= proto_tree_add_uint(drx_config_tree
, hf_mac_lte_drx_config_previous_frame_num
, tvb
,
1607 0, 0, frame_state
->config
.previousFrameNum
);
1608 PROTO_ITEM_SET_GENERATED(ti
);
1612 ti
= proto_tree_add_uint(drx_config_tree
, hf_mac_lte_drx_config_long_cycle
, tvb
,
1613 0, 0, frame_state
->config
.longCycle
);
1614 PROTO_ITEM_SET_GENERATED(ti
);
1615 ti
= proto_tree_add_uint(drx_config_tree
, hf_mac_lte_drx_config_cycle_offset
, tvb
,
1616 0, 0, frame_state
->config
.cycleOffset
);
1617 PROTO_ITEM_SET_GENERATED(ti
);
1618 ti
= proto_tree_add_uint(drx_config_tree
, hf_mac_lte_drx_config_onduration_timer
, tvb
,
1619 0, 0, frame_state
->config
.onDurationTimer
);
1620 PROTO_ITEM_SET_GENERATED(ti
);
1621 ti
= proto_tree_add_uint(drx_config_tree
, hf_mac_lte_drx_config_inactivity_timer
, tvb
,
1622 0, 0, frame_state
->config
.inactivityTimer
);
1623 PROTO_ITEM_SET_GENERATED(ti
);
1624 ti
= proto_tree_add_uint(drx_config_tree
, hf_mac_lte_drx_config_retransmission_timer
, tvb
,
1625 0, 0, frame_state
->config
.retransmissionTimer
);
1626 PROTO_ITEM_SET_GENERATED(ti
);
1628 if (frame_state
->config
.shortCycleConfigured
) {
1629 ti
= proto_tree_add_uint(drx_config_tree
, hf_mac_lte_drx_config_short_cycle
, tvb
,
1630 0, 0, frame_state
->config
.shortCycle
);
1631 PROTO_ITEM_SET_GENERATED(ti
);
1633 ti
= proto_tree_add_uint(drx_config_tree
, hf_mac_lte_drx_config_short_cycle_timer
, tvb
,
1634 0, 0, frame_state
->config
.shortCycleTimer
);
1635 PROTO_ITEM_SET_GENERATED(ti
);
1638 proto_item_append_text(drx_config_ti
, " (Long-cycle=%u cycle-offset=%u onDuration=%u)",
1639 frame_state
->config
.longCycle
, frame_state
->config
.cycleOffset
,
1640 frame_state
->config
.onDurationTimer
);
1641 if (frame_state
->config
.shortCycleConfigured
) {
1642 proto_item_append_text(drx_config_ti
, " (Short-cycle=%u Short-cycle-timer=%u)",
1643 frame_state
->config
.shortCycle
, frame_state
->config
.shortCycleTimer
);
1647 /*************************************/
1648 /* Create state subtree */
1649 drx_state_ti
= proto_tree_add_string_format(tree
, hf_mac_lte_drx_state
,
1651 (before_event
) ? "DRX State Before" : "DRX State After");
1652 /* Get appropriate state pointer to use below */
1654 state_to_show
= &frame_state
->state_before
;
1657 state_to_show
= &frame_state
->state_after
;
1660 drx_state_tree
= proto_item_add_subtree(drx_state_ti
, ett_mac_lte_drx_state
);
1661 PROTO_ITEM_SET_GENERATED(drx_state_ti
);
1663 /* Show cycle information */
1665 if (!state_to_show
->inShortCycle
) {
1666 /* Show where we are in current long cycle */
1667 guint16 offset_into_long_cycle
= ((p_mac_lte_info
->sysframeNumber
*10) + p_mac_lte_info
->subframeNumber
) %
1668 frame_state
->config
.longCycle
;
1669 ti
= proto_tree_add_uint(drx_state_tree
, hf_mac_lte_drx_state_long_cycle_offset
, tvb
,
1670 0, 0, offset_into_long_cycle
);
1671 PROTO_ITEM_SET_GENERATED(ti
);
1673 /* Show whether we're inside long cycle on-duration */
1674 ti
= proto_tree_add_boolean(drx_state_tree
, hf_mac_lte_drx_state_long_cycle_on
, tvb
,
1675 0, 0, state_to_show
->inOnDuration
);
1676 PROTO_ITEM_SET_GENERATED(ti
);
1678 proto_item_append_text(drx_state_ti
, " (Offset-into-Long=%u, Long-cycle-on=%s)",
1679 offset_into_long_cycle
, state_to_show
->inOnDuration
? "True" : "False");
1682 /* Show where we are inside short cycle */
1683 guint16 offset_into_short_cycle
= ((p_mac_lte_info
->sysframeNumber
*10) + p_mac_lte_info
->subframeNumber
) %
1684 frame_state
->config
.shortCycle
;
1686 ti
= proto_tree_add_uint(drx_state_tree
, hf_mac_lte_drx_state_short_cycle_offset
, tvb
,
1687 0, 0, offset_into_short_cycle
);
1688 PROTO_ITEM_SET_GENERATED(ti
);
1690 /* Show whether we're inside short cycle on-duration */
1691 ti
= proto_tree_add_boolean(drx_state_tree
, hf_mac_lte_drx_state_short_cycle_on
, tvb
,
1692 0, 0, state_to_show
->inOnDuration
);
1693 PROTO_ITEM_SET_GENERATED(ti
);
1695 proto_item_append_text(drx_state_ti
, " (Offset-into-Short=%u, Long-cycle-on=%s)",
1696 offset_into_short_cycle
, state_to_show
->inOnDuration
? "True" : "False");
1698 /* Is short-cycle-timer running? */
1699 /* TODO: do we need this and the boolean above? */
1700 if (!mac_lte_drx_has_timer_expired(frame_state
, drx_short_cycle_timer
, 0, before_event
, &time_until_expires
)) {
1701 ti
= proto_tree_add_uint(drx_state_tree
, hf_mac_lte_drx_state_short_cycle_remaining
, tvb
,
1702 0, 0, (guint16
)time_until_expires
);
1703 PROTO_ITEM_SET_GENERATED(ti
);
1707 /* Show which timers are still running and how long they have to go.
1708 TODO: Complain if it looks like DRX looks like it should be on
1709 TODO: if PDU is a retranmission, would be good to check to see if DRX
1710 would have been on for original Tx! */
1712 /* Is onduration timer running? */
1713 if (!mac_lte_drx_has_timer_expired(frame_state
, drx_onduration_timer
, 0, before_event
, &time_until_expires
)) {
1714 ti
= proto_tree_add_uint(drx_state_tree
, hf_mac_lte_drx_state_onduration_remaining
, tvb
,
1715 0, 0, (guint16
)time_until_expires
);
1716 PROTO_ITEM_SET_GENERATED(ti
);
1720 /* Is inactivity timer running? */
1721 if (!mac_lte_drx_has_timer_expired(frame_state
, drx_inactivity_timer
, 0, before_event
, &time_until_expires
)) {
1722 ti
= proto_tree_add_uint(drx_state_tree
, hf_mac_lte_drx_state_inactivity_remaining
, tvb
,
1723 0, 0, (guint16
)time_until_expires
);
1724 PROTO_ITEM_SET_GENERATED(ti
);
1727 /* Are any of the Retransmission timers running? */
1728 for (n
=0; n
< 8; n
++) {
1729 if (!mac_lte_drx_has_timer_expired(frame_state
, drx_retx_timer
, n
, before_event
, &time_until_expires
)) {
1730 ti
= proto_tree_add_uint(drx_state_tree
, hf_mac_lte_drx_state_retransmission_remaining
, tvb
,
1731 0, 0, (guint16
)time_until_expires
);
1732 PROTO_ITEM_SET_GENERATED(ti
);
1733 proto_item_append_text(ti
, " (harqid=%u)", n
);
1737 /* Are any of the RTT timers running? */
1738 for (n
=0; n
< 8; n
++) {
1739 if (!mac_lte_drx_has_timer_expired(frame_state
, drx_rtt_timer
, n
, before_event
, &time_until_expires
)) {
1740 ti
= proto_tree_add_uint(drx_state_tree
, hf_mac_lte_drx_state_rtt_remaining
, tvb
,
1741 0, 0, (guint16
)time_until_expires
);
1742 PROTO_ITEM_SET_GENERATED(ti
);
1743 proto_item_append_text(ti
, " (harqid=%u)", n
);
1750 /**************************************************************************/
1754 /* Forward declarations */
1755 void dissect_mac_lte(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
);
1757 static guint8
get_mac_lte_channel_priority(guint16 ueid _U_
, guint8 lcid
,
1761 /* Heuristic dissection */
1762 static gboolean global_mac_lte_heur
= FALSE
;
1764 static void call_with_catch_all(dissector_handle_t handle
, tvbuff_t
* tvb
, packet_info
*pinfo
, proto_tree
*tree
)
1766 /* Call it (catch exceptions so that stats will be updated) */
1768 call_dissector_only(handle
, tvb
, pinfo
, tree
, NULL
);
1775 /* Dissect context fields in the format described in packet-mac-lte.h.
1776 Return TRUE if the necessary information was successfully found */
1777 gboolean
dissect_mac_lte_context_fields(struct mac_lte_info
*p_mac_lte_info
, tvbuff_t
*tvb
,
1780 gint offset
= *p_offset
;
1783 /* Read fixed fields */
1784 p_mac_lte_info
->radioType
= tvb_get_guint8(tvb
, offset
++);
1785 p_mac_lte_info
->direction
= tvb_get_guint8(tvb
, offset
++);
1787 /* TODO: currently no support for detailed PHY info... */
1788 if (p_mac_lte_info
->direction
== DIRECTION_UPLINK
) {
1789 p_mac_lte_info
->detailed_phy_info
.ul_info
.present
= FALSE
;
1792 p_mac_lte_info
->detailed_phy_info
.dl_info
.present
= FALSE
;
1795 p_mac_lte_info
->rntiType
= tvb_get_guint8(tvb
, offset
++);
1797 /* Initialize RNTI with a default value in case optional field is not present */
1798 switch (p_mac_lte_info
->rntiType
) {
1800 p_mac_lte_info
->rnti
= 0xFFFD;
1803 p_mac_lte_info
->rnti
= 0xFFFE;
1806 p_mac_lte_info
->rnti
= 0xFFFF;
1811 p_mac_lte_info
->rnti
= 0x0001;
1817 /* Read optional fields */
1818 while (tag
!= MAC_LTE_PAYLOAD_TAG
) {
1819 /* Process next tag */
1820 tag
= tvb_get_guint8(tvb
, offset
++);
1822 case MAC_LTE_RNTI_TAG
:
1823 p_mac_lte_info
->rnti
= tvb_get_ntohs(tvb
, offset
);
1826 case MAC_LTE_UEID_TAG
:
1827 p_mac_lte_info
->ueid
= tvb_get_ntohs(tvb
, offset
);
1830 case MAC_LTE_SUBFRAME_TAG
:
1831 p_mac_lte_info
->subframeNumber
= tvb_get_ntohs(tvb
, offset
);
1834 case MAC_LTE_PREDEFINED_DATA_TAG
:
1835 p_mac_lte_info
->isPredefinedData
= tvb_get_guint8(tvb
, offset
);
1838 case MAC_LTE_RETX_TAG
:
1839 p_mac_lte_info
->reTxCount
= tvb_get_guint8(tvb
, offset
);
1842 case MAC_LTE_CRC_STATUS_TAG
:
1843 p_mac_lte_info
->crcStatusValid
= crc_success
;
1844 p_mac_lte_info
->detailed_phy_info
.dl_info
.crc_status
=
1845 (mac_lte_crc_status
)tvb_get_guint8(tvb
, offset
);
1848 case MAC_LTE_EXT_BSR_SIZES_TAG
:
1849 p_mac_lte_info
->isExtendedBSRSizes
= TRUE
;
1852 case MAC_LTE_PAYLOAD_TAG
:
1853 /* Have reached data, so set payload length and get out of loop */
1854 /* TODO: this is not correct if there is padding which isn't in frame */
1855 p_mac_lte_info
->length
= tvb_length_remaining(tvb
, offset
);
1859 /* It must be a recognised tag */
1864 /* Pass out where offset is now */
1870 /* Heuristic dissector looks for supported framing protocol (see wiki page) */
1871 static gboolean
dissect_mac_lte_heur(tvbuff_t
*tvb
, packet_info
*pinfo
,
1872 proto_tree
*tree
, void *data _U_
)
1875 struct mac_lte_info
*p_mac_lte_info
;
1877 gboolean infoAlreadySet
= FALSE
;
1879 /* This is a heuristic dissector, which means we get all the UDP
1880 * traffic not sent to a known dissector and not claimed by
1881 * a heuristic dissector called before us!
1884 if (!global_mac_lte_heur
) {
1888 /* Do this again on re-dissection to re-discover offset of actual PDU */
1890 /* Needs to be at least as long as:
1891 - the signature string
1892 - fixed header bytes
1894 - at least one byte of MAC PDU payload */
1895 if (tvb_length_remaining(tvb
, offset
) < (gint
)(strlen(MAC_LTE_START_STRING
)+3+2)) {
1899 /* OK, compare with signature string */
1900 if (tvb_strneql(tvb
, offset
, MAC_LTE_START_STRING
, strlen(MAC_LTE_START_STRING
)) != 0) {
1903 offset
+= (gint
)strlen(MAC_LTE_START_STRING
);
1905 /* If redissecting, use previous info struct (if available) */
1906 p_mac_lte_info
= (mac_lte_info
*)p_get_proto_data(pinfo
->fd
, proto_mac_lte
, 0);
1907 if (p_mac_lte_info
== NULL
) {
1908 /* Allocate new info struct for this frame */
1909 p_mac_lte_info
= wmem_new0(wmem_file_scope(), struct mac_lte_info
);
1910 infoAlreadySet
= FALSE
;
1913 infoAlreadySet
= TRUE
;
1916 /* Dissect the fields to populate p_mac_lte */
1917 if (!dissect_mac_lte_context_fields(p_mac_lte_info
, tvb
, &offset
)) {
1922 if (!infoAlreadySet
) {
1923 /* Store info in packet */
1924 p_add_proto_data(pinfo
->fd
, proto_mac_lte
, 0, p_mac_lte_info
);
1927 /**************************************/
1928 /* OK, now dissect as MAC LTE */
1930 /* Create tvb that starts at actual MAC PDU */
1931 mac_tvb
= tvb_new_subset_remaining(tvb
, offset
);
1932 dissect_mac_lte(mac_tvb
, pinfo
, tree
);
1938 /* Write the given formatted text to:
1939 - the info column (if pinfo != NULL)
1940 - 1 or 2 other labels (optional)
1942 static void write_pdu_label_and_info(proto_item
*ti1
, proto_item
*ti2
,
1943 packet_info
*pinfo
, const char *format
, ...)
1945 #define MAX_INFO_BUFFER 256
1946 static char info_buffer
[MAX_INFO_BUFFER
];
1949 if ((ti1
== NULL
) && (ti2
== NULL
) && (pinfo
== NULL
)) {
1953 va_start(ap
, format
);
1954 g_vsnprintf(info_buffer
, MAX_INFO_BUFFER
, format
, ap
);
1957 /* Add to indicated places */
1958 if (pinfo
!= NULL
) {
1959 col_append_str(pinfo
->cinfo
, COL_INFO
, info_buffer
);
1962 proto_item_append_text(ti1
, "%s", info_buffer
);
1965 proto_item_append_text(ti2
, "%s", info_buffer
);
1969 /* Version of function above, where no g_vsnprintf() call needed */
1970 static void write_pdu_label_and_info_literal(proto_item
*ti1
, proto_item
*ti2
,
1971 packet_info
*pinfo
, const char *info_buffer
)
1973 if ((ti1
== NULL
) && (ti2
== NULL
) && (pinfo
== NULL
)) {
1977 /* Add to indicated places */
1978 if (pinfo
!= NULL
) {
1979 col_append_str(pinfo
->cinfo
, COL_INFO
, info_buffer
);
1982 proto_item_append_text(ti1
, "%s", info_buffer
);
1985 proto_item_append_text(ti2
, "%s", info_buffer
);
1991 /* Show extra PHY parameters (if present) */
1992 static void show_extra_phy_parameters(packet_info
*pinfo
, tvbuff_t
*tvb
, proto_tree
*tree
,
1993 struct mac_lte_info
*p_mac_lte_info
)
1996 proto_tree
*phy_tree
;
1999 if (global_mac_lte_layer_to_show
== ShowPHYLayer
) {
2000 /* Clear the info column */
2001 col_clear(pinfo
->cinfo
, COL_INFO
);
2004 if (p_mac_lte_info
->direction
== DIRECTION_UPLINK
) {
2005 if (p_mac_lte_info
->detailed_phy_info
.ul_info
.present
) {
2008 phy_ti
= proto_tree_add_string_format(tree
, hf_mac_lte_context_phy_ul
,
2009 tvb
, 0, 0, "", "UL PHY Context");
2010 phy_tree
= proto_item_add_subtree(phy_ti
, ett_mac_lte_phy_context
);
2011 PROTO_ITEM_SET_GENERATED(phy_ti
);
2014 ti
= proto_tree_add_uint(phy_tree
, hf_mac_lte_context_phy_ul_modulation_type
,
2016 p_mac_lte_info
->detailed_phy_info
.ul_info
.modulation_type
);
2017 PROTO_ITEM_SET_GENERATED(ti
);
2019 ti
= proto_tree_add_uint(phy_tree
, hf_mac_lte_context_phy_ul_tbs_index
,
2021 p_mac_lte_info
->detailed_phy_info
.ul_info
.tbs_index
);
2022 PROTO_ITEM_SET_GENERATED(ti
);
2024 ti
= proto_tree_add_uint(phy_tree
, hf_mac_lte_context_phy_ul_resource_block_length
,
2026 p_mac_lte_info
->detailed_phy_info
.ul_info
.resource_block_length
);
2027 PROTO_ITEM_SET_GENERATED(ti
);
2029 ti
= proto_tree_add_uint(phy_tree
, hf_mac_lte_context_phy_ul_resource_block_start
,
2031 p_mac_lte_info
->detailed_phy_info
.ul_info
.resource_block_start
);
2032 PROTO_ITEM_SET_GENERATED(ti
);
2034 ti
= proto_tree_add_uint(phy_tree
, hf_mac_lte_context_phy_ul_harq_id
,
2036 p_mac_lte_info
->detailed_phy_info
.ul_info
.harq_id
);
2037 PROTO_ITEM_SET_GENERATED(ti
);
2039 ti
= proto_tree_add_uint(phy_tree
, hf_mac_lte_context_phy_ul_ndi
,
2041 p_mac_lte_info
->detailed_phy_info
.ul_info
.ndi
);
2042 PROTO_ITEM_SET_GENERATED(ti
);
2045 proto_item_append_text(phy_ti
, " (");
2047 write_pdu_label_and_info(phy_ti
, NULL
,
2048 (global_mac_lte_layer_to_show
== ShowPHYLayer
) ? pinfo
: NULL
,
2049 "UL: UEId=%u RNTI=%u %s Tbs_Index=%u RB_len=%u RB_start=%u",
2050 p_mac_lte_info
->ueid
,
2051 p_mac_lte_info
->rnti
,
2052 val_to_str_const(p_mac_lte_info
->detailed_phy_info
.ul_info
.modulation_type
,
2053 modulation_type_vals
, "Unknown"),
2054 p_mac_lte_info
->detailed_phy_info
.ul_info
.tbs_index
,
2055 p_mac_lte_info
->detailed_phy_info
.ul_info
.resource_block_length
,
2056 p_mac_lte_info
->detailed_phy_info
.ul_info
.resource_block_start
);
2058 proto_item_append_text(phy_ti
, ")");
2060 /* Don't want columns to be replaced now */
2061 if (global_mac_lte_layer_to_show
== ShowPHYLayer
) {
2062 col_set_writable(pinfo
->cinfo
, FALSE
);
2067 if (p_mac_lte_info
->detailed_phy_info
.dl_info
.present
) {
2070 phy_ti
= proto_tree_add_string_format(tree
, hf_mac_lte_context_phy_dl
,
2071 tvb
, 0, 0, "", "DL PHY Context");
2072 phy_tree
= proto_item_add_subtree(phy_ti
, ett_mac_lte_phy_context
);
2073 PROTO_ITEM_SET_GENERATED(phy_ti
);
2076 ti
= proto_tree_add_uint(phy_tree
, hf_mac_lte_context_phy_dl_dci_format
,
2078 p_mac_lte_info
->detailed_phy_info
.dl_info
.dci_format
);
2079 PROTO_ITEM_SET_GENERATED(ti
);
2081 ti
= proto_tree_add_uint(phy_tree
, hf_mac_lte_context_phy_dl_resource_allocation_type
,
2083 p_mac_lte_info
->detailed_phy_info
.dl_info
.resource_allocation_type
);
2084 PROTO_ITEM_SET_GENERATED(ti
);
2086 ti
= proto_tree_add_uint(phy_tree
, hf_mac_lte_context_phy_dl_aggregation_level
,
2088 p_mac_lte_info
->detailed_phy_info
.dl_info
.aggregation_level
);
2089 PROTO_ITEM_SET_GENERATED(ti
);
2091 ti
= proto_tree_add_uint(phy_tree
, hf_mac_lte_context_phy_dl_mcs_index
,
2093 p_mac_lte_info
->detailed_phy_info
.dl_info
.mcs_index
);
2094 PROTO_ITEM_SET_GENERATED(ti
);
2096 ti
= proto_tree_add_uint(phy_tree
, hf_mac_lte_context_phy_dl_redundancy_version_index
,
2098 p_mac_lte_info
->detailed_phy_info
.dl_info
.redundancy_version_index
);
2099 PROTO_ITEM_SET_GENERATED(ti
);
2101 ti
= proto_tree_add_boolean(phy_tree
, hf_mac_lte_context_phy_dl_retx
,
2103 p_mac_lte_info
->dl_retx
);
2104 PROTO_ITEM_SET_GENERATED(ti
);
2106 ti
= proto_tree_add_uint(phy_tree
, hf_mac_lte_context_phy_dl_resource_block_length
,
2108 p_mac_lte_info
->detailed_phy_info
.dl_info
.resource_block_length
);
2109 PROTO_ITEM_SET_GENERATED(ti
);
2111 ti
= proto_tree_add_uint(phy_tree
, hf_mac_lte_context_phy_dl_crc_status
,
2113 p_mac_lte_info
->detailed_phy_info
.dl_info
.crc_status
);
2114 PROTO_ITEM_SET_GENERATED(ti
);
2116 ti
= proto_tree_add_uint(phy_tree
, hf_mac_lte_context_phy_dl_harq_id
,
2118 p_mac_lte_info
->detailed_phy_info
.dl_info
.harq_id
);
2119 PROTO_ITEM_SET_GENERATED(ti
);
2121 ti
= proto_tree_add_uint(phy_tree
, hf_mac_lte_context_phy_dl_ndi
,
2123 p_mac_lte_info
->detailed_phy_info
.dl_info
.ndi
);
2124 PROTO_ITEM_SET_GENERATED(ti
);
2126 ti
= proto_tree_add_uint(phy_tree
, hf_mac_lte_context_phy_dl_tb
,
2128 p_mac_lte_info
->detailed_phy_info
.dl_info
.transport_block
);
2129 PROTO_ITEM_SET_GENERATED(ti
);
2132 proto_item_append_text(phy_ti
, " (");
2134 write_pdu_label_and_info(phy_ti
, NULL
,
2135 (global_mac_lte_layer_to_show
== ShowPHYLayer
) ? pinfo
: NULL
,
2136 "DL: UEId=%u RNTI=%u DCI_Format=%s Res_Alloc=%u Aggr_Level=%s MCS=%u RV=%u "
2137 "Res_Block_len=%u CRC_status=%s HARQ_id=%u NDI=%u",
2138 p_mac_lte_info
->ueid
,
2139 p_mac_lte_info
->rnti
,
2140 val_to_str_const(p_mac_lte_info
->detailed_phy_info
.dl_info
.dci_format
,
2141 dci_format_vals
, "Unknown"),
2142 p_mac_lte_info
->detailed_phy_info
.dl_info
.resource_allocation_type
,
2143 val_to_str_const(p_mac_lte_info
->detailed_phy_info
.dl_info
.aggregation_level
,
2144 aggregation_level_vals
, "Unknown"),
2145 p_mac_lte_info
->detailed_phy_info
.dl_info
.mcs_index
,
2146 p_mac_lte_info
->detailed_phy_info
.dl_info
.redundancy_version_index
,
2147 p_mac_lte_info
->detailed_phy_info
.dl_info
.resource_block_length
,
2148 val_to_str_const(p_mac_lte_info
->detailed_phy_info
.dl_info
.crc_status
,
2149 crc_status_vals
, "Unknown"),
2150 p_mac_lte_info
->detailed_phy_info
.dl_info
.harq_id
,
2151 p_mac_lte_info
->detailed_phy_info
.dl_info
.ndi
);
2152 proto_item_append_text(phy_ti
, ")");
2154 /* Don't want columns to be replaced now */
2155 if (global_mac_lte_layer_to_show
== ShowPHYLayer
) {
2156 col_set_writable(pinfo
->cinfo
, FALSE
);
2163 /* Dissect a single Random Access Reponse body */
2164 static gint
dissect_rar_entry(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
2166 gint offset
, guint8 rapid
)
2169 guint start_body_offset
= offset
;
2171 proto_item
*rar_body_ti
;
2172 proto_tree
*rar_body_tree
;
2173 proto_tree
*ul_grant_tree
;
2174 proto_item
*ul_grant_ti
;
2175 guint16 timing_advance
;
2179 /* Create tree for this Body */
2180 rar_body_ti
= proto_tree_add_item(tree
,
2181 hf_mac_lte_rar_body
,
2182 tvb
, offset
, 0, ENC_ASCII
|ENC_NA
);
2183 rar_body_tree
= proto_item_add_subtree(rar_body_ti
, ett_mac_lte_rar_body
);
2185 /* Dissect an RAR entry */
2187 /* Check reserved bit */
2188 reserved
= (tvb_get_guint8(tvb
, offset
) & 0x80) >> 7;
2189 ti
= proto_tree_add_item(rar_body_tree
, hf_mac_lte_rar_reserved2
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2190 if (reserved
!= 0) {
2191 expert_add_info_format(pinfo
, ti
, &ei_mac_lte_reserved_not_zero
, "RAR body Reserved bit not zero (found 0x%x)", reserved
);
2194 /* Timing Advance */
2195 timing_advance
= (tvb_get_ntohs(tvb
, offset
) & 0x7ff0) >> 4;
2196 ti
= proto_tree_add_item(rar_body_tree
, hf_mac_lte_rar_ta
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
2197 if (timing_advance
!= 0) {
2198 if (timing_advance
<= 31) {
2199 expert_add_info_format(pinfo
, ti
, &ei_mac_lte_rar_timing_advance_not_zero_note
,
2200 "RAR Timing advance not zero (%u)", timing_advance
);
2202 expert_add_info_format(pinfo
, ti
, &ei_mac_lte_rar_timing_advance_not_zero_warn
,
2203 "RAR Timing advance not zero (%u)", timing_advance
);
2209 ul_grant
= (tvb_get_ntohl(tvb
, offset
) & 0x0fffff00) >> 8;
2210 ul_grant_ti
= proto_tree_add_item(rar_body_tree
, hf_mac_lte_rar_ul_grant
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
2212 /* Break these 20 bits down as described in 36.213, section 6.2 */
2213 /* Create subtree for UL grant break-down */
2214 ul_grant_tree
= proto_item_add_subtree(ul_grant_ti
, ett_mac_lte_rar_ul_grant
);
2216 /* Hopping flag (1 bit) */
2217 proto_tree_add_item(ul_grant_tree
, hf_mac_lte_rar_ul_grant_hopping
,
2218 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2220 /* Fixed sized resource block assignment (10 bits) */
2221 proto_tree_add_item(ul_grant_tree
, hf_mac_lte_rar_ul_grant_fsrba
,
2222 tvb
, offset
, 2, ENC_BIG_ENDIAN
);
2224 /* Truncated Modulation and coding scheme (4 bits) */
2225 proto_tree_add_item(ul_grant_tree
, hf_mac_lte_rar_ul_grant_tmcs
,
2226 tvb
, offset
+1, 2, ENC_BIG_ENDIAN
);
2228 /* TPC command for scheduled PUSCH (3 bits) */
2229 proto_tree_add_item(ul_grant_tree
, hf_mac_lte_rar_ul_grant_tcsp
,
2230 tvb
, offset
+2, 1, ENC_BIG_ENDIAN
);
2232 /* UL delay (1 bit) */
2233 proto_tree_add_item(ul_grant_tree
, hf_mac_lte_rar_ul_grant_ul_delay
,
2234 tvb
, offset
+2, 1, ENC_BIG_ENDIAN
);
2236 /* CQI request (1 bit) */
2237 proto_tree_add_item(ul_grant_tree
, hf_mac_lte_rar_ul_grant_cqi_request
,
2238 tvb
, offset
+2, 1, ENC_BIG_ENDIAN
);
2242 /* Temporary C-RNTI */
2243 temp_crnti
= tvb_get_ntohs(tvb
, offset
);
2244 proto_tree_add_item(rar_body_tree
, hf_mac_lte_rar_temporary_crnti
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
2247 write_pdu_label_and_info(pdu_ti
, rar_body_ti
, pinfo
,
2248 "(RAPID=%u: TA=%u, UL-Grant=%u, Temp C-RNTI=%u) ",
2249 rapid
, timing_advance
, ul_grant
, temp_crnti
);
2251 proto_item_set_len(rar_body_ti
, offset
-start_body_offset
);
2257 #define MAX_RAR_PDUS 64
2258 /* Dissect Random Access Reponse (RAR) PDU */
2259 static void dissect_rar(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, proto_item
*pdu_ti
,
2260 gint offset
, mac_lte_info
*p_mac_lte_info
, mac_lte_tap_info
*tap_info
)
2262 gint number_of_rars
= 0; /* No of RAR bodies expected following headers */
2263 guint8
*rapids
= (guint8
*)wmem_alloc(wmem_packet_scope(), MAX_RAR_PDUS
* sizeof(guint8
));
2264 gboolean backoff_indicator_seen
= FALSE
;
2265 guint8 backoff_indicator
= 0;
2268 proto_tree
*rar_headers_tree
;
2270 proto_item
*rar_headers_ti
;
2271 proto_item
*padding_length_ti
;
2272 int start_headers_offset
= offset
;
2274 write_pdu_label_and_info(pdu_ti
, NULL
, pinfo
,
2275 "RAR (RA-RNTI=%u, SF=%u) ",
2276 p_mac_lte_info
->rnti
, p_mac_lte_info
->subframeNumber
);
2278 /* Create hidden 'virtual root' so can filter on mac-lte.rar */
2279 ti
= proto_tree_add_item(tree
, hf_mac_lte_rar
, tvb
, offset
, -1, ENC_NA
);
2280 PROTO_ITEM_SET_HIDDEN(ti
);
2282 /* Create headers tree */
2283 rar_headers_ti
= proto_tree_add_item(tree
,
2284 hf_mac_lte_rar_headers
,
2285 tvb
, offset
, 0, ENC_ASCII
|ENC_NA
);
2286 rar_headers_tree
= proto_item_add_subtree(rar_headers_ti
, ett_mac_lte_rar_headers
);
2289 /***************************/
2290 /* Read the header entries */
2292 int start_header_offset
= offset
;
2293 proto_tree
*rar_header_tree
;
2294 proto_item
*rar_header_ti
;
2296 guint8 first_byte
= tvb_get_guint8(tvb
, offset
);
2298 /* Create tree for this header */
2299 rar_header_ti
= proto_tree_add_item(rar_headers_tree
,
2300 hf_mac_lte_rar_header
,
2301 tvb
, offset
, 0, ENC_ASCII
|ENC_NA
);
2302 rar_header_tree
= proto_item_add_subtree(rar_header_ti
, ett_mac_lte_rar_header
);
2305 extension
= (first_byte
& 0x80) >> 7;
2306 proto_tree_add_item(rar_header_tree
, hf_mac_lte_rar_extension
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2309 type_value
= (first_byte
& 0x40) >> 6;
2310 proto_tree_add_item(rar_header_tree
, hf_mac_lte_rar_t
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2312 if (type_value
== 0) {
2313 /* Backoff Indicator (BI) case */
2319 /* 2 Reserved bits */
2320 reserved
= (tvb_get_guint8(tvb
, offset
) & 0x30) >> 4;
2321 tii
= proto_tree_add_item(rar_header_tree
, hf_mac_lte_rar_reserved
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2322 if (reserved
!= 0) {
2323 expert_add_info_format(pinfo
, tii
, &ei_mac_lte_reserved_not_zero
,
2324 "RAR header Reserved bits not zero (found 0x%x)", reserved
);
2327 /* Backoff Indicator */
2328 backoff_indicator
= tvb_get_guint8(tvb
, offset
) & 0x0f;
2329 bi_ti
= proto_tree_add_item(rar_header_tree
, hf_mac_lte_rar_bi
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2331 /* As of March 2009 spec, it must be first, and may only appear once */
2332 if (backoff_indicator_seen
) {
2333 expert_add_info(pinfo
, bi_ti
, &ei_mac_lte_rar_bi_present
);
2335 backoff_indicator_seen
= TRUE
;
2337 write_pdu_label_and_info(pdu_ti
, rar_header_ti
, pinfo
,
2338 "(Backoff Indicator=%sms)",
2339 val_to_str_const(backoff_indicator
, rar_bi_vals
, "Illegal-value "));
2341 /* If present, it must be the first subheader */
2342 if (number_of_rars
> 0) {
2343 expert_add_info(pinfo
, bi_ti
, &ei_mac_lte_rar_bi_not_first_subheader
);
2349 /* TODO: complain if the same RAPID appears twice in same frame? */
2350 rapids
[number_of_rars
] = tvb_get_guint8(tvb
, offset
) & 0x3f;
2351 proto_tree_add_item(rar_header_tree
, hf_mac_lte_rar_rapid
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2353 proto_item_append_text(rar_header_ti
, "(RAPID=%u)", rapids
[number_of_rars
]);
2360 /* Finalise length of header tree selection */
2361 proto_item_set_len(rar_header_ti
, offset
- start_header_offset
);
2363 } while (extension
&& number_of_rars
< MAX_RAR_PDUS
);
2365 /* Append summary to headers root */
2366 proto_item_append_text(rar_headers_ti
, " (%u RARs", number_of_rars
);
2367 ti
= proto_tree_add_uint(rar_headers_tree
, hf_mac_lte_rar_no_of_rapids
, tvb
, 0, 0, number_of_rars
);
2368 PROTO_ITEM_SET_GENERATED(ti
);
2369 if (backoff_indicator_seen
) {
2370 proto_item_append_text(rar_headers_ti
, ", BI=%sms)",
2371 val_to_str_const(backoff_indicator
, rar_bi_vals
, "Illegal-value "));
2374 proto_item_append_text(rar_headers_ti
, ")");
2377 /* Set length for headers root */
2378 proto_item_set_len(rar_headers_ti
, offset
-start_headers_offset
);
2381 /***************************/
2382 /* Read any indicated RARs */
2383 for (n
=0; n
< number_of_rars
; n
++) {
2384 offset
= dissect_rar_entry(tvb
, pinfo
, tree
, pdu_ti
, offset
, rapids
[n
]);
2387 /* Update TAP info */
2388 tap_info
->number_of_rars
+= number_of_rars
;
2390 /* Padding may follow */
2391 if (tvb_length_remaining(tvb
, offset
) > 0) {
2392 proto_tree_add_item(tree
, hf_mac_lte_padding_data
,
2393 tvb
, offset
, -1, ENC_NA
);
2395 padding_length_ti
= proto_tree_add_int(tree
, hf_mac_lte_padding_length
,
2397 p_mac_lte_info
->length
- offset
);
2398 PROTO_ITEM_SET_GENERATED(padding_length_ti
);
2400 /* Update padding bytes in stats */
2401 tap_info
->padding_bytes
+= (p_mac_lte_info
->length
- offset
);
2405 /* Dissect BCH PDU */
2406 static void dissect_bch(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
2408 int offset
, mac_lte_info
*p_mac_lte_info
)
2412 write_pdu_label_and_info(pdu_ti
, NULL
, pinfo
,
2413 "BCH PDU (%u bytes, on %s transport) ",
2414 tvb_length_remaining(tvb
, offset
),
2415 val_to_str_const(p_mac_lte_info
->rntiType
,
2416 bch_transport_channel_vals
,
2419 /* Show which transport layer it came in on (inferred from RNTI type) */
2420 ti
= proto_tree_add_uint(tree
, hf_mac_lte_context_bch_transport_channel
,
2421 tvb
, offset
, 0, p_mac_lte_info
->rntiType
);
2422 PROTO_ITEM_SET_GENERATED(ti
);
2424 /****************************************/
2425 /* Whole frame is BCH data */
2428 ti
= proto_tree_add_item(tree
, hf_mac_lte_bch_pdu
,
2429 tvb
, offset
, -1, ENC_NA
);
2431 if (global_mac_lte_attempt_rrc_decode
) {
2432 /* Attempt to decode payload using LTE RRC dissector */
2433 tvbuff_t
*rrc_tvb
= tvb_new_subset_remaining(tvb
, offset
);
2435 /* Get appropriate dissector handle */
2436 dissector_handle_t protocol_handle
= 0;
2437 if (p_mac_lte_info
->rntiType
== SI_RNTI
) {
2438 protocol_handle
= find_dissector("lte_rrc.bcch_dl_sch");
2441 protocol_handle
= find_dissector("lte_rrc.bcch_bch");
2444 /* Hide raw view of bytes */
2445 PROTO_ITEM_SET_HIDDEN(ti
);
2447 call_with_catch_all(protocol_handle
, rrc_tvb
, pinfo
, tree
);
2450 /* Check that this *is* downlink! */
2451 if (p_mac_lte_info
->direction
== DIRECTION_UPLINK
) {
2452 expert_add_info(pinfo
, ti
, &ei_mac_lte_bch_pdu
);
2457 /* Dissect PCH PDU */
2458 static void dissect_pch(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
2459 proto_item
*pdu_ti
, int offset
, guint8 direction
, mac_lte_tap_info
*tap_info
)
2463 write_pdu_label_and_info(pdu_ti
, NULL
, pinfo
,
2464 "PCH PDU (%u bytes) ",
2465 tvb_length_remaining(tvb
, offset
));
2467 /****************************************/
2468 /* Whole frame is PCH data */
2470 /* Always show as raw data */
2471 ti
= proto_tree_add_item(tree
, hf_mac_lte_pch_pdu
,
2472 tvb
, offset
, -1, ENC_NA
);
2474 /* Get number of paging IDs for tap */
2475 tap_info
->number_of_paging_ids
= (tvb_get_guint8(tvb
, offset
) & 0x40) ?
2476 ((tvb_get_ntohs(tvb
, offset
) >> 7) & 0x000f) + 1 : 0;
2478 if (global_mac_lte_attempt_rrc_decode
) {
2480 /* Attempt to decode payload using LTE RRC dissector */
2481 tvbuff_t
*rrc_tvb
= tvb_new_subset_remaining(tvb
, offset
);
2483 /* Get appropriate dissector handle */
2484 dissector_handle_t protocol_handle
= find_dissector("lte_rrc.pcch");
2486 /* Hide raw view of bytes */
2487 PROTO_ITEM_SET_HIDDEN(ti
);
2489 /* Call it (catch exceptions so that stats will be updated) */
2490 call_with_catch_all(protocol_handle
, rrc_tvb
, pinfo
, tree
);
2493 /* Check that this *is* downlink! */
2494 if (direction
== DIRECTION_UPLINK
) {
2495 expert_add_info(pinfo
, ti
, &ei_mac_lte_pch_pdu
);
2500 /* Does this header entry correspond to a fixed-sized control element? */
2501 static int is_fixed_sized_control_element(guint8 lcid
, guint8 direction
)
2503 if (direction
== DIRECTION_UPLINK
) {
2506 case POWER_HEADROOM_REPORT_LCID
:
2508 case TRUNCATED_BSR_LCID
:
2509 case SHORT_BSR_LCID
:
2518 /* Assume Downlink */
2520 case ACTIVATION_DEACTIVATION_LCID
:
2521 case UE_CONTENTION_RESOLUTION_IDENTITY_LCID
:
2522 case TIMING_ADVANCE_LCID
:
2523 case DRX_COMMAND_LCID
:
2533 /* Is this a BSR report header? */
2534 static int is_bsr_lcid(guint8 lcid
)
2536 return ((lcid
== TRUNCATED_BSR_LCID
) ||
2537 (lcid
== SHORT_BSR_LCID
) ||
2538 (lcid
== LONG_BSR_LCID
));
2542 /* Helper function to call RLC dissector for SDUs (where channel params are known) */
2543 static void call_rlc_dissector(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
2545 int offset
, guint16 data_length
,
2546 guint8 mode
, guint8 direction
, guint16 ueid
,
2547 guint16 channelType
, guint16 channelId
,
2548 guint8 UMSequenceNumberLength
,
2551 tvbuff_t
*rb_tvb
= tvb_new_subset(tvb
, offset
, data_length
, data_length
);
2552 struct rlc_lte_info
*p_rlc_lte_info
;
2554 /* Resuse or create RLC info */
2555 p_rlc_lte_info
= (rlc_lte_info
*)p_get_proto_data(pinfo
->fd
, proto_rlc_lte
, 0);
2556 if (p_rlc_lte_info
== NULL
) {
2557 p_rlc_lte_info
= wmem_new0(wmem_file_scope(), struct rlc_lte_info
);
2560 /* Fill in struct details for srb channels */
2561 p_rlc_lte_info
->rlcMode
= mode
;
2562 p_rlc_lte_info
->direction
= direction
;
2563 p_rlc_lte_info
->priority
= priority
;
2564 p_rlc_lte_info
->ueid
= ueid
;
2565 p_rlc_lte_info
->channelType
= channelType
;
2566 p_rlc_lte_info
->channelId
= channelId
;
2567 p_rlc_lte_info
->pduLength
= data_length
;
2568 p_rlc_lte_info
->UMSequenceNumberLength
= UMSequenceNumberLength
;
2570 /* Store info in packet */
2571 p_add_proto_data(pinfo
->fd
, proto_rlc_lte
, 0, p_rlc_lte_info
);
2573 if (global_mac_lte_layer_to_show
!= ShowRLCLayer
) {
2574 /* Don't want these columns replaced */
2575 col_set_writable(pinfo
->cinfo
, FALSE
);
2578 /* Clear info column before first RLC PDU */
2579 if (s_number_of_rlc_pdus_shown
== 0) {
2580 col_clear(pinfo
->cinfo
, COL_INFO
);
2583 /* Add a separator and protect column contents here */
2584 write_pdu_label_and_info_literal(pdu_ti
, NULL
, pinfo
, " || ");
2585 col_set_fence(pinfo
->cinfo
, COL_INFO
);
2588 s_number_of_rlc_pdus_shown
++;
2590 /* Call it (catch exceptions so that stats will be updated) */
2591 call_with_catch_all(rlc_lte_handle
, rb_tvb
, pinfo
, tree
);
2593 /* Let columns be written to again */
2594 col_set_writable(pinfo
->cinfo
, TRUE
);
2598 /* For DL frames, look for previous Tx. Add link back if found */
2599 static void TrackReportedDLHARQResend(packet_info
*pinfo
, tvbuff_t
*tvb
, volatile int length
,
2600 proto_tree
*tree
, mac_lte_info
*p_mac_lte_info
)
2602 DLHARQResult
*result
= NULL
;
2603 DLHARQResult
*original_result
= NULL
;
2605 /* If don't have detailed DL PHy info, just give up */
2606 if (!p_mac_lte_info
->detailed_phy_info
.dl_info
.present
) {
2610 /* TDD may not work... */
2612 if (!pinfo
->fd
->flags
.visited
) {
2613 /* First time, so set result and update DL harq table */
2614 LastFrameData
*lastData
= NULL
;
2615 LastFrameData
*thisData
= NULL
;
2617 DLHarqBuffers
*ueData
;
2619 /* Read these for convenience */
2620 guint8 harq_id
= p_mac_lte_info
->detailed_phy_info
.dl_info
.harq_id
;
2621 guint8 transport_block
= p_mac_lte_info
->detailed_phy_info
.dl_info
.transport_block
;
2623 /* Check harq-id bounds, give up if invalid */
2624 if ((harq_id
>= 15) || (transport_block
> 1)) {
2628 /* Look up entry for this UE/RNTI */
2629 ueData
= (DLHarqBuffers
*)g_hash_table_lookup(mac_lte_dl_harq_hash
, GUINT_TO_POINTER((guint
)p_mac_lte_info
->rnti
));
2631 if (ueData
!= NULL
) {
2632 /* Get previous info for this harq-id */
2633 lastData
= &(ueData
->harqid
[transport_block
][harq_id
]);
2634 if (lastData
->inUse
) {
2635 /* Compare time difference, ndi, data to see if this looks like a retx */
2636 if ((length
== lastData
->length
) &&
2637 (p_mac_lte_info
->detailed_phy_info
.dl_info
.ndi
== lastData
->ndi
) &&
2638 tvb_memeql(tvb
, 0, lastData
->data
, MIN(lastData
->length
, MAX_EXPECTED_PDU_LENGTH
)) == 0) {
2640 /* Work out gap between frames */
2641 gint seconds_between_packets
= (gint
)
2642 (pinfo
->fd
->abs_ts
.secs
- lastData
->received_time
.secs
);
2643 gint nseconds_between_packets
=
2644 pinfo
->fd
->abs_ts
.nsecs
- lastData
->received_time
.nsecs
;
2646 /* Round difference to nearest millisecond */
2647 gint total_gap
= (seconds_between_packets
*1000) +
2648 ((nseconds_between_packets
+500000) / 1000000);
2650 /* Expect to be within (say) 8-13 subframes since previous */
2651 if ((total_gap
>= 8) && (total_gap
<= 13)) {
2653 /* Resend detected! Store result pointing back. */
2654 result
= wmem_new0(wmem_file_scope(), DLHARQResult
);
2655 result
->previousSet
= TRUE
;
2656 result
->previousFrameNum
= lastData
->framenum
;
2657 result
->timeSincePreviousFrame
= total_gap
;
2658 g_hash_table_insert(mac_lte_dl_harq_result_hash
, GUINT_TO_POINTER(pinfo
->fd
->num
), result
);
2660 /* Now make previous frame point forward to here */
2661 original_result
= (DLHARQResult
*)g_hash_table_lookup(mac_lte_dl_harq_result_hash
, GUINT_TO_POINTER(lastData
->framenum
));
2662 if (original_result
== NULL
) {
2663 original_result
= wmem_new0(wmem_file_scope(), DLHARQResult
);
2664 g_hash_table_insert(mac_lte_dl_harq_result_hash
, GUINT_TO_POINTER(lastData
->framenum
), original_result
);
2666 original_result
->nextSet
= TRUE
;
2667 original_result
->nextFrameNum
= pinfo
->fd
->num
;
2668 original_result
->timeToNextFrame
= total_gap
;
2674 /* Allocate entry in table for this UE/RNTI */
2675 ueData
= wmem_new0(wmem_file_scope(), DLHarqBuffers
);
2676 g_hash_table_insert(mac_lte_dl_harq_hash
, GUINT_TO_POINTER((guint
)p_mac_lte_info
->rnti
), ueData
);
2679 /* Store this frame's details in table */
2680 thisData
= &(ueData
->harqid
[transport_block
][harq_id
]);
2681 thisData
->inUse
= TRUE
;
2682 thisData
->length
= length
;
2683 tvb_memcpy(tvb
, thisData
->data
, 0, MIN(thisData
->length
, MAX_EXPECTED_PDU_LENGTH
));
2684 thisData
->ndi
= p_mac_lte_info
->detailed_phy_info
.dl_info
.ndi
;
2685 thisData
->framenum
= pinfo
->fd
->num
;
2686 thisData
->received_time
= pinfo
->fd
->abs_ts
;
2689 /* Not first time, so just set whats already stored in result */
2690 result
= (DLHARQResult
*)g_hash_table_lookup(mac_lte_dl_harq_result_hash
, GUINT_TO_POINTER(pinfo
->fd
->num
));
2694 /***************************************************/
2695 /* Show link back to original frame (if available) */
2696 if (result
!= NULL
) {
2697 if (result
->previousSet
) {
2699 proto_item
*original_ti
= proto_tree_add_uint(tree
, hf_mac_lte_dl_harq_resend_original_frame
,
2700 tvb
, 0, 0, result
->previousFrameNum
);
2701 PROTO_ITEM_SET_GENERATED(original_ti
);
2703 gap_ti
= proto_tree_add_uint(tree
, hf_mac_lte_dl_harq_resend_time_since_previous_frame
,
2704 tvb
, 0, 0, result
->timeSincePreviousFrame
);
2705 PROTO_ITEM_SET_GENERATED(gap_ti
);
2708 if (result
->nextSet
) {
2710 proto_item
*next_ti
= proto_tree_add_uint(tree
, hf_mac_lte_dl_harq_resend_next_frame
,
2711 tvb
, 0, 0, result
->nextFrameNum
);
2712 PROTO_ITEM_SET_GENERATED(next_ti
);
2714 gap_ti
= proto_tree_add_uint(tree
, hf_mac_lte_dl_harq_resend_time_until_next_frame
,
2715 tvb
, 0, 0, result
->timeToNextFrame
);
2716 PROTO_ITEM_SET_GENERATED(gap_ti
);
2723 /* Return TRUE if the given packet is thought to be a retx */
2724 int is_mac_lte_frame_retx(packet_info
*pinfo
, guint8 direction
)
2726 struct mac_lte_info
*p_mac_lte_info
= (struct mac_lte_info
*)p_get_proto_data(pinfo
->fd
, proto_mac_lte
, 0);
2728 if (p_mac_lte_info
== NULL
) {
2732 if (direction
== DIRECTION_UPLINK
) {
2733 /* For UL, retx count is stored in per-packet struct */
2734 return (p_mac_lte_info
->reTxCount
> 0);
2737 /* Use answer if told directly */
2738 if (p_mac_lte_info
->dl_retx
== dl_retx_yes
) {
2742 /* Otherwise look up in table */
2743 DLHARQResult
*result
= (DLHARQResult
*)g_hash_table_lookup(mac_lte_dl_harq_result_hash
, GUINT_TO_POINTER(pinfo
->fd
->num
));
2744 return ((result
!= NULL
) && result
->previousSet
);
2750 /* Track UL frames, so that when a retx is indicated, we can search for
2751 the original tx. We will either find it, and provide a link back to it,
2752 or flag that we couldn't find as an expert error */
2753 static void TrackReportedULHARQResend(packet_info
*pinfo
, tvbuff_t
*tvb
, volatile int offset
,
2754 proto_tree
*tree
, mac_lte_info
*p_mac_lte_info
,
2755 proto_item
*retx_ti
)
2757 ULHARQResult
*result
= NULL
;
2759 /* If don't have detailed DL PHY info, just give up */
2760 if (!p_mac_lte_info
->detailed_phy_info
.ul_info
.present
) {
2764 /* Give up if harqid is out of range */
2765 if (p_mac_lte_info
->detailed_phy_info
.ul_info
.harq_id
>= 8) {
2769 if (!pinfo
->fd
->flags
.visited
) {
2770 /* First time, so set result and update UL harq table */
2771 LastFrameData
*lastData
= NULL
;
2772 LastFrameData
*thisData
= NULL
;
2774 /* Look up entry for this UE/RNTI */
2775 ULHarqBuffers
*ueData
= (ULHarqBuffers
*)g_hash_table_lookup(
2776 mac_lte_ul_harq_hash
, GUINT_TO_POINTER((guint
)p_mac_lte_info
->rnti
));
2777 if (ueData
!= NULL
) {
2778 if (p_mac_lte_info
->reTxCount
>= 1) {
2779 /* Looking for frame previously on this harq-id */
2780 lastData
= &(ueData
->harqid
[p_mac_lte_info
->detailed_phy_info
.ul_info
.harq_id
]);
2781 if (lastData
->inUse
) {
2782 /* Compare time, sf, data to see if this looks like a retx */
2783 if ((tvb_length_remaining(tvb
, offset
) == lastData
->length
) &&
2784 (p_mac_lte_info
->detailed_phy_info
.ul_info
.ndi
== lastData
->ndi
) &&
2785 tvb_memeql(tvb
, offset
, lastData
->data
, MIN(lastData
->length
, MAX_EXPECTED_PDU_LENGTH
)) == 0) {
2787 /* Work out gap between frames */
2788 gint seconds_between_packets
= (gint
)
2789 (pinfo
->fd
->abs_ts
.secs
- lastData
->received_time
.secs
);
2790 gint nseconds_between_packets
=
2791 pinfo
->fd
->abs_ts
.nsecs
- lastData
->received_time
.nsecs
;
2793 /* Round to nearest ms */
2794 gint total_gap
= (seconds_between_packets
*1000) +
2795 ((nseconds_between_packets
+500000) / 1000000);
2797 /* Could be as many as max-tx (which we don't know) * 8ms ago.
2798 32 is the most I've seen... */
2799 if (total_gap
<= 33) {
2800 ULHARQResult
*original_result
;
2802 /* Original detected!!! Store result pointing back */
2803 result
= wmem_new0(wmem_file_scope(), ULHARQResult
);
2804 result
->previousSet
= TRUE
;
2805 result
->previousFrameNum
= lastData
->framenum
;
2806 result
->timeSincePreviousFrame
= total_gap
;
2807 g_hash_table_insert(mac_lte_ul_harq_result_hash
, GUINT_TO_POINTER(pinfo
->fd
->num
), result
);
2809 /* Now make previous frame point forward to here */
2810 original_result
= (ULHARQResult
*)g_hash_table_lookup(mac_lte_ul_harq_result_hash
, GUINT_TO_POINTER(lastData
->framenum
));
2811 if (original_result
== NULL
) {
2812 original_result
= wmem_new0(wmem_file_scope(), ULHARQResult
);
2813 g_hash_table_insert(mac_lte_ul_harq_result_hash
, GUINT_TO_POINTER(lastData
->framenum
), original_result
);
2815 original_result
->nextSet
= TRUE
;
2816 original_result
->nextFrameNum
= pinfo
->fd
->num
;
2817 original_result
->timeToNextFrame
= total_gap
;
2824 /* Allocate entry in table for this UE/RNTI */
2825 ueData
= wmem_new0(wmem_file_scope(), ULHarqBuffers
);
2826 g_hash_table_insert(mac_lte_ul_harq_hash
, GUINT_TO_POINTER((guint
)p_mac_lte_info
->rnti
), ueData
);
2829 /* Store this frame's details in table */
2830 thisData
= &(ueData
->harqid
[p_mac_lte_info
->detailed_phy_info
.ul_info
.harq_id
]);
2831 thisData
->inUse
= TRUE
;
2832 thisData
->length
= tvb_length_remaining(tvb
, offset
);
2833 tvb_memcpy(tvb
, thisData
->data
, offset
, MIN(thisData
->length
, MAX_EXPECTED_PDU_LENGTH
));
2834 thisData
->ndi
= p_mac_lte_info
->detailed_phy_info
.ul_info
.ndi
;
2835 thisData
->framenum
= pinfo
->fd
->num
;
2836 thisData
->received_time
= pinfo
->fd
->abs_ts
;
2839 /* Not first time, so just get whats already stored in result */
2840 result
= (ULHARQResult
*)g_hash_table_lookup(mac_lte_ul_harq_result_hash
, GUINT_TO_POINTER(pinfo
->fd
->num
));
2843 /* Show any link back to previous Tx */
2844 if (retx_ti
!= NULL
) {
2845 if (result
!= NULL
) {
2846 if (result
->previousSet
) {
2847 proto_item
*original_ti
, *gap_ti
;
2849 original_ti
= proto_tree_add_uint(tree
, hf_mac_lte_ul_harq_resend_original_frame
,
2850 tvb
, 0, 0, result
->previousFrameNum
);
2851 PROTO_ITEM_SET_GENERATED(original_ti
);
2853 gap_ti
= proto_tree_add_uint(tree
, hf_mac_lte_ul_harq_resend_time_since_previous_frame
,
2854 tvb
, 0, 0, result
->timeSincePreviousFrame
);
2855 PROTO_ITEM_SET_GENERATED(gap_ti
);
2859 expert_add_info_format(pinfo
, retx_ti
, &ei_mac_lte_orig_tx_ul_frame_not_found
,
2860 "Original Tx of UL frame not found (UE %u) !!", p_mac_lte_info
->ueid
);
2864 /* Show link forward to any known next Tx */
2865 if ((result
!= NULL
) && result
->nextSet
) {
2866 proto_item
*next_ti
, *gap_ti
;
2868 next_ti
= proto_tree_add_uint(tree
, hf_mac_lte_ul_harq_resend_next_frame
,
2869 tvb
, 0, 0, result
->nextFrameNum
);
2870 expert_add_info_format(pinfo
, next_ti
, &ei_mac_lte_ul_harq_resend_next_frame
,
2871 "UL MAC PDU (UE %u) needed to be retransmitted", p_mac_lte_info
->ueid
);
2873 PROTO_ITEM_SET_GENERATED(next_ti
);
2875 gap_ti
= proto_tree_add_uint(tree
, hf_mac_lte_ul_harq_resend_time_until_next_frame
,
2876 tvb
, 0, 0, result
->timeToNextFrame
);
2877 PROTO_ITEM_SET_GENERATED(gap_ti
);
2882 /* Look up SRResult associated with a given frame. Will create one if necessary
2883 if can_create is set */
2884 static SRResult
*GetSRResult(guint32 frameNum
, gboolean can_create
)
2887 result
= (SRResult
*)g_hash_table_lookup(mac_lte_sr_request_hash
, GUINT_TO_POINTER(frameNum
));
2889 if ((result
== NULL
) && can_create
) {
2890 result
= wmem_new0(wmem_file_scope(), SRResult
);
2891 g_hash_table_insert(mac_lte_sr_request_hash
, GUINT_TO_POINTER((guint
)frameNum
), result
);
2897 /* Keep track of SR requests, failures and related grants, in order to show them
2898 as generated fields in these frames */
2899 static void TrackSRInfo(SREvent event
, packet_info
*pinfo
, proto_tree
*tree
,
2900 tvbuff_t
*tvb
, mac_lte_info
*p_mac_lte_info
, gint idx
, proto_item
*event_ti
)
2902 SRResult
*result
= NULL
;
2904 SRResult
*resultForSRFrame
= NULL
;
2910 /* Get appropriate identifiers */
2911 if (event
== SR_Request
) {
2912 rnti
= p_mac_lte_info
->oob_rnti
[idx
];
2913 ueid
= p_mac_lte_info
->oob_ueid
[idx
];
2916 rnti
= p_mac_lte_info
->rnti
;
2917 ueid
= p_mac_lte_info
->ueid
;
2920 /* Create state for this RNTI if necessary */
2921 state
= (SRState
*)g_hash_table_lookup(mac_lte_ue_sr_state
, GUINT_TO_POINTER((guint
)rnti
));
2922 if (state
== NULL
) {
2923 /* Allocate status for this RNTI */
2924 state
= wmem_new(wmem_file_scope(), SRState
);
2925 state
->status
= None
;
2926 g_hash_table_insert(mac_lte_ue_sr_state
, GUINT_TO_POINTER((guint
)rnti
), state
);
2929 /* First time through - update state with new info */
2930 if (!pinfo
->fd
->flags
.visited
) {
2931 guint32 timeSinceRequest
;
2933 /* Store time of request */
2934 if (event
== SR_Request
) {
2935 state
->requestTime
= pinfo
->fd
->abs_ts
;
2938 switch (state
->status
) {
2942 /* Got another grant - fine */
2945 state
->lastGrantFramenum
= pinfo
->fd
->num
;
2949 /* Sent an SR - fine */
2952 state
->status
= SR_Outstanding
;
2953 state
->lastSRFramenum
= pinfo
->fd
->num
;
2957 /* This is an error, since we hadn't send an SR... */
2958 result
= GetSRResult(pinfo
->fd
->num
, TRUE
);
2959 result
->type
= InvalidSREvent
;
2960 result
->status
= None
;
2961 result
->event
= SR_Failure
;
2966 case SR_Outstanding
:
2967 timeSinceRequest
= (guint32
)(((pinfo
->fd
->abs_ts
.secs
- state
->requestTime
.secs
) * 1000) +
2968 ((pinfo
->fd
->abs_ts
.nsecs
- state
->requestTime
.nsecs
) / 1000000));
2972 /* Got grant we were waiting for, so state goes to None */
2975 state
->status
= None
;
2977 /* Set result info */
2978 result
= GetSRResult(pinfo
->fd
->num
, TRUE
);
2979 result
->type
= GrantAnsweringSR
;
2980 result
->frameNum
= state
->lastSRFramenum
;
2981 result
->timeDifference
= timeSinceRequest
;
2983 /* Also set forward link for SR */
2984 resultForSRFrame
= GetSRResult(state
->lastSRFramenum
, TRUE
);
2985 resultForSRFrame
->type
= SRLeadingToGrant
;
2986 resultForSRFrame
->frameNum
= pinfo
->fd
->num
;
2987 resultForSRFrame
->timeDifference
= timeSinceRequest
;
2991 /* Another request when already have one pending */
2992 result
= GetSRResult(pinfo
->fd
->num
, TRUE
);
2993 result
->type
= InvalidSREvent
;
2994 result
->status
= SR_Outstanding
;
2995 result
->event
= SR_Request
;
2999 /* We sent an SR but it failed */
3002 state
->status
= SR_Failed
;
3004 /* Set result info for failure frame */
3005 result
= GetSRResult(pinfo
->fd
->num
, TRUE
);
3006 result
->type
= FailureAnsweringSR
;
3007 result
->frameNum
= state
->lastSRFramenum
;
3008 result
->timeDifference
= timeSinceRequest
;
3010 /* Also set forward link for SR */
3011 resultForSRFrame
= GetSRResult(state
->lastSRFramenum
, TRUE
);
3012 resultForSRFrame
->type
= SRLeadingToFailure
;
3013 resultForSRFrame
->frameNum
= pinfo
->fd
->num
;
3014 resultForSRFrame
->timeDifference
= timeSinceRequest
;
3022 /* Got a grant, presumably after a subsequent RACH - fine */
3025 state
->status
= None
;
3029 /* Tried another SR after previous one failed.
3030 Presumably a subsequent RACH was tried in-between... */
3032 state
->status
= SR_Outstanding
;
3034 result
= GetSRResult(pinfo
->fd
->num
, TRUE
);
3035 result
->status
= SR_Outstanding
;
3036 result
->event
= SR_Request
;
3040 /* 2 failures in a row.... */
3041 result
= GetSRResult(pinfo
->fd
->num
, TRUE
);
3042 result
->type
= InvalidSREvent
;
3043 result
->status
= SR_Failed
;
3044 result
->event
= SR_Failure
;
3051 /* Get stored result for this frame */
3052 result
= GetSRResult(pinfo
->fd
->num
, FALSE
);
3053 if (result
== NULL
) {
3054 /* For an SR frame, there should always be either a PDCCH grant or indication
3055 that the SR has failed */
3056 if (event
== SR_Request
) {
3057 expert_add_info_format(pinfo
, event_ti
, &ei_mac_lte_sr_results_not_grant_or_failure_indication
,
3058 "UE %u: SR results in neither a grant nor a failure indication",
3065 /* Show result info */
3066 switch (result
->type
) {
3067 case GrantAnsweringSR
:
3068 ti
= proto_tree_add_uint(tree
, hf_mac_lte_grant_answering_sr
,
3069 tvb
, 0, 0, result
->frameNum
);
3070 PROTO_ITEM_SET_GENERATED(ti
);
3071 ti
= proto_tree_add_uint(tree
, hf_mac_lte_sr_time_since_request
,
3072 tvb
, 0, 0, result
->timeDifference
);
3073 PROTO_ITEM_SET_GENERATED(ti
);
3076 case FailureAnsweringSR
:
3077 ti
= proto_tree_add_uint(tree
, hf_mac_lte_failure_answering_sr
,
3078 tvb
, 0, 0, result
->frameNum
);
3079 PROTO_ITEM_SET_GENERATED(ti
);
3080 ti
= proto_tree_add_uint(tree
, hf_mac_lte_sr_time_since_request
,
3081 tvb
, 0, 0, result
->timeDifference
);
3082 PROTO_ITEM_SET_GENERATED(ti
);
3085 case SRLeadingToGrant
:
3086 ti
= proto_tree_add_uint(tree
, hf_mac_lte_sr_leading_to_grant
,
3087 tvb
, 0, 0, result
->frameNum
);
3088 PROTO_ITEM_SET_GENERATED(ti
);
3089 ti
= proto_tree_add_uint(tree
, hf_mac_lte_sr_time_until_answer
,
3090 tvb
, 0, 0, result
->timeDifference
);
3091 PROTO_ITEM_SET_GENERATED(ti
);
3095 case SRLeadingToFailure
:
3096 ti
= proto_tree_add_uint(tree
, hf_mac_lte_sr_leading_to_failure
,
3097 tvb
, 0, 0, result
->frameNum
);
3098 PROTO_ITEM_SET_GENERATED(ti
);
3099 ti
= proto_tree_add_uint(tree
, hf_mac_lte_sr_time_until_answer
,
3100 tvb
, 0, 0, result
->timeDifference
);
3101 PROTO_ITEM_SET_GENERATED(ti
);
3104 case InvalidSREvent
:
3105 proto_tree_add_expert_format(tree
, pinfo
, &ei_mac_lte_sr_invalid_event
,
3106 tvb
, 0, 0, "UE %u: Invalid SR event - state=%s, event=%s",
3108 val_to_str_const(result
->status
, sr_status_vals
, "Unknown"),
3109 val_to_str_const(result
->event
, sr_event_vals
, "Unknown"));
3115 /********************************************************/
3116 /* Count number of UEs/TTI (in both directions) */
3117 /********************************************************/
3119 /* For keeping track during first pass */
3120 typedef struct tti_info_t
{
3122 nstime_t ttiStartTime
;
3126 static tti_info_t UL_tti_info
;
3127 static tti_info_t DL_tti_info
;
3129 /* For associating with frame and displaying */
3130 typedef struct TTIInfoResult_t
{
3134 /* This table stores (FrameNumber -> *TTIInfoResult_t). It is assigned during the first
3135 pass and used thereafter */
3136 static GHashTable
*mac_lte_tti_info_result_hash
= NULL
;
3139 /* Work out which UE this is within TTI (within direction). Return answer */
3140 static guint16
count_ues_tti(mac_lte_info
*p_mac_lte_info
, packet_info
*pinfo
)
3142 gboolean same_tti
= FALSE
;
3143 tti_info_t
*tti_info
;
3145 /* Just return any previous result */
3146 TTIInfoResult_t
*result
= (TTIInfoResult_t
*)g_hash_table_lookup(mac_lte_tti_info_result_hash
, GUINT_TO_POINTER(pinfo
->fd
->num
));
3147 if (result
!= NULL
) {
3148 return result
->ues_in_tti
;
3151 /* Set tti_info based upon direction */
3152 if (p_mac_lte_info
->direction
== DIRECTION_UPLINK
) {
3153 tti_info
= &UL_tti_info
;
3156 tti_info
= &DL_tti_info
;
3159 /* Work out if we are still in the same tti as before */
3160 if (tti_info
->subframe
== p_mac_lte_info
->subframeNumber
) {
3161 gint seconds_between_packets
= (gint
)
3162 (pinfo
->fd
->abs_ts
.secs
- tti_info
->ttiStartTime
.secs
);
3163 gint nseconds_between_packets
=
3164 pinfo
->fd
->abs_ts
.nsecs
- tti_info
->ttiStartTime
.nsecs
;
3166 /* Round difference to nearest microsecond */
3167 gint total_us_gap
= (seconds_between_packets
*1000000) +
3168 ((nseconds_between_packets
+500) / 1000);
3170 if (total_us_gap
< 1000) {
3175 /* Update global state */
3177 tti_info
->subframe
= p_mac_lte_info
->subframeNumber
;
3178 tti_info
->ttiStartTime
= pinfo
->fd
->abs_ts
;
3179 tti_info
->ues_in_tti
= 1;
3182 tti_info
->ues_in_tti
++;
3185 /* Set result state for this frame */
3186 result
= wmem_new(wmem_file_scope(), TTIInfoResult_t
);
3187 result
->ues_in_tti
= tti_info
->ues_in_tti
;
3188 g_hash_table_insert(mac_lte_tti_info_result_hash
,
3189 GUINT_TO_POINTER(pinfo
->fd
->num
), result
);
3191 return tti_info
->ues_in_tti
;
3195 /* Show which UE this is (within direction) for this TTI */
3196 static void show_ues_tti(packet_info
*pinfo
, mac_lte_info
*p_mac_lte_info
, tvbuff_t
*tvb
, proto_tree
*context_tree
)
3198 /* Look up result */
3199 TTIInfoResult_t
*result
= (TTIInfoResult_t
*)g_hash_table_lookup(mac_lte_tti_info_result_hash
, GUINT_TO_POINTER(pinfo
->fd
->num
));
3200 if (result
!= NULL
) {
3201 proto_item
*ti
= proto_tree_add_uint(context_tree
,
3202 (p_mac_lte_info
->direction
== DIRECTION_UPLINK
) ?
3203 hf_mac_lte_ues_ul_per_tti
:
3204 hf_mac_lte_ues_dl_per_tti
,
3205 tvb
, 0, 0, result
->ues_in_tti
);
3206 PROTO_ITEM_SET_GENERATED(ti
);
3212 /* Lookup channel details for lcid */
3213 static void lookup_rlc_channel_from_lcid(guint16 ueid
,
3215 rlc_channel_type_t
*rlc_channel_type
,
3216 guint8
*UM_seqnum_length
,
3219 /* Zero params (in case no match is found) */
3220 *rlc_channel_type
= rlcRaw
;
3221 *UM_seqnum_length
= 0;
3224 if (global_mac_lte_lcid_drb_source
== (int)FromStaticTable
) {
3226 /* Look up in static (UAT) table */
3228 for (m
=0; m
< num_lcid_drb_mappings
; m
++) {
3229 if (lcid
== lcid_drb_mappings
[m
].lcid
) {
3231 *rlc_channel_type
= lcid_drb_mappings
[m
].channel_type
;
3233 /* Set UM_seqnum_length */
3234 switch (*rlc_channel_type
) {
3236 *UM_seqnum_length
= 5;
3239 *UM_seqnum_length
= 10;
3246 *drb_id
= lcid_drb_mappings
[m
].drbid
;
3252 /* Look up the mappings for this UE */
3253 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
));
3258 /* Look up setting gleaned from configuration protocol */
3259 if (!ue_mappings
->mapping
[lcid
].valid
) {
3263 *rlc_channel_type
= ue_mappings
->mapping
[lcid
].channel_type
;
3265 /* Set UM_seqnum_length */
3266 switch (*rlc_channel_type
) {
3268 *UM_seqnum_length
= 5;
3271 *UM_seqnum_length
= 10;
3278 *drb_id
= ue_mappings
->mapping
[lcid
].drbid
;
3284 #define MAX_HEADERS_IN_PDU 1024
3286 /* UL-SCH and DL-SCH formats have much in common, so handle them in a common
3288 static void dissect_ulsch_or_dlsch(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
3290 volatile guint32 offset
, guint8 direction
,
3291 mac_lte_info
*p_mac_lte_info
, mac_lte_tap_info
*tap_info
,
3292 proto_item
*retx_ti
,
3293 proto_tree
*context_tree
)
3297 proto_item
*truncated_ti
;
3298 proto_item
*padding_length_ti
;
3299 proto_item
*hidden_root_ti
;
3301 /* Keep track of LCIDs and lengths as we dissect the header */
3302 volatile guint16 number_of_headers
= 0;
3303 guint8 lcids
[MAX_HEADERS_IN_PDU
];
3304 gint16 pdu_lengths
[MAX_HEADERS_IN_PDU
];
3306 proto_item
*pdu_header_ti
;
3307 proto_tree
*pdu_header_tree
;
3309 gboolean have_seen_data_header
= FALSE
;
3310 guint8 number_of_padding_subheaders
= 0;
3311 gboolean have_seen_non_padding_control
= FALSE
;
3312 gboolean have_seen_bsr
= FALSE
;
3313 gboolean expecting_body_data
= FALSE
;
3314 volatile guint32 is_truncated
= FALSE
;
3316 /* Maintain/show UEs/TTI count */
3317 tap_info
->ueInTTI
= count_ues_tti(p_mac_lte_info
, pinfo
);
3318 show_ues_tti(pinfo
, p_mac_lte_info
, tvb
, context_tree
);
3320 write_pdu_label_and_info(pdu_ti
, NULL
, pinfo
,
3321 "%s: (SF=%u) UEId=%-3u ",
3322 (direction
== DIRECTION_UPLINK
) ? "UL-SCH" : "DL-SCH",
3323 p_mac_lte_info
->subframeNumber
,
3324 p_mac_lte_info
->ueid
);
3326 tap_info
->raw_length
= p_mac_lte_info
->length
;
3328 /******************************************************/
3329 /* DRX information */
3331 /* Update DRX state of UE */
3332 if (global_mac_lte_show_drx
) {
3333 if (!pinfo
->fd
->flags
.visited
) {
3335 /* Update UE state to this subframe (but before this event is processed) */
3336 update_drx_info(pinfo
, p_mac_lte_info
);
3338 /* Store 'before' snapshot of UE state for this frame */
3339 set_drx_info(pinfo
, p_mac_lte_info
, TRUE
);
3342 /* Show current DRX state in tree as 'before' */
3343 show_drx_info(pinfo
, tree
, tvb
, p_mac_lte_info
, TRUE
);
3345 /* Changes of state caused by events */
3346 if (!pinfo
->fd
->flags
.visited
) {
3347 if ((p_mac_lte_info
->reTxCount
== 0) && (p_mac_lte_info
->direction
== DIRECTION_UPLINK
)) {
3348 mac_lte_drx_new_ulsch_data(p_mac_lte_info
->ueid
);
3352 if (p_mac_lte_info
->crcStatusValid
!= crc_success
) {
3353 mac_lte_drx_dl_crc_error(p_mac_lte_info
->ueid
);
3355 else if (p_mac_lte_info
->reTxCount
== 0) {
3356 mac_lte_drx_new_dlsch_data(p_mac_lte_info
->ueid
);
3363 /* For uplink frames, if this is logged as a resend, look for original tx */
3364 if (direction
== DIRECTION_UPLINK
) {
3365 TrackReportedULHARQResend(pinfo
, tvb
, offset
, tree
, p_mac_lte_info
, retx_ti
);
3368 /* For uplink grants, update SR status. N.B. only newTx grant should stop SR */
3369 if ((direction
== DIRECTION_UPLINK
) && (p_mac_lte_info
->reTxCount
== 0) &&
3370 global_mac_lte_track_sr
) {
3372 TrackSRInfo(SR_Grant
, pinfo
, tree
, tvb
, p_mac_lte_info
, 0, NULL
);
3375 /* Add hidden item to filter on */
3376 hidden_root_ti
= proto_tree_add_string_format(tree
,
3377 (direction
== DIRECTION_UPLINK
) ?
3383 PROTO_ITEM_SET_HIDDEN(hidden_root_ti
);
3385 /* Add PDU block header subtree */
3386 pdu_header_ti
= proto_tree_add_string_format(tree
,
3387 (direction
== DIRECTION_UPLINK
) ?
3388 hf_mac_lte_ulsch_header
:
3389 hf_mac_lte_dlsch_header
,
3393 pdu_header_tree
= proto_item_add_subtree(pdu_header_ti
,
3394 (direction
== DIRECTION_UPLINK
) ?
3395 ett_mac_lte_ulsch_header
:
3396 ett_mac_lte_dlsch_header
);
3399 /************************************************************************/
3400 /* Dissect each sub-header. */
3404 proto_item
*pdu_subheader_ti
;
3405 proto_tree
*pdu_subheader_tree
;
3406 proto_item
*lcid_ti
;
3408 gint offset_start_subheader
= offset
;
3409 guint8 first_byte
= tvb_get_guint8(tvb
, offset
);
3411 /* Add PDU block header subtree.
3412 Default with length of 1 byte. */
3413 pdu_subheader_ti
= proto_tree_add_string_format(pdu_header_tree
,
3414 hf_mac_lte_sch_subheader
,
3418 pdu_subheader_tree
= proto_item_add_subtree(pdu_subheader_ti
,
3419 ett_mac_lte_sch_subheader
);
3421 /* Check 1st 2 reserved bits */
3422 reserved
= (first_byte
& 0xc0) >> 6;
3423 ti
= proto_tree_add_item(pdu_subheader_tree
, hf_mac_lte_sch_reserved
,
3424 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3425 if (reserved
!= 0) {
3426 expert_add_info_format(pinfo
, ti
, &ei_mac_lte_reserved_not_zero
,
3427 "%cL-SCH header Reserved bits not zero",
3428 (p_mac_lte_info
->direction
== DIRECTION_UPLINK
) ? 'U' : 'D');
3432 extension
= (first_byte
& 0x20) >> 5;
3433 proto_tree_add_item(pdu_subheader_tree
, hf_mac_lte_sch_extended
,
3434 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3436 /* LCID. Has different meaning depending upon direction. */
3437 lcids
[number_of_headers
] = first_byte
& 0x1f;
3438 if (direction
== DIRECTION_UPLINK
) {
3440 lcid_ti
= proto_tree_add_item(pdu_subheader_tree
, hf_mac_lte_ulsch_lcid
,
3441 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3442 write_pdu_label_and_info(pdu_ti
, NULL
, pinfo
,
3444 val_to_str_const(lcids
[number_of_headers
],
3445 ulsch_lcid_vals
, "(Unknown LCID)"));
3449 lcid_ti
= proto_tree_add_item(pdu_subheader_tree
, hf_mac_lte_dlsch_lcid
,
3450 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3451 write_pdu_label_and_info(pdu_ti
, NULL
, pinfo
,
3453 val_to_str_const(lcids
[number_of_headers
],
3454 dlsch_lcid_vals
, "(Unknown LCID)"));
3456 if (lcids
[number_of_headers
] == DRX_COMMAND_LCID
) {
3457 expert_add_info_format(pinfo
, lcid_ti
, &ei_mac_lte_dlsch_lcid
,
3458 "DRX command received for UE %u (RNTI %u)",
3459 p_mac_lte_info
->ueid
, p_mac_lte_info
->rnti
);
3464 /* Remember if we've seen a data subheader */
3465 if (lcids
[number_of_headers
] <= 10) {
3466 have_seen_data_header
= TRUE
;
3467 expecting_body_data
= TRUE
;
3470 /* Show an expert item if a contol subheader (except Padding) appears
3471 *after* a data PDU */
3472 if (have_seen_data_header
&&
3473 (lcids
[number_of_headers
] > 10) && (lcids
[number_of_headers
] != PADDING_LCID
)) {
3474 expert_add_info_format(pinfo
, lcid_ti
, &ei_mac_lte_control_subheader_after_data_subheader
,
3475 "%cL-SCH Control subheaders should not appear after data subheaders",
3476 (p_mac_lte_info
->direction
== DIRECTION_UPLINK
) ? 'U' : 'D');
3480 /* Show an expert item if we're seeing more then one BSR in a frame */
3481 if ((direction
== DIRECTION_UPLINK
) && is_bsr_lcid(lcids
[number_of_headers
])) {
3482 if (have_seen_bsr
) {
3483 expert_add_info(pinfo
, lcid_ti
, &ei_mac_lte_control_bsr_multiple
);
3486 have_seen_bsr
= TRUE
;
3489 /* Should not see padding after non-padding control... */
3490 if ((lcids
[number_of_headers
] > 10) &&
3491 (lcids
[number_of_headers
] == PADDING_LCID
) &&
3494 number_of_padding_subheaders
++;
3495 if (number_of_padding_subheaders
> 2) {
3496 expert_add_info(pinfo
, lcid_ti
, &ei_mac_lte_padding_data_multiple
);
3499 if (have_seen_non_padding_control
) {
3500 expert_add_info(pinfo
, lcid_ti
, &ei_mac_lte_padding_data_before_control_subheader
);
3504 /* Also flag if we have final padding but also padding subheaders
3506 if (!extension
&& (lcids
[number_of_headers
] == PADDING_LCID
) &&
3507 (number_of_padding_subheaders
> 0)) {
3508 expert_add_info(pinfo
, lcid_ti
, &ei_mac_lte_padding_data_start_and_end
);
3511 /* Remember that we've seen non-padding control */
3512 if ((lcids
[number_of_headers
] > 10) &&
3513 (lcids
[number_of_headers
] != PADDING_LCID
)) {
3514 have_seen_non_padding_control
= TRUE
;
3519 /********************************************************************/
3520 /* Length field follows if not the last header or for a fixed-sized
3524 if (is_fixed_sized_control_element(lcids
[number_of_headers
], direction
)) {
3525 pdu_lengths
[number_of_headers
] = 0;
3528 pdu_lengths
[number_of_headers
] = -1;
3532 /* Not the last one */
3533 if (!is_fixed_sized_control_element(lcids
[number_of_headers
], direction
) &&
3534 (lcids
[number_of_headers
] != PADDING_LCID
)) {
3538 /* F(ormat) bit tells us how long the length field is */
3539 format
= (tvb_get_guint8(tvb
, offset
) & 0x80) >> 7;
3540 proto_tree_add_item(pdu_subheader_tree
, hf_mac_lte_sch_format
,
3541 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3543 /* Now read length field itself */
3545 /* >= 128 - use 15 bits */
3546 proto_tree_add_bits_ret_val(pdu_subheader_tree
, hf_mac_lte_sch_length
,
3547 tvb
, offset
*8 + 1, 15, &length
, ENC_BIG_ENDIAN
);
3552 /* Less than 128 - only 7 bits */
3553 proto_tree_add_bits_ret_val(pdu_subheader_tree
, hf_mac_lte_sch_length
,
3554 tvb
, offset
*8 + 1, 7, &length
, ENC_BIG_ENDIAN
);
3557 pdu_lengths
[number_of_headers
] = (gint16
)length
;
3560 pdu_lengths
[number_of_headers
] = 0;
3565 /* Close off description in info column */
3566 switch (pdu_lengths
[number_of_headers
]) {
3568 write_pdu_label_and_info_literal(pdu_ti
, NULL
, pinfo
, ") ");
3571 write_pdu_label_and_info_literal(pdu_ti
, NULL
, pinfo
, ":remainder) ");
3574 write_pdu_label_and_info(pdu_ti
, NULL
, pinfo
, ":%u bytes) ",
3575 pdu_lengths
[number_of_headers
]);
3579 /* Append summary to subheader root */
3580 proto_item_append_text(pdu_subheader_ti
, " (lcid=%s",
3581 val_to_str_const(lcids
[number_of_headers
],
3582 (direction
== DIRECTION_UPLINK
) ?
3587 switch (pdu_lengths
[number_of_headers
]) {
3589 proto_item_append_text(pdu_subheader_ti
, ", length is remainder)");
3590 proto_item_append_text(pdu_header_ti
, " (%s:remainder)",
3591 val_to_str_const(lcids
[number_of_headers
],
3592 (direction
== DIRECTION_UPLINK
) ? ulsch_lcid_vals
: dlsch_lcid_vals
,
3596 proto_item_append_text(pdu_subheader_ti
, ")");
3597 proto_item_append_text(pdu_header_ti
, " (%s)",
3598 val_to_str_const(lcids
[number_of_headers
],
3599 (direction
== DIRECTION_UPLINK
) ? ulsch_lcid_vals
: dlsch_lcid_vals
,
3603 proto_item_append_text(pdu_subheader_ti
, ", length=%u)",
3604 pdu_lengths
[number_of_headers
]);
3605 proto_item_append_text(pdu_header_ti
, " (%s:%u)",
3606 val_to_str_const(lcids
[number_of_headers
],
3607 (direction
== DIRECTION_UPLINK
) ? ulsch_lcid_vals
: dlsch_lcid_vals
,
3609 pdu_lengths
[number_of_headers
]);
3614 /* Flag unknown lcid values in expert info */
3615 if (try_val_to_str(lcids
[number_of_headers
],
3616 (direction
== DIRECTION_UPLINK
) ? ulsch_lcid_vals
: dlsch_lcid_vals
) == NULL
) {
3617 expert_add_info_format(pinfo
, pdu_subheader_ti
, &ei_mac_lte_lcid_unexpected
,
3618 "%cL-SCH: Unexpected LCID received (%u)",
3619 (p_mac_lte_info
->direction
== DIRECTION_UPLINK
) ? 'U' : 'D',
3620 lcids
[number_of_headers
]);
3623 /* Set length of this subheader */
3624 proto_item_set_len(pdu_subheader_ti
, offset
- offset_start_subheader
);
3626 number_of_headers
++;
3627 } while ((number_of_headers
< MAX_HEADERS_IN_PDU
) && extension
);
3629 /* Check that we didn't reach the end of the subheader array... */
3630 if (number_of_headers
>= MAX_HEADERS_IN_PDU
) {
3631 proto_tree_add_expert_format(tree
, pinfo
, &ei_mac_lte_too_many_subheaders
, tvb
, offset
, 1,
3632 "Reached %u subheaders - frame obviously malformed",
3633 MAX_HEADERS_IN_PDU
);
3638 /* Append summary to overall PDU header root */
3639 proto_item_append_text(pdu_header_ti
, " [%u subheaders]",
3642 /* And set its length to offset */
3643 proto_item_set_len(pdu_header_ti
, offset
);
3646 /* For DL, see if this is a retx. Use whole PDU present (i.e. ignore padding if not logged) */
3647 if (direction
== DIRECTION_DOWNLINK
) {
3648 /* Result will be added to context tree */
3649 TrackReportedDLHARQResend(pinfo
, tvb
, tvb_length_remaining(tvb
, 0), context_tree
, p_mac_lte_info
);
3651 tap_info
->isPHYRetx
= (p_mac_lte_info
->dl_retx
== dl_retx_yes
);
3655 /************************************************************************/
3656 /* Dissect SDUs / control elements / padding. */
3657 /************************************************************************/
3659 /* Dissect control element bodies first */
3661 for (n
=0; n
< number_of_headers
; n
++) {
3662 /* Get out of loop once see any data SDU subheaders */
3663 if (lcids
[n
] <= 10) {
3664 /* Update tap sdu count for this channel */
3665 tap_info
->sdus_for_lcid
[lcids
[n
]]++;
3669 /* Process what should be a valid control PDU type */
3670 if (direction
== DIRECTION_DOWNLINK
) {
3672 /****************************/
3673 /* DL-SCH Control PDUs */
3675 case ACTIVATION_DEACTIVATION_LCID
:
3678 proto_tree
*ad_tree
;
3682 /* Create AD root */
3683 ad_ti
= proto_tree_add_string_format(tree
,
3684 hf_mac_lte_control_activation_deactivation
,
3687 "Activation/Deactivation");
3688 ad_tree
= proto_item_add_subtree(ad_ti
, ett_mac_lte_activation_deactivation
);
3690 proto_tree_add_item(ad_tree
, hf_mac_lte_control_activation_deactivation_c7
,
3691 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3692 proto_tree_add_item(ad_tree
, hf_mac_lte_control_activation_deactivation_c6
,
3693 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3694 proto_tree_add_item(ad_tree
, hf_mac_lte_control_activation_deactivation_c5
,
3695 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3696 proto_tree_add_item(ad_tree
, hf_mac_lte_control_activation_deactivation_c4
,
3697 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3698 proto_tree_add_item(ad_tree
, hf_mac_lte_control_activation_deactivation_c3
,
3699 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3700 proto_tree_add_item(ad_tree
, hf_mac_lte_control_activation_deactivation_c2
,
3701 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3702 proto_tree_add_item(ad_tree
, hf_mac_lte_control_activation_deactivation_c1
,
3703 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3704 ti
= proto_tree_add_item(ad_tree
, hf_mac_lte_control_activation_deactivation_reserved
,
3705 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3706 reserved
= tvb_get_guint8(tvb
, offset
) & 0x01;
3707 if (reserved
!= 0) {
3708 expert_add_info_format(pinfo
, ti
, &ei_mac_lte_reserved_not_zero
,
3709 "Activation/Deactivation Reserved bit not zero");
3714 case UE_CONTENTION_RESOLUTION_IDENTITY_LCID
:
3717 proto_tree
*cr_tree
;
3719 ContentionResolutionResult
*crResult
;
3721 /* Create CR root */
3722 cr_ti
= proto_tree_add_string_format(tree
,
3723 hf_mac_lte_control_ue_contention_resolution
,
3726 "Contention Resolution");
3727 cr_tree
= proto_item_add_subtree(cr_ti
, ett_mac_lte_contention_resolution
);
3729 /* Contention resolution body */
3730 proto_tree_add_item(cr_tree
, hf_mac_lte_control_ue_contention_resolution_identity
,
3731 tvb
, offset
, 6, ENC_NA
);
3732 if (global_mac_lte_decode_cr_body
) {
3733 tvbuff_t
*cr_body_tvb
= tvb_new_subset(tvb
, offset
, 6, 6);
3734 dissector_handle_t ul_ccch_handle
= find_dissector("lte_rrc.ul_ccch");
3735 if (ul_ccch_handle
!= 0) {
3736 call_with_catch_all(ul_ccch_handle
, cr_body_tvb
, pinfo
, cr_tree
);
3740 /* Get pointer to result struct for this frame */
3741 crResult
= (ContentionResolutionResult
*)g_hash_table_lookup(mac_lte_cr_result_hash
, GUINT_TO_POINTER(pinfo
->fd
->num
));
3742 if (crResult
== NULL
) {
3744 /* Need to set result by looking for and comparing with Msg3 */
3746 guint msg3Key
= p_mac_lte_info
->rnti
;
3748 /* Allocate result and add it to the table */
3749 crResult
= wmem_new(wmem_file_scope(), ContentionResolutionResult
);
3750 g_hash_table_insert(mac_lte_cr_result_hash
, GUINT_TO_POINTER(pinfo
->fd
->num
), crResult
);
3753 msg3Data
= (Msg3Data
*)g_hash_table_lookup(mac_lte_msg3_hash
, GUINT_TO_POINTER(msg3Key
));
3755 /* Compare CCCH bytes */
3756 if (msg3Data
!= NULL
) {
3757 crResult
->msSinceMsg3
= (guint32
)(((pinfo
->fd
->abs_ts
.secs
- msg3Data
->msg3Time
.secs
) * 1000) +
3758 ((pinfo
->fd
->abs_ts
.nsecs
- msg3Data
->msg3Time
.nsecs
) / 1000000));
3759 crResult
->msg3FrameNum
= msg3Data
->framenum
;
3761 /* Compare the 6 bytes */
3762 if (tvb_memeql(tvb
, offset
, msg3Data
->data
, 6) == 0) {
3763 crResult
->status
= Msg3Match
;
3766 crResult
->status
= Msg3NoMatch
;
3770 crResult
->status
= NoMsg3
;
3774 /* Now show CR result in tree */
3775 switch (crResult
->status
) {
3777 proto_item_append_text(cr_ti
, " (no corresponding Msg3 found!)");
3781 ti
= proto_tree_add_uint(cr_tree
, hf_mac_lte_control_ue_contention_resolution_msg3
,
3782 tvb
, 0, 0, crResult
->msg3FrameNum
);
3783 PROTO_ITEM_SET_GENERATED(ti
);
3784 ti
= proto_tree_add_uint(cr_tree
, hf_mac_lte_control_ue_contention_resolution_time_since_msg3
,
3785 tvb
, 0, 0, crResult
->msSinceMsg3
);
3786 PROTO_ITEM_SET_GENERATED(ti
);
3788 ti
= proto_tree_add_boolean(cr_tree
, hf_mac_lte_control_ue_contention_resolution_msg3_matched
,
3790 PROTO_ITEM_SET_GENERATED(ti
);
3791 proto_item_append_text(cr_ti
, " (matches Msg3 from frame %u, %ums ago)",
3792 crResult
->msg3FrameNum
, crResult
->msSinceMsg3
);
3796 ti
= proto_tree_add_uint(cr_tree
, hf_mac_lte_control_ue_contention_resolution_msg3
,
3797 tvb
, 0, 0, crResult
->msg3FrameNum
);
3798 PROTO_ITEM_SET_GENERATED(ti
);
3799 ti
= proto_tree_add_uint(cr_tree
, hf_mac_lte_control_ue_contention_resolution_time_since_msg3
,
3800 tvb
, 0, 0, crResult
->msSinceMsg3
);
3801 PROTO_ITEM_SET_GENERATED(ti
);
3803 ti
= proto_tree_add_boolean(cr_tree
, hf_mac_lte_control_ue_contention_resolution_msg3_matched
,
3805 expert_add_info_format(pinfo
, ti
, &ei_mac_lte_control_ue_contention_resolution_msg3_matched
,
3806 "CR body in Msg4 doesn't match Msg3 CCCH in frame %u",
3807 crResult
->msg3FrameNum
);
3808 PROTO_ITEM_SET_GENERATED(ti
);
3809 proto_item_append_text(cr_ti
, " (doesn't match Msg3 from frame %u, %u ago)",
3810 crResult
->msg3FrameNum
, crResult
->msSinceMsg3
);
3817 case TIMING_ADVANCE_LCID
:
3820 proto_item
*ta_value_ti
;
3821 proto_tree
*ta_tree
;
3824 /* Create TA root */
3825 ta_ti
= proto_tree_add_string_format(tree
,
3826 hf_mac_lte_control_timing_advance
,
3830 ta_tree
= proto_item_add_subtree(ta_ti
, ett_mac_lte_timing_advance
);
3833 proto_tree_add_item(ta_tree
, hf_mac_lte_control_timing_advance_group_id
,
3834 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3837 ta_value
= tvb_get_guint8(tvb
, offset
) & 0x3f;
3838 ta_value_ti
= proto_tree_add_item(ta_tree
, hf_mac_lte_control_timing_advance_command
,
3839 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3841 if (ta_value
== 31) {
3842 expert_add_info(pinfo
, ta_value_ti
, &ei_mac_lte_control_timing_advance_command_no_correction
);
3845 expert_add_info_format(pinfo
, ta_value_ti
, &ei_mac_lte_control_timing_advance_command_correction_needed
,
3846 "Timing Advance control element received (%u) %s correction needed",
3848 (ta_value
< 31) ? "-ve" : "+ve");
3853 case DRX_COMMAND_LCID
:
3855 mac_lte_drx_control_element_received(p_mac_lte_info
->ueid
);
3858 /* No payload (in this position) */
3859 tap_info
->padding_bytes
++;
3868 /**********************************/
3869 /* UL-SCH Control PDUs */
3871 case EXTENDED_POWER_HEADROOM_REPORT_LCID
:
3873 proto_item
*ephr_ti
;
3874 proto_tree
*ephr_tree
;
3876 proto_tree
*ephr_cell_tree
;
3877 proto_item
*ephr_cell_ti
;
3878 guint8 scell_bitmap
;
3882 guint32 curr_offset
= offset
;
3883 guint32 computed_header_offset
;
3885 if (pdu_lengths
[n
] == -1) {
3886 /* Control Element size is the remaining PDU */
3887 pdu_lengths
[n
] = (gint16
)tvb_length_remaining(tvb
, curr_offset
);
3890 /* Create EPHR root */
3891 ephr_ti
= proto_tree_add_string_format(tree
,
3892 hf_mac_lte_control_ext_power_headroom
,
3893 tvb
, curr_offset
, pdu_lengths
[n
],
3895 "Extended Power Headroom");
3896 ephr_tree
= proto_item_add_subtree(ephr_ti
, ett_mac_lte_extended_power_headroom
);
3898 scell_bitmap
= tvb_get_guint8(tvb
, curr_offset
);
3899 proto_tree_add_item(ephr_tree
, hf_mac_lte_control_ext_power_headroom_c7
,
3900 tvb
, curr_offset
, 1, ENC_BIG_ENDIAN
);
3901 proto_tree_add_item(ephr_tree
, hf_mac_lte_control_ext_power_headroom_c6
,
3902 tvb
, curr_offset
, 1, ENC_BIG_ENDIAN
);
3903 proto_tree_add_item(ephr_tree
, hf_mac_lte_control_ext_power_headroom_c5
,
3904 tvb
, curr_offset
, 1, ENC_BIG_ENDIAN
);
3905 proto_tree_add_item(ephr_tree
, hf_mac_lte_control_ext_power_headroom_c4
,
3906 tvb
, curr_offset
, 1, ENC_BIG_ENDIAN
);
3907 proto_tree_add_item(ephr_tree
, hf_mac_lte_control_ext_power_headroom_c3
,
3908 tvb
, curr_offset
, 1, ENC_BIG_ENDIAN
);
3909 proto_tree_add_item(ephr_tree
, hf_mac_lte_control_ext_power_headroom_c2
,
3910 tvb
, curr_offset
, 1, ENC_BIG_ENDIAN
);
3911 proto_tree_add_item(ephr_tree
, hf_mac_lte_control_ext_power_headroom_c1
,
3912 tvb
, curr_offset
, 1, ENC_BIG_ENDIAN
);
3913 /* Check Reserved bit */
3914 ti
= proto_tree_add_item(ephr_tree
, hf_mac_lte_control_ext_power_headroom_reserved
,
3915 tvb
, curr_offset
, 1, ENC_BIG_ENDIAN
);
3916 if (scell_bitmap
& 0x01) {
3917 expert_add_info_format(pinfo
, ti
, &ei_mac_lte_reserved_not_zero
,
3918 "Extended Power Headroom Reserved bit not zero");
3922 /* Compute expected header size to deduce if PH Type 2 report is present or not */
3923 /* First count the number of SCells */
3924 for (i
= 0, scell_count
= 0; i
< 7; i
++) {
3925 if (scell_bitmap
& (0x80>>i
)) {
3929 /* Now quickly parse the header */
3930 computed_header_offset
= curr_offset
;
3931 for (i
= 0; i
< scell_count
; i
++) {
3932 if (tvb_get_guint8(tvb
, computed_header_offset
) & 0x80) {
3933 computed_header_offset
++;
3935 computed_header_offset
++;
3938 if ((gint16
)(computed_header_offset
+ 1 - curr_offset
) != pdu_lengths
[n
]) {
3939 /* PH Type 2 is present */
3940 if (tvb_get_guint8(tvb
, computed_header_offset
) & 0x80) {
3941 computed_header_offset
++;
3943 computed_header_offset
++;
3944 if ((gint16
)(computed_header_offset
+ 1 - curr_offset
) != pdu_lengths
[n
]) {
3945 expert_add_info_format(pinfo
, ephr_ti
, &ei_mac_lte_control_element_size_invalid
,
3946 "Control Element has an unexpected size (computed=%d, actual=%d)",
3947 computed_header_offset
+ 1 - curr_offset
, pdu_lengths
[n
]);
3948 offset
+= pdu_lengths
[n
];
3951 byte
= tvb_get_guint8(tvb
, curr_offset
);
3952 ephr_cell_ti
= proto_tree_add_text(ephr_tree
, tvb
, curr_offset
, ((byte
&0x80)?2:1), "PCell");
3953 ephr_cell_tree
= proto_item_add_subtree(ephr_cell_ti
, ett_mac_lte_extended_power_headroom_cell
);
3954 proto_tree_add_item(ephr_cell_tree
, hf_mac_lte_control_ext_power_headroom_power_backoff
,
3955 tvb
, curr_offset
, 1, ENC_BIG_ENDIAN
);
3956 proto_tree_add_item(ephr_cell_tree
, hf_mac_lte_control_ext_power_headroom_value
,
3957 tvb
, curr_offset
, 1, ENC_BIG_ENDIAN
);
3958 proto_tree_add_item(ephr_cell_tree
, hf_mac_lte_control_ext_power_headroom_level
,
3959 tvb
, curr_offset
, 1, ENC_BIG_ENDIAN
);
3960 proto_item_append_text(ephr_cell_ti
, " (%s)",
3961 val_to_str_ext_const((byte
&0x3f), &power_headroom_vals_ext
, "Unknown"));
3964 /* Pcmax,c field is present */
3965 byte
= tvb_get_guint8(tvb
, curr_offset
);
3966 /* Check 2 Reserved bits */
3967 ti
= proto_tree_add_item(ephr_cell_tree
, hf_mac_lte_control_ext_power_headroom_reserved2
,
3968 tvb
, curr_offset
, 1, ENC_BIG_ENDIAN
);
3970 expert_add_info_format(pinfo
, ti
, &ei_mac_lte_reserved_not_zero
,
3971 "Extended Power Headroom Reserved bits not zero (found 0x%x)",
3972 (byte
& 0xc0) >> 6);
3974 proto_tree_add_item(ephr_cell_tree
, hf_mac_lte_control_ext_power_headroom_pcmaxc
,
3975 tvb
, curr_offset
, 1, ENC_BIG_ENDIAN
);
3976 proto_item_append_text(ephr_cell_ti
, " (%s)",
3977 val_to_str_ext_const((byte
&0x3f), &pcmaxc_vals_ext
, "Unknown"));
3981 if ((gint16
)(computed_header_offset
+ 1 - curr_offset
) != pdu_lengths
[n
]) {
3982 expert_add_info_format(pinfo
, ephr_ti
, &ei_mac_lte_control_element_size_invalid
,
3983 "Control Element has an unexpected size (computed=%d, actual=%d)",
3984 computed_header_offset
+ 1 - curr_offset
, pdu_lengths
[n
]);
3985 offset
+= pdu_lengths
[n
];
3989 for (i
= 1, scell_bitmap
>>=1; i
<= 7; i
++, scell_bitmap
>>=1) {
3990 if (scell_bitmap
& 0x01) {
3991 byte
= tvb_get_guint8(tvb
, curr_offset
);
3992 ephr_cell_ti
= proto_tree_add_text(ephr_tree
, tvb
, curr_offset
, ((byte
&0x80)?2:1), "SCell Index %u", i
);
3993 ephr_cell_tree
= proto_item_add_subtree(ephr_cell_ti
, ett_mac_lte_extended_power_headroom_cell
);
3994 proto_tree_add_item(ephr_cell_tree
, hf_mac_lte_control_ext_power_headroom_power_backoff
,
3995 tvb
, curr_offset
, 1, ENC_BIG_ENDIAN
);
3996 proto_tree_add_item(ephr_cell_tree
, hf_mac_lte_control_ext_power_headroom_value
,
3997 tvb
, curr_offset
, 1, ENC_BIG_ENDIAN
);
3998 proto_tree_add_item(ephr_cell_tree
, hf_mac_lte_control_ext_power_headroom_level
,
3999 tvb
, curr_offset
, 1, ENC_BIG_ENDIAN
);
4000 proto_item_append_text(ephr_cell_ti
, " (%s)",
4001 val_to_str_ext_const((byte
&0x3f), &power_headroom_vals_ext
, "Unknown"));
4004 /* Pcmax,c field is present */
4005 byte
= tvb_get_guint8(tvb
, curr_offset
);
4006 /* Check 2 Reserved bits */
4007 ti
= proto_tree_add_item(ephr_cell_tree
, hf_mac_lte_control_ext_power_headroom_reserved2
,
4008 tvb
, curr_offset
, 1, ENC_BIG_ENDIAN
);
4010 expert_add_info_format(pinfo
, ti
, &ei_mac_lte_reserved_not_zero
,
4011 "Extended Power Headroom Reserved bits not zero (found 0x%x)",
4012 (byte
& 0xc0) >> 6);
4014 proto_tree_add_item(ephr_cell_tree
, hf_mac_lte_control_ext_power_headroom_pcmaxc
,
4015 tvb
, curr_offset
, 1, ENC_BIG_ENDIAN
);
4016 proto_item_append_text(ephr_cell_ti
, " (%s)",
4017 val_to_str_ext_const((byte
&0x3f), &pcmaxc_vals_ext
, "Unknown"));
4022 offset
+= pdu_lengths
[n
];
4025 case POWER_HEADROOM_REPORT_LCID
:
4028 proto_tree
*phr_tree
;
4033 /* Create PHR root */
4034 phr_ti
= proto_tree_add_string_format(tree
,
4035 hf_mac_lte_control_power_headroom
,
4039 phr_tree
= proto_item_add_subtree(phr_ti
, ett_mac_lte_power_headroom
);
4041 /* Check 2 Reserved bits */
4042 reserved
= (tvb_get_guint8(tvb
, offset
) & 0xc0) >> 6;
4043 ti
= proto_tree_add_item(phr_tree
, hf_mac_lte_control_power_headroom_reserved
,
4044 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
4045 if (reserved
!= 0) {
4046 expert_add_info_format(pinfo
, ti
, &ei_mac_lte_reserved_not_zero
,
4047 "Power Headroom Reserved bits not zero (found 0x%x)", reserved
);
4051 level
= tvb_get_guint8(tvb
, offset
) & 0x3f;
4052 proto_tree_add_item(phr_tree
, hf_mac_lte_control_power_headroom_level
,
4053 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
4055 /* Show value in root label */
4056 proto_item_append_text(phr_ti
, " (%s)",
4057 val_to_str_ext_const(level
, &power_headroom_vals_ext
, "Unknown"));
4064 proto_tree_add_item(tree
, hf_mac_lte_control_crnti
,
4065 tvb
, offset
, 2, ENC_BIG_ENDIAN
);
4068 case TRUNCATED_BSR_LCID
:
4069 case SHORT_BSR_LCID
:
4071 proto_tree
*bsr_tree
;
4073 proto_item
*buffer_size_ti
;
4077 value_string_ext
*p_vs_ext
;
4079 if (p_mac_lte_info
->isExtendedBSRSizes
) {
4080 hfindex
= hf_mac_lte_control_short_ext_bsr_buffer_size
;
4081 p_vs_ext
= &ext_buffer_size_vals_ext
;
4083 hfindex
= hf_mac_lte_control_short_bsr_buffer_size
;
4084 p_vs_ext
= &buffer_size_vals_ext
;
4087 bsr_ti
= proto_tree_add_string_format(tree
,
4088 hf_mac_lte_control_bsr
,
4092 bsr_tree
= proto_item_add_subtree(bsr_ti
, ett_mac_lte_bsr
);
4095 lcgid
= (tvb_get_guint8(tvb
, offset
) & 0xc0) >> 6;
4096 proto_tree_add_item(bsr_tree
, hf_mac_lte_control_bsr_lcg_id
,
4097 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
4099 buffer_size
= tvb_get_guint8(tvb
, offset
) & 0x3f;
4100 buffer_size_ti
= proto_tree_add_item(bsr_tree
, hfindex
,
4101 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
4103 if (buffer_size
>= global_mac_lte_bsr_warn_threshold
) {
4104 expert_add_info_format(pinfo
, buffer_size_ti
, &ei_mac_lte_bsr_warn_threshold_exceeded
,
4105 "UE %u - BSR for LCG %u exceeds threshold: %u (%s)",
4106 p_mac_lte_info
->ueid
,
4109 val_to_str_ext_const(buffer_size
, p_vs_ext
, "Unknown"));
4113 proto_item_append_text(bsr_ti
, " (lcgid=%u %s)",
4115 val_to_str_ext_const(buffer_size
, &buffer_size_vals_ext
, "Unknown"));
4120 proto_tree
*bsr_tree
;
4122 proto_item
*buffer_size_ti
;
4123 guint8 buffer_size
[4];
4125 value_string_ext
*p_vs_ext
;
4127 if (p_mac_lte_info
->isExtendedBSRSizes
) {
4128 hfindex
[0] = hf_mac_lte_control_long_ext_bsr_buffer_size_0
;
4129 hfindex
[1] = hf_mac_lte_control_long_ext_bsr_buffer_size_1
;
4130 hfindex
[2] = hf_mac_lte_control_long_ext_bsr_buffer_size_2
;
4131 hfindex
[3] = hf_mac_lte_control_long_ext_bsr_buffer_size_3
;
4132 p_vs_ext
= &ext_buffer_size_vals_ext
;
4134 hfindex
[0] = hf_mac_lte_control_long_bsr_buffer_size_0
;
4135 hfindex
[1] = hf_mac_lte_control_long_bsr_buffer_size_1
;
4136 hfindex
[2] = hf_mac_lte_control_long_bsr_buffer_size_2
;
4137 hfindex
[3] = hf_mac_lte_control_long_bsr_buffer_size_3
;
4138 p_vs_ext
= &buffer_size_vals_ext
;
4141 bsr_ti
= proto_tree_add_string_format(tree
,
4142 hf_mac_lte_control_bsr
,
4146 bsr_tree
= proto_item_add_subtree(bsr_ti
, ett_mac_lte_bsr
);
4149 buffer_size_ti
= proto_tree_add_item(bsr_tree
, hfindex
[0],
4150 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
4151 buffer_size
[0] = (tvb_get_guint8(tvb
, offset
) & 0xfc) >> 2;
4152 if (buffer_size
[0] >= global_mac_lte_bsr_warn_threshold
) {
4153 expert_add_info_format(pinfo
, buffer_size_ti
, &ei_mac_lte_bsr_warn_threshold_exceeded
,
4154 "UE %u - BSR for LCG 0 exceeds threshold: %u (%s)",
4155 p_mac_lte_info
->ueid
,
4157 val_to_str_ext_const(buffer_size
[0], p_vs_ext
, "Unknown"));
4161 buffer_size_ti
= proto_tree_add_item(bsr_tree
, hfindex
[1],
4162 tvb
, offset
, 2, ENC_BIG_ENDIAN
);
4163 buffer_size
[1] = ((tvb_get_guint8(tvb
, offset
) & 0x03) << 4) | ((tvb_get_guint8(tvb
, offset
+1) & 0xf0) >> 4);
4165 if (buffer_size
[1] >= global_mac_lte_bsr_warn_threshold
) {
4166 expert_add_info_format(pinfo
, buffer_size_ti
, &ei_mac_lte_bsr_warn_threshold_exceeded
,
4167 "UE %u - BSR for LCG 1 exceeds threshold: %u (%s)",
4168 p_mac_lte_info
->ueid
,
4170 val_to_str_ext_const(buffer_size
[1], p_vs_ext
, "Unknown"));
4174 buffer_size_ti
= proto_tree_add_item(bsr_tree
, hfindex
[2],
4175 tvb
, offset
, 2, ENC_BIG_ENDIAN
);
4177 buffer_size
[2] = ((tvb_get_guint8(tvb
, offset
) & 0x0f) << 2) | ((tvb_get_guint8(tvb
, offset
+1) & 0xc0) >> 6);
4179 if (buffer_size
[2] >= global_mac_lte_bsr_warn_threshold
) {
4180 expert_add_info_format(pinfo
, buffer_size_ti
, &ei_mac_lte_bsr_warn_threshold_exceeded
,
4181 "UE %u - BSR for LCG 2 exceeds threshold: %u (%s)",
4182 p_mac_lte_info
->ueid
,
4184 val_to_str_ext_const(buffer_size
[2], p_vs_ext
, "Unknown"));
4188 buffer_size_ti
= proto_tree_add_item(bsr_tree
, hfindex
[3],
4189 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
4190 buffer_size
[3] = tvb_get_guint8(tvb
, offset
) & 0x3f;
4192 if (buffer_size
[3] >= global_mac_lte_bsr_warn_threshold
) {
4193 expert_add_info_format(pinfo
, buffer_size_ti
, &ei_mac_lte_bsr_warn_threshold_exceeded
,
4194 "UE %u - BSR for LCG 3 exceeds threshold: %u (%s)",
4195 p_mac_lte_info
->ueid
,
4197 val_to_str_ext_const(buffer_size
[3], p_vs_ext
, "Unknown"));
4200 /* Append summary to parent */
4201 proto_item_append_text(bsr_ti
, " 0:(%s) 1:(%s) 2:(%s) 3:(%s)",
4202 val_to_str_ext_const(buffer_size
[0], p_vs_ext
, "Unknown"),
4203 val_to_str_ext_const(buffer_size
[1], p_vs_ext
, "Unknown"),
4204 val_to_str_ext_const(buffer_size
[2], p_vs_ext
, "Unknown"),
4205 val_to_str_ext_const(buffer_size
[3], p_vs_ext
, "Unknown"));
4209 /* No payload, in this position */
4210 tap_info
->padding_bytes
++;
4219 /* There might not be any data, if only headers (plus control data) were logged */
4220 is_truncated
= ((tvb_length_remaining(tvb
, offset
) == 0) && expecting_body_data
);
4221 truncated_ti
= proto_tree_add_uint(tree
, hf_mac_lte_sch_header_only
, tvb
, 0, 0,
4224 PROTO_ITEM_SET_GENERATED(truncated_ti
);
4225 expert_add_info(pinfo
, truncated_ti
, &ei_mac_lte_sch_header_only
);
4229 PROTO_ITEM_SET_HIDDEN(truncated_ti
);
4233 /* Now process remaining bodies, which should all be data */
4234 for (; n
< number_of_headers
; n
++) {
4236 /* Data SDUs treated identically for Uplink or downlink channels */
4238 const guint8
*pdu_data
;
4239 volatile guint16 data_length
;
4242 gboolean rlc_called_for_sdu
= FALSE
;
4244 /* Break out if meet padding */
4245 if (lcids
[n
] == PADDING_LCID
) {
4249 /* Work out length */
4250 data_length
= (pdu_lengths
[n
] == -1) ?
4251 tvb_length_remaining(tvb
, offset
) :
4254 /* Dissect SDU as raw bytes */
4255 sdu_ti
= proto_tree_add_bytes_format(tree
, hf_mac_lte_sch_sdu
, tvb
, offset
, pdu_lengths
[n
],
4256 NULL
, "SDU (%s, length=%u bytes): ",
4257 val_to_str_const(lcids
[n
],
4258 (direction
== DIRECTION_UPLINK
) ?
4264 /* Look for Msg3 data so that it may be compared with later
4265 Contention Resolution body */
4266 if ((lcids
[n
] == 0) && (direction
== DIRECTION_UPLINK
) && (data_length
== 6)) {
4267 if (!pinfo
->fd
->flags
.visited
) {
4268 guint key
= p_mac_lte_info
->rnti
;
4269 Msg3Data
*data
= (Msg3Data
*)g_hash_table_lookup(mac_lte_msg3_hash
, GUINT_TO_POINTER(key
));
4271 /* Look for previous entry for this UE */
4273 /* Allocate space for data and add to table */
4274 data
= wmem_new(wmem_file_scope(), Msg3Data
);
4275 g_hash_table_insert(mac_lte_msg3_hash
, GUINT_TO_POINTER(key
), data
);
4278 /* Fill in data details */
4279 data
->framenum
= pinfo
->fd
->num
;
4280 tvb_memcpy(tvb
, data
->data
, offset
, data_length
);
4281 data
->msg3Time
= pinfo
->fd
->abs_ts
;
4285 /* CCCH frames can be dissected directly by LTE RRC... */
4286 if ((lcids
[n
] == 0) && global_mac_lte_attempt_rrc_decode
) {
4287 tvbuff_t
*rrc_tvb
= tvb_new_subset(tvb
, offset
, data_length
, data_length
);
4289 /* Get appropriate dissector handle */
4290 volatile dissector_handle_t protocol_handle
= 0;
4291 if (p_mac_lte_info
->direction
== DIRECTION_UPLINK
) {
4292 protocol_handle
= find_dissector("lte_rrc.ul_ccch");
4295 protocol_handle
= find_dissector("lte_rrc.dl_ccch");
4298 /* Hide raw view of bytes */
4299 PROTO_ITEM_SET_HIDDEN(sdu_ti
);
4300 rlc_called_for_sdu
= TRUE
;
4302 call_with_catch_all(protocol_handle
, rrc_tvb
, pinfo
, tree
);
4305 /* LCID 1 and 2 can be assumed to be srb1&2, so can dissect as RLC AM */
4306 else if ((lcids
[n
] == 1) || (lcids
[n
] == 2)) {
4307 if (global_mac_lte_attempt_srb_decode
) {
4308 /* Call RLC dissector */
4309 call_rlc_dissector(tvb
, pinfo
, tree
, pdu_ti
, offset
, data_length
,
4310 RLC_AM_MODE
, direction
, p_mac_lte_info
->ueid
,
4311 CHANNEL_TYPE_SRB
, lcids
[n
], 0,
4312 get_mac_lte_channel_priority(p_mac_lte_info
->ueid
,
4313 lcids
[n
], direction
));
4315 /* Hide raw view of bytes */
4316 PROTO_ITEM_SET_HIDDEN(sdu_ti
);
4317 rlc_called_for_sdu
= TRUE
;
4321 else if ((lcids
[n
] >= 2) && (lcids
[n
] <= 10)) {
4323 /* Look for mapping for this LCID to drb channel set by UAT table */
4324 rlc_channel_type_t rlc_channel_type
;
4325 guint8 UM_seqnum_length
;
4327 guint8 priority
= get_mac_lte_channel_priority(p_mac_lte_info
->ueid
,
4328 lcids
[n
], direction
);
4330 lookup_rlc_channel_from_lcid(p_mac_lte_info
->ueid
,
4336 /* Dissect according to channel type */
4337 switch (rlc_channel_type
) {
4339 call_rlc_dissector(tvb
, pinfo
, tree
, pdu_ti
, offset
, data_length
,
4340 RLC_UM_MODE
, direction
, p_mac_lte_info
->ueid
,
4341 CHANNEL_TYPE_DRB
, (guint16
)drb_id
, UM_seqnum_length
,
4345 call_rlc_dissector(tvb
, pinfo
, tree
, pdu_ti
, offset
, data_length
,
4346 RLC_UM_MODE
, direction
, p_mac_lte_info
->ueid
,
4347 CHANNEL_TYPE_DRB
, (guint16
)drb_id
, UM_seqnum_length
,
4351 call_rlc_dissector(tvb
, pinfo
, tree
, pdu_ti
, offset
, data_length
,
4352 RLC_AM_MODE
, direction
, p_mac_lte_info
->ueid
,
4353 CHANNEL_TYPE_DRB
, (guint16
)drb_id
, 0,
4357 call_rlc_dissector(tvb
, pinfo
, tree
, pdu_ti
, offset
, data_length
,
4358 RLC_TM_MODE
, direction
, p_mac_lte_info
->ueid
,
4359 CHANNEL_TYPE_DRB
, (guint16
)drb_id
, 0,
4363 /* Nothing to do! */
4367 if (rlc_channel_type
!= rlcRaw
) {
4368 /* Hide raw view of bytes */
4369 PROTO_ITEM_SET_HIDDEN(sdu_ti
);
4370 rlc_called_for_sdu
= TRUE
;
4375 /* Show bytes too, if won't be hidden (slow). There must be a nicer way of doing this! */
4376 if (!rlc_called_for_sdu
) {
4377 pdu_data
= tvb_get_ptr(tvb
, offset
, pdu_lengths
[n
]);
4378 for (i
=0; i
< data_length
; i
++) {
4379 g_snprintf(buff
+(i
*2), 3, "%02x", pdu_data
[i
]);
4381 g_snprintf(buff
+(i
*2), 4, "...");
4385 proto_item_append_text(sdu_ti
, "%s", buff
);
4388 offset
+= data_length
;
4390 /* Update tap byte count for this channel */
4391 tap_info
->bytes_for_lcid
[lcids
[n
]] += data_length
;
4395 /* Now padding, if present, extends to the end of the PDU */
4396 if (lcids
[number_of_headers
-1] == PADDING_LCID
) {
4397 if (tvb_length_remaining(tvb
, offset
) > 0) {
4398 proto_tree_add_item(tree
, hf_mac_lte_padding_data
,
4399 tvb
, offset
, -1, ENC_NA
);
4401 padding_length_ti
= proto_tree_add_int(tree
, hf_mac_lte_padding_length
,
4403 p_mac_lte_info
->length
- offset
);
4404 PROTO_ITEM_SET_GENERATED(padding_length_ti
);
4406 /* Update padding bytes in stats */
4407 tap_info
->padding_bytes
+= (p_mac_lte_info
->length
- offset
);
4409 /* Make sure the PDU isn't bigger than reported! */
4410 if (offset
> p_mac_lte_info
->length
) {
4411 expert_add_info_format(pinfo
, padding_length_ti
, &ei_mac_lte_context_length
,
4412 "%s MAC PDU is longer than reported length (reported=%u, actual=%u)",
4413 (direction
== DIRECTION_UPLINK
) ? "UL-SCH" : "DL-SCH",
4414 p_mac_lte_info
->length
, offset
);
4418 /* There is no padding at the end of the frame */
4419 if (!is_truncated
&& (offset
< p_mac_lte_info
->length
)) {
4420 /* There is a problem if we haven't used all of the PDU */
4421 expert_add_info_format(pinfo
, pdu_ti
, &ei_mac_lte_context_length
,
4422 "%s PDU for UE %u is shorter than reported length (reported=%u, actual=%u)",
4423 (direction
== DIRECTION_UPLINK
) ? "UL-SCH" : "DL-SCH",
4424 p_mac_lte_info
->ueid
, p_mac_lte_info
->length
, offset
);
4427 if (!is_truncated
&& (offset
> p_mac_lte_info
->length
)) {
4428 /* There is a problem if the PDU is longer than rpeported */
4429 expert_add_info_format(pinfo
, pdu_ti
, &ei_mac_lte_context_length
,
4430 "%s PDU for UE %u is longer than reported length (reported=%u, actual=%u)",
4431 (direction
== DIRECTION_UPLINK
) ? "UL-SCH" : "DL-SCH",
4432 p_mac_lte_info
->ueid
, p_mac_lte_info
->length
, offset
);
4436 /* Can now store updated DRX info and show its info in the tree */
4437 if (global_mac_lte_show_drx
) {
4438 if (!pinfo
->fd
->flags
.visited
) {
4439 /* Store 'after' snapshot of UE state for this frame */
4440 set_drx_info(pinfo
, p_mac_lte_info
, FALSE
);
4443 /* Show current DRX state in tree as 'after' */
4444 show_drx_info(pinfo
, tree
, tvb
, p_mac_lte_info
, FALSE
);
4448 static void dissect_mch(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, proto_item
*pdu_ti
,
4449 volatile guint32 offset
, mac_lte_info
*p_mac_lte_info
)
4453 proto_item
*truncated_ti
;
4454 proto_item
*padding_length_ti
;
4455 proto_item
*hidden_root_ti
;
4457 /* Keep track of LCIDs and lengths as we dissect the header */
4458 volatile guint16 number_of_headers
= 0;
4459 guint8 lcids
[MAX_HEADERS_IN_PDU
];
4460 gint16 pdu_lengths
[MAX_HEADERS_IN_PDU
];
4462 proto_item
*pdu_header_ti
, *sched_info_ti
= NULL
;
4463 proto_tree
*pdu_header_tree
;
4465 gboolean have_seen_data_header
= FALSE
;
4466 guint8 number_of_padding_subheaders
= 0;
4467 gboolean have_seen_non_padding_control
= FALSE
;
4468 gboolean expecting_body_data
= FALSE
;
4469 volatile guint32 is_truncated
= FALSE
;
4471 write_pdu_label_and_info_literal(pdu_ti
, NULL
, pinfo
, "MCH: ");
4473 /* Add hidden item to filter on */
4474 hidden_root_ti
= proto_tree_add_string_format(tree
, hf_mac_lte_mch
, tvb
,
4475 offset
, 0, "", "Hidden header");
4476 PROTO_ITEM_SET_HIDDEN(hidden_root_ti
);
4478 /* Add PDU block header subtree */
4479 pdu_header_ti
= proto_tree_add_string_format(tree
, hf_mac_lte_mch_header
,
4483 pdu_header_tree
= proto_item_add_subtree(pdu_header_ti
, ett_mac_lte_mch_header
);
4486 /************************************************************************/
4487 /* Dissect each sub-header. */
4491 proto_item
*pdu_subheader_ti
;
4492 proto_tree
*pdu_subheader_tree
;
4493 proto_item
*lcid_ti
;
4495 gint offset_start_subheader
= offset
;
4496 guint8 first_byte
= tvb_get_guint8(tvb
, offset
);
4498 /* Add PDU block header subtree.
4499 Default with length of 1 byte. */
4500 pdu_subheader_ti
= proto_tree_add_string_format(pdu_header_tree
,
4501 hf_mac_lte_mch_subheader
,
4505 pdu_subheader_tree
= proto_item_add_subtree(pdu_subheader_ti
,
4506 ett_mac_lte_mch_subheader
);
4508 /* Check 1st 2 reserved bits */
4509 reserved
= (first_byte
& 0xc0) >> 6;
4510 ti
= proto_tree_add_item(pdu_subheader_tree
, hf_mac_lte_mch_reserved
,
4511 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
4512 if (reserved
!= 0) {
4513 expert_add_info_format(pinfo
, ti
, &ei_mac_lte_reserved_not_zero
,
4514 "MCH header Reserved bits not zero");
4518 extension
= (first_byte
& 0x20) >> 5;
4519 proto_tree_add_item(pdu_subheader_tree
, hf_mac_lte_mch_extended
,
4520 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
4523 lcids
[number_of_headers
] = first_byte
& 0x1f;
4524 lcid_ti
= proto_tree_add_item(pdu_subheader_tree
, hf_mac_lte_mch_lcid
,
4525 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
4526 if (lcids
[number_of_headers
] == MCH_SCHEDULING_INFO_LCID
) {
4527 sched_info_ti
= lcid_ti
;
4529 write_pdu_label_and_info(pdu_ti
, NULL
, pinfo
,
4531 val_to_str_const(lcids
[number_of_headers
],
4532 mch_lcid_vals
, "(Unknown LCID)"));
4535 /* Remember if we've seen a data subheader */
4536 if (lcids
[number_of_headers
] <= 28) {
4537 have_seen_data_header
= TRUE
;
4538 expecting_body_data
= TRUE
;
4541 /* Show an expert item if a contol subheader (except Padding) appears
4542 *after* a data PDU */
4543 if (have_seen_data_header
&&
4544 (lcids
[number_of_headers
] > 28) && (lcids
[number_of_headers
] != PADDING_LCID
)) {
4545 expert_add_info_format(pinfo
, lcid_ti
, &ei_mac_lte_control_subheader_after_data_subheader
,
4546 "MCH Control subheaders should not appear after data subheaders");
4550 /* Should not see padding after non-padding control... */
4551 if ((lcids
[number_of_headers
] > 28) &&
4552 (lcids
[number_of_headers
] == PADDING_LCID
) &&
4555 number_of_padding_subheaders
++;
4556 if (number_of_padding_subheaders
> 2) {
4557 expert_add_info(pinfo
, lcid_ti
, &ei_mac_lte_padding_data_multiple
);
4560 if (have_seen_non_padding_control
) {
4561 expert_add_info(pinfo
, lcid_ti
, &ei_mac_lte_padding_data_before_control_subheader
);
4565 /* Remember that we've seen non-padding control */
4566 if ((lcids
[number_of_headers
] > 28) &&
4567 (lcids
[number_of_headers
] != PADDING_LCID
)) {
4568 have_seen_non_padding_control
= TRUE
;
4573 /********************************************************************/
4574 /* Length field follows if not the last header or for a fixed-sized
4578 pdu_lengths
[number_of_headers
] = -1;
4581 /* Not the last one */
4582 if (lcids
[number_of_headers
] != PADDING_LCID
) {
4586 /* F(ormat) bit tells us how long the length field is */
4587 format
= (tvb_get_guint8(tvb
, offset
) & 0x80) >> 7;
4588 proto_tree_add_item(pdu_subheader_tree
, hf_mac_lte_mch_format
,
4589 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
4591 /* Now read length field itself */
4593 /* >= 128 - use 15 bits */
4594 proto_tree_add_bits_ret_val(pdu_subheader_tree
, hf_mac_lte_mch_length
,
4595 tvb
, offset
*8 + 1, 15, &length
, ENC_BIG_ENDIAN
);
4600 /* Less than 128 - only 7 bits */
4601 proto_tree_add_bits_ret_val(pdu_subheader_tree
, hf_mac_lte_mch_length
,
4602 tvb
, offset
*8 + 1, 7, &length
, ENC_BIG_ENDIAN
);
4605 pdu_lengths
[number_of_headers
] = (gint16
)length
;
4608 pdu_lengths
[number_of_headers
] = 0;
4613 /* Close off description in info column */
4614 switch (pdu_lengths
[number_of_headers
]) {
4616 write_pdu_label_and_info_literal(pdu_ti
, NULL
, pinfo
, ") ");
4619 write_pdu_label_and_info_literal(pdu_ti
, NULL
, pinfo
, ":remainder) ");
4622 write_pdu_label_and_info(pdu_ti
, NULL
, pinfo
, ":%u bytes) ",
4623 pdu_lengths
[number_of_headers
]);
4627 /* Append summary to subheader root */
4628 proto_item_append_text(pdu_subheader_ti
, " (lcid=%s",
4629 val_to_str_const(lcids
[number_of_headers
],
4630 mch_lcid_vals
, "Unknown"));
4632 switch (pdu_lengths
[number_of_headers
]) {
4634 proto_item_append_text(pdu_subheader_ti
, ", length is remainder)");
4635 proto_item_append_text(pdu_header_ti
, " (%s:remainder)",
4636 val_to_str_const(lcids
[number_of_headers
],
4641 proto_item_append_text(pdu_subheader_ti
, ")");
4642 proto_item_append_text(pdu_header_ti
, " (%s)",
4643 val_to_str_const(lcids
[number_of_headers
],
4648 proto_item_append_text(pdu_subheader_ti
, ", length=%u)",
4649 pdu_lengths
[number_of_headers
]);
4650 proto_item_append_text(pdu_header_ti
, " (%s:%u)",
4651 val_to_str_const(lcids
[number_of_headers
],
4654 pdu_lengths
[number_of_headers
]);
4659 /* Flag unknown lcid values in expert info */
4660 if (try_val_to_str(lcids
[number_of_headers
],mch_lcid_vals
) == NULL
) {
4661 expert_add_info_format(pinfo
, pdu_subheader_ti
, &ei_mac_lte_lcid_unexpected
,
4662 "MCH: Unexpected LCID received (%u)",
4663 lcids
[number_of_headers
]);
4666 /* Set length of this subheader */
4667 proto_item_set_len(pdu_subheader_ti
, offset
- offset_start_subheader
);
4669 number_of_headers
++;
4670 } while ((number_of_headers
< MAX_HEADERS_IN_PDU
) && extension
);
4672 /* Check that we didn't reach the end of the subheader array... */
4673 if (number_of_headers
>= MAX_HEADERS_IN_PDU
) {
4674 proto_tree_add_expert_format(tree
, pinfo
, &ei_mac_lte_too_many_subheaders
, tvb
, offset
, 1,
4675 "Reached %u subheaders - frame obviously malformed",
4676 MAX_HEADERS_IN_PDU
);
4681 /* Append summary to overall PDU header root */
4682 proto_item_append_text(pdu_header_ti
, " (%u subheaders)",
4685 /* And set its length to offset */
4686 proto_item_set_len(pdu_header_ti
, offset
);
4689 /************************************************************************/
4690 /* Dissect SDUs / control elements / padding. */
4691 /************************************************************************/
4693 /* Dissect control element bodies first */
4695 for (n
=0; n
< number_of_headers
; n
++) {
4696 /* Get out of loop once see any data SDU subheaders */
4697 if (lcids
[n
] <= 28) {
4701 /* Process what should be a valid control PDU type */
4703 case MCH_SCHEDULING_INFO_LCID
:
4705 guint32 curr_offset
= offset
;
4707 guint16 stop_mtch_val
;
4708 proto_item
*mch_sched_info_ti
, *ti
;
4709 proto_tree
*mch_sched_info_tree
;
4711 if (pdu_lengths
[n
] == -1) {
4712 /* Control Element size is the remaining PDU */
4713 pdu_lengths
[n
] = (gint16
)tvb_length_remaining(tvb
, curr_offset
);
4715 if (pdu_lengths
[n
] & 0x01) {
4716 expert_add_info_format(pinfo
, sched_info_ti
, &ei_mac_lte_context_length
,
4717 "MCH Scheduling Information MAC Control Element should have an even size");
4720 mch_sched_info_ti
= proto_tree_add_string_format(tree
,
4721 hf_mac_lte_control_mch_scheduling_info
,
4722 tvb
, curr_offset
, pdu_lengths
[n
],
4724 "MCH Scheduling Information");
4725 mch_sched_info_tree
= proto_item_add_subtree(mch_sched_info_ti
, ett_mac_lte_mch_scheduling_info
);
4727 for (i
=0; i
<(pdu_lengths
[n
]/2); i
++) {
4728 proto_tree_add_item(mch_sched_info_tree
, hf_mac_lte_control_mch_scheduling_info_lcid
,
4729 tvb
, curr_offset
, 1, ENC_BIG_ENDIAN
);
4730 stop_mtch_val
= tvb_get_ntohs(tvb
, curr_offset
) & 0x7ff;
4731 ti
= proto_tree_add_item(mch_sched_info_tree
, hf_mac_lte_control_mch_scheduling_info_stop_mtch
,
4732 tvb
, curr_offset
, 2, ENC_BIG_ENDIAN
);
4733 if ((stop_mtch_val
>= 2043) && (stop_mtch_val
<= 2046)) {
4734 proto_item_append_text(ti
, " (reserved)");
4736 else if (stop_mtch_val
== 2047) {
4737 proto_item_append_text(ti
, " (MTCH is not scheduled)");
4742 offset
+= pdu_lengths
[n
];
4746 /* No payload (in this position) */
4755 /* There might not be any data, if only headers (plus control data) were logged */
4756 is_truncated
= ((tvb_length_remaining(tvb
, offset
) == 0) && expecting_body_data
);
4757 truncated_ti
= proto_tree_add_uint(tree
, hf_mac_lte_mch_header_only
, tvb
, 0, 0,
4760 PROTO_ITEM_SET_GENERATED(truncated_ti
);
4761 expert_add_info(pinfo
, truncated_ti
, &ei_mac_lte_sch_header_only
);
4765 PROTO_ITEM_SET_HIDDEN(truncated_ti
);
4769 /* Now process remaining bodies, which should all be data */
4770 for (; n
< number_of_headers
; n
++) {
4773 const guint8
*pdu_data
;
4774 volatile guint16 data_length
;
4778 /* Break out if meet padding */
4779 if (lcids
[n
] == PADDING_LCID
) {
4783 /* Work out length */
4784 data_length
= (pdu_lengths
[n
] == -1) ?
4785 tvb_length_remaining(tvb
, offset
) :
4788 if ((lcids
[n
] == 0) && global_mac_lte_attempt_mcch_decode
) {
4789 /* Call RLC dissector */
4790 call_rlc_dissector(tvb
, pinfo
, tree
, pdu_ti
, offset
, data_length
,
4791 RLC_UM_MODE
, DIRECTION_DOWNLINK
, 0,
4792 CHANNEL_TYPE_MCCH
, 0, 5, 0);
4793 } else if ((lcids
[n
] <= 28) && global_mac_lte_call_rlc_for_mtch
) {
4794 /* Call RLC dissector */
4795 call_rlc_dissector(tvb
, pinfo
, tree
, pdu_ti
, offset
, data_length
,
4796 RLC_UM_MODE
, DIRECTION_DOWNLINK
, 0,
4797 CHANNEL_TYPE_MTCH
, 0, 5, 0);
4799 /* Dissect SDU as raw bytes */
4800 sdu_ti
= proto_tree_add_bytes_format(tree
, hf_mac_lte_mch_sdu
, tvb
, offset
, pdu_lengths
[n
],
4801 NULL
, "SDU (%s, length=%u bytes): ",
4802 val_to_str_const(lcids
[n
], mch_lcid_vals
, "Unknown"),
4805 /* Show bytes too. There must be a nicer way of doing this! */
4806 pdu_data
= tvb_get_ptr(tvb
, offset
, pdu_lengths
[n
]);
4807 for (i
=0; i
< data_length
; i
++) {
4808 g_snprintf(buff
+(i
*2), 3, "%02x", pdu_data
[i
]);
4810 g_snprintf(buff
+(i
*2), 4, "...");
4814 proto_item_append_text(sdu_ti
, "%s", buff
);
4817 offset
+= data_length
;
4820 /* Now padding, if present, extends to the end of the PDU */
4821 if (lcids
[number_of_headers
-1] == PADDING_LCID
) {
4822 if (tvb_length_remaining(tvb
, offset
) > 0) {
4823 proto_tree_add_item(tree
, hf_mac_lte_padding_data
,
4824 tvb
, offset
, -1, ENC_NA
);
4826 padding_length_ti
= proto_tree_add_int(tree
, hf_mac_lte_padding_length
,
4828 p_mac_lte_info
->length
- offset
);
4829 PROTO_ITEM_SET_GENERATED(padding_length_ti
);
4831 /* Make sure the PDU isn't bigger than reported! */
4832 if (offset
> p_mac_lte_info
->length
) {
4833 expert_add_info_format(pinfo
, padding_length_ti
, &ei_mac_lte_context_length
,
4834 "MAC PDU is longer than reported length (reported=%u, actual=%u)",
4835 p_mac_lte_info
->length
, offset
);
4839 /* There is no padding at the end of the frame */
4840 if (!is_truncated
&& (offset
< p_mac_lte_info
->length
)) {
4841 /* There is a problem if we haven't used all of the PDU */
4842 expert_add_info_format(pinfo
, pdu_ti
, &ei_mac_lte_context_length
,
4843 "PDU is shorter than reported length (reported=%u, actual=%u)",
4844 p_mac_lte_info
->length
, offset
);
4847 if (!is_truncated
&& (offset
> p_mac_lte_info
->length
)) {
4848 /* There is a problem if the PDU is longer than rpeported */
4849 expert_add_info_format(pinfo
, pdu_ti
, &ei_mac_lte_context_length
,
4850 "PDU is longer than reported length (reported=%u, actual=%u)",
4851 p_mac_lte_info
->length
, offset
);
4857 /*****************************/
4858 /* Main dissection function. */
4859 void dissect_mac_lte(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
4861 proto_tree
*mac_lte_tree
;
4863 proto_tree
*context_tree
;
4864 proto_item
*context_ti
;
4865 proto_item
*retx_ti
= NULL
;
4868 struct mac_lte_info
*p_mac_lte_info
;
4871 /* Allocate and zero tap struct */
4872 mac_lte_tap_info
*tap_info
= (mac_lte_tap_info
*)wmem_alloc0(wmem_packet_scope(), sizeof(mac_lte_tap_info
));
4874 /* Set protocol name */
4875 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "MAC-LTE");
4877 /* Create protocol tree. */
4878 pdu_ti
= proto_tree_add_item(tree
, proto_mac_lte
, tvb
, offset
, -1, ENC_NA
);
4879 proto_item_append_text(pdu_ti
, " ");
4880 mac_lte_tree
= proto_item_add_subtree(pdu_ti
, ett_mac_lte
);
4882 /* Look for packet info! */
4883 p_mac_lte_info
= (mac_lte_info
*)p_get_proto_data(pinfo
->fd
, proto_mac_lte
, 0);
4885 /* Can't dissect anything without it... */
4886 if (p_mac_lte_info
== NULL
) {
4888 proto_tree_add_text(mac_lte_tree
, tvb
, offset
, -1,
4889 "Can't dissect LTE MAC frame because no per-frame info was attached!");
4890 PROTO_ITEM_SET_GENERATED(tii
);
4894 /* Clear info column */
4895 col_clear(pinfo
->cinfo
, COL_INFO
);
4898 /*****************************************/
4899 /* Show context information */
4901 /* Create context root */
4902 context_ti
= proto_tree_add_string_format(mac_lte_tree
, hf_mac_lte_context
,
4903 tvb
, offset
, 0, "", "Context");
4904 context_tree
= proto_item_add_subtree(context_ti
, ett_mac_lte_context
);
4905 PROTO_ITEM_SET_GENERATED(context_ti
);
4907 ti
= proto_tree_add_uint(context_tree
, hf_mac_lte_context_radio_type
,
4908 tvb
, 0, 0, p_mac_lte_info
->radioType
);
4909 PROTO_ITEM_SET_GENERATED(ti
);
4911 ti
= proto_tree_add_uint(context_tree
, hf_mac_lte_context_direction
,
4912 tvb
, 0, 0, p_mac_lte_info
->direction
);
4913 PROTO_ITEM_SET_GENERATED(ti
);
4915 if (p_mac_lte_info
->ueid
!= 0) {
4916 ti
= proto_tree_add_uint(context_tree
, hf_mac_lte_context_ueid
,
4917 tvb
, 0, 0, p_mac_lte_info
->ueid
);
4918 PROTO_ITEM_SET_GENERATED(ti
);
4921 /* There are several out-of-band MAC events that may be indicated in the context info. */
4922 /* Handle them here */
4923 if (p_mac_lte_info
->length
== 0) {
4924 proto_item
*preamble_ti
;
4925 proto_tree
*preamble_tree
;
4927 switch (p_mac_lte_info
->oob_event
) {
4928 case ltemac_send_preamble
:
4929 preamble_ti
= proto_tree_add_item(mac_lte_tree
, hf_mac_lte_oob_send_preamble
,
4930 tvb
, 0, 0, ENC_ASCII
|ENC_NA
);
4931 preamble_tree
= proto_item_add_subtree(preamble_ti
, ett_mac_lte_oob
);
4932 PROTO_ITEM_SET_GENERATED(ti
);
4934 ti
= proto_tree_add_uint(preamble_tree
, hf_mac_lte_context_rapid
,
4935 tvb
, 0, 0, p_mac_lte_info
->rapid
);
4936 PROTO_ITEM_SET_GENERATED(ti
);
4938 ti
= proto_tree_add_uint(preamble_tree
, hf_mac_lte_context_rach_attempt_number
,
4939 tvb
, 0, 0, p_mac_lte_info
->rach_attempt_number
);
4940 PROTO_ITEM_SET_GENERATED(ti
);
4943 write_pdu_label_and_info(pdu_ti
, preamble_ti
, pinfo
,
4944 "RACH Preamble chosen for UE %u (RAPID=%u, attempt=%u)",
4945 p_mac_lte_info
->ueid
, p_mac_lte_info
->rapid
,
4946 p_mac_lte_info
->rach_attempt_number
);
4948 /* Add expert info (a note, unless attempt > 1) */
4949 expert_add_info_format(pinfo
, ti
,
4950 (p_mac_lte_info
->rach_attempt_number
> 1) ? &ei_mac_lte_rach_preamble_sent_warn
: &ei_mac_lte_rach_preamble_sent_note
,
4951 "RACH Preamble sent for UE %u (RAPID=%u, attempt=%u)",
4952 p_mac_lte_info
->ueid
, p_mac_lte_info
->rapid
,
4953 p_mac_lte_info
->rach_attempt_number
);
4955 case ltemac_send_sr
:
4957 ti
= proto_tree_add_uint(mac_lte_tree
, hf_mac_lte_number_of_srs
,
4958 tvb
, 0, 0, p_mac_lte_info
->number_of_srs
);
4959 PROTO_ITEM_SET_GENERATED(ti
);
4962 for (n
=0; n
< p_mac_lte_info
->number_of_srs
; n
++) {
4964 proto_tree
*sr_tree
;
4966 /* SR event is subtree */
4967 sr_ti
= proto_tree_add_expert_format(mac_lte_tree
, pinfo
, &ei_mac_lte_oob_send_sr
,
4969 "Scheduling Request sent for UE %u (RNTI %u)", p_mac_lte_info
->oob_ueid
[n
], p_mac_lte_info
->oob_rnti
[n
]);
4970 sr_tree
= proto_item_add_subtree(sr_ti
, ett_mac_lte_oob
);
4971 PROTO_ITEM_SET_GENERATED(sr_ti
);
4974 ti
= proto_tree_add_uint(sr_tree
, hf_mac_lte_context_rnti
,
4975 tvb
, 0, 0, p_mac_lte_info
->oob_rnti
[n
]);
4976 PROTO_ITEM_SET_GENERATED(ti
);
4979 ti
= proto_tree_add_uint(sr_tree
, hf_mac_lte_context_ueid
,
4980 tvb
, 0, 0, p_mac_lte_info
->oob_ueid
[n
]);
4981 PROTO_ITEM_SET_GENERATED(ti
);
4983 /* Add summary to root. */
4984 proto_item_append_text(sr_ti
, " (UE=%u C-RNTI=%u)",
4985 p_mac_lte_info
->oob_ueid
[n
],
4986 p_mac_lte_info
->oob_rnti
[n
]);
4990 write_pdu_label_and_info(pdu_ti
, NULL
, pinfo
,
4991 "Scheduling Requests (%u) sent: (UE=%u C-RNTI=%u)",
4992 p_mac_lte_info
->number_of_srs
,
4993 p_mac_lte_info
->oob_ueid
[n
],
4994 p_mac_lte_info
->oob_rnti
[n
]);
4997 write_pdu_label_and_info(pdu_ti
, NULL
, pinfo
,
4998 " (UE=%u C-RNTI=%u)",
4999 p_mac_lte_info
->oob_ueid
[n
],
5000 p_mac_lte_info
->oob_rnti
[n
]);
5003 /* Update SR status for this UE */
5004 if (global_mac_lte_track_sr
) {
5005 TrackSRInfo(SR_Request
, pinfo
, mac_lte_tree
, tvb
, p_mac_lte_info
, n
, sr_ti
);
5009 case ltemac_sr_failure
:
5010 ti
= proto_tree_add_uint(context_tree
, hf_mac_lte_context_rnti
,
5011 tvb
, 0, 0, p_mac_lte_info
->rnti
);
5012 PROTO_ITEM_SET_GENERATED(ti
);
5014 proto_tree_add_expert_format(mac_lte_tree
, pinfo
, &ei_mac_lte_oob_sr_failure
,
5015 tvb
, 0, 0, "Scheduling Request failed for UE %u (RNTI %u)",
5016 p_mac_lte_info
->ueid
, p_mac_lte_info
->rnti
);
5017 PROTO_ITEM_SET_GENERATED(ti
);
5020 write_pdu_label_and_info(pdu_ti
, NULL
, pinfo
,
5021 "Scheduling Request FAILED for UE %u (C-RNTI=%u)",
5022 p_mac_lte_info
->ueid
,
5023 p_mac_lte_info
->rnti
);
5025 /* Update SR status */
5026 if (global_mac_lte_track_sr
) {
5027 TrackSRInfo(SR_Failure
, pinfo
, mac_lte_tree
, tvb
, p_mac_lte_info
, 0, ti
);
5033 /* Our work here is done */
5037 /* Show remaining meta information */
5038 ti
= proto_tree_add_uint(context_tree
, hf_mac_lte_context_sysframe_number
,
5039 tvb
, 0, 0, p_mac_lte_info
->sysframeNumber
);
5040 PROTO_ITEM_SET_GENERATED(ti
);
5041 if (p_mac_lte_info
->sysframeNumber
> 1023) {
5042 expert_add_info_format(pinfo
, ti
, &ei_mac_lte_context_sysframe_number
,
5043 "Sysframe number (%u) out of range - valid range is 0-1023",
5044 p_mac_lte_info
->sysframeNumber
);
5047 ti
= proto_tree_add_uint(context_tree
, hf_mac_lte_context_subframe_number
,
5048 tvb
, 0, 0, p_mac_lte_info
->subframeNumber
);
5049 PROTO_ITEM_SET_GENERATED(ti
);
5050 if (p_mac_lte_info
->subframeNumber
> 9) {
5051 /* N.B. if we set it to valid value, it won't trigger when we rescan
5052 (at least with DCT2000 files where the context struct isn't re-read). */
5053 expert_add_info_format(pinfo
, ti
, &ei_mac_lte_context_sysframe_number
,
5054 "Subframe number (%u) out of range - valid range is 0-9",
5055 p_mac_lte_info
->subframeNumber
);
5058 if (p_mac_lte_info
->subframeNumberOfGrantPresent
) {
5059 ti
= proto_tree_add_uint(context_tree
, hf_mac_lte_context_grant_subframe_number
,
5060 tvb
, 0, 0, p_mac_lte_info
->subframeNumberOfGrant
);
5061 PROTO_ITEM_SET_GENERATED(ti
);
5064 if (p_mac_lte_info
->rntiType
!= NO_RNTI
) {
5065 ti
= proto_tree_add_uint(context_tree
, hf_mac_lte_context_rnti
,
5066 tvb
, 0, 0, p_mac_lte_info
->rnti
);
5067 PROTO_ITEM_SET_GENERATED(ti
);
5068 proto_item_append_text(context_ti
, " (RNTI=%u)", p_mac_lte_info
->rnti
);
5072 ti
= proto_tree_add_uint(context_tree
, hf_mac_lte_context_rnti_type
,
5073 tvb
, 0, 0, p_mac_lte_info
->rntiType
);
5074 PROTO_ITEM_SET_GENERATED(ti
);
5076 /* Check that RNTI value is consistent with given RNTI type */
5077 switch (p_mac_lte_info
->rntiType
) {
5079 if (p_mac_lte_info
->rnti
!= 0xFFFD) {
5080 expert_add_info_format(pinfo
, ti
, &ei_mac_lte_context_rnti_type
,
5081 "M-RNTI indicated, but value is %u (0x%x) (must be 0x%x)",
5082 p_mac_lte_info
->rnti
, p_mac_lte_info
->rnti
, 0xFFFD);
5087 if (p_mac_lte_info
->rnti
!= 0xFFFE) {
5088 expert_add_info_format(pinfo
, ti
, &ei_mac_lte_context_rnti_type
,
5089 "P-RNTI indicated, but value is %u (0x%x) (must be 0x%x)",
5090 p_mac_lte_info
->rnti
, p_mac_lte_info
->rnti
, 0xFFFE);
5095 if (p_mac_lte_info
->rnti
!= 0xFFFF) {
5096 expert_add_info_format(pinfo
, ti
, &ei_mac_lte_context_rnti_type
,
5097 "SI-RNTI indicated, but value is %u (0x%x) (must be 0x%x)",
5098 p_mac_lte_info
->rnti
, p_mac_lte_info
->rnti
, 0xFFFE);
5103 if ((p_mac_lte_info
->rnti
< 0x0001) || (p_mac_lte_info
->rnti
> 0x003C)) {
5104 expert_add_info_format(pinfo
, ti
, &ei_mac_lte_context_rnti_type
,
5105 "RA_RNTI indicated, but given value %u (0x%x)is out of range",
5106 p_mac_lte_info
->rnti
, p_mac_lte_info
->rnti
);
5112 if ((p_mac_lte_info
->rnti
< 0x0001) || (p_mac_lte_info
->rnti
> 0xFFF3)) {
5113 expert_add_info_format(pinfo
, ti
, &ei_mac_lte_context_rnti_type
,
5114 "%s indicated, but given value %u (0x%x)is out of range",
5115 val_to_str_const(p_mac_lte_info
->rntiType
, rnti_type_vals
, "Unknown"),
5116 p_mac_lte_info
->rnti
, p_mac_lte_info
->rnti
);
5125 ti
= proto_tree_add_uint(context_tree
, hf_mac_lte_context_predefined_frame
,
5126 tvb
, 0, 0, p_mac_lte_info
->isPredefinedData
);
5127 if (p_mac_lte_info
->isPredefinedData
) {
5128 PROTO_ITEM_SET_GENERATED(ti
);
5131 PROTO_ITEM_SET_HIDDEN(ti
);
5134 ti
= proto_tree_add_uint(context_tree
, hf_mac_lte_context_length
,
5135 tvb
, 0, 0, p_mac_lte_info
->length
);
5136 PROTO_ITEM_SET_GENERATED(ti
);
5137 /* Infer uplink grant size */
5138 if (p_mac_lte_info
->direction
== DIRECTION_UPLINK
) {
5139 ti
= proto_tree_add_uint(context_tree
, hf_mac_lte_context_ul_grant_size
,
5140 tvb
, 0, 0, p_mac_lte_info
->length
);
5141 PROTO_ITEM_SET_GENERATED(ti
);
5144 /* Retx count goes in top-level tree to make it more visible */
5145 if (p_mac_lte_info
->reTxCount
) {
5146 proto_item
*retx_reason_ti
;
5147 retx_ti
= proto_tree_add_uint(mac_lte_tree
, hf_mac_lte_context_retx_count
,
5148 tvb
, 0, 0, p_mac_lte_info
->reTxCount
);
5149 PROTO_ITEM_SET_GENERATED(retx_ti
);
5151 if (p_mac_lte_info
->reTxCount
>= global_mac_lte_retx_counter_trigger
) {
5152 expert_add_info_format(pinfo
, retx_ti
, &ei_mac_lte_ul_mac_frame_retx
,
5153 "UE %u: UL MAC frame ReTX no. %u",
5154 p_mac_lte_info
->ueid
, p_mac_lte_info
->reTxCount
);
5157 retx_reason_ti
= proto_tree_add_uint(mac_lte_tree
, hf_mac_lte_context_retx_reason
,
5158 tvb
, 0, 0, p_mac_lte_info
->isPHICHNACK
);
5159 PROTO_ITEM_SET_GENERATED(retx_reason_ti
);
5162 if (p_mac_lte_info
->crcStatusValid
) {
5164 ti
= proto_tree_add_uint(context_tree
, hf_mac_lte_context_crc_status
,
5165 tvb
, 0, 0, p_mac_lte_info
->detailed_phy_info
.dl_info
.crc_status
);
5166 PROTO_ITEM_SET_GENERATED(ti
);
5168 /* Report non-success */
5169 if (p_mac_lte_info
->detailed_phy_info
.dl_info
.crc_status
!= crc_success
) {
5170 expert_add_info_format(pinfo
, ti
, &ei_mac_lte_context_crc_status
,
5171 "%s Frame has CRC error problem (%s)",
5172 (p_mac_lte_info
->direction
== DIRECTION_UPLINK
) ? "UL" : "DL",
5173 val_to_str_const(p_mac_lte_info
->detailed_phy_info
.dl_info
.crc_status
,
5176 write_pdu_label_and_info(pdu_ti
, NULL
, pinfo
,
5177 "%s: <CRC %s> UEId=%u %s=%u ",
5178 (p_mac_lte_info
->direction
== DIRECTION_UPLINK
) ? "UL" : "DL",
5179 val_to_str_const(p_mac_lte_info
->detailed_phy_info
.dl_info
.crc_status
,
5182 p_mac_lte_info
->ueid
,
5183 val_to_str_const(p_mac_lte_info
->rntiType
, rnti_type_vals
,
5184 "Unknown RNTI type"),
5185 p_mac_lte_info
->rnti
);
5190 ti
= proto_tree_add_uint(context_tree
, hf_mac_lte_context_carrier_id
,
5191 tvb
, 0, 0, p_mac_lte_info
->carrierId
);
5192 PROTO_ITEM_SET_GENERATED(ti
);
5194 /* May also have extra Physical layer attributes set for this frame */
5195 show_extra_phy_parameters(pinfo
, tvb
, mac_lte_tree
, p_mac_lte_info
);
5197 /* Set context-info parts of tap struct */
5198 tap_info
->rnti
= p_mac_lte_info
->rnti
;
5199 tap_info
->ueid
= p_mac_lte_info
->ueid
;
5200 tap_info
->rntiType
= p_mac_lte_info
->rntiType
;
5201 tap_info
->isPredefinedData
= p_mac_lte_info
->isPredefinedData
;
5202 tap_info
->isPHYRetx
= (p_mac_lte_info
->reTxCount
>= 1);
5203 tap_info
->crcStatusValid
= p_mac_lte_info
->crcStatusValid
;
5204 tap_info
->crcStatus
= p_mac_lte_info
->detailed_phy_info
.dl_info
.crc_status
;
5205 tap_info
->direction
= p_mac_lte_info
->direction
;
5207 tap_info
->time
= pinfo
->fd
->abs_ts
;
5209 /* Also set total number of bytes (won't be used for UL/DL-SCH) */
5210 tap_info
->single_number_of_bytes
= tvb_length_remaining(tvb
, offset
);
5212 /* If we know its predefined data, don't try to decode any further */
5213 if (p_mac_lte_info
->isPredefinedData
) {
5214 proto_tree_add_item(mac_lte_tree
, hf_mac_lte_predefined_pdu
, tvb
, offset
, -1, ENC_NA
);
5215 write_pdu_label_and_info(pdu_ti
, NULL
, pinfo
,
5216 "Predefined data (%u bytes%s)",
5217 p_mac_lte_info
->length
,
5218 (p_mac_lte_info
->length
> tvb_length_remaining(tvb
, offset
) ?
5222 /* Queue tap info */
5223 if (!pinfo
->flags
.in_error_pkt
) {
5224 tap_queue_packet(mac_lte_tap
, pinfo
, tap_info
);
5230 /* IF CRC status failed, just do decode as raw bytes */
5231 if (!global_mac_lte_dissect_crc_failures
&&
5232 (p_mac_lte_info
->crcStatusValid
&&
5233 (p_mac_lte_info
->detailed_phy_info
.dl_info
.crc_status
!= crc_success
))) {
5235 proto_tree_add_item(mac_lte_tree
, hf_mac_lte_raw_pdu
, tvb
, offset
, -1, ENC_NA
);
5236 write_pdu_label_and_info(pdu_ti
, NULL
, pinfo
, "Raw data (%u bytes)", tvb_length_remaining(tvb
, offset
));
5239 TODO: unfortunately DL retx detection won't get done if we return here... */
5240 if (!pinfo
->flags
.in_error_pkt
) {
5241 tap_queue_packet(mac_lte_tap
, pinfo
, tap_info
);
5247 /* Reset this counter */
5248 s_number_of_rlc_pdus_shown
= 0;
5250 /* Dissect the MAC PDU itself. Format depends upon RNTI type. */
5251 switch (p_mac_lte_info
->rntiType
) {
5255 dissect_pch(tvb
, pinfo
, mac_lte_tree
, pdu_ti
, offset
, p_mac_lte_info
->direction
, tap_info
);
5260 dissect_rar(tvb
, pinfo
, mac_lte_tree
, pdu_ti
, offset
, p_mac_lte_info
, tap_info
);
5265 /* Can be UL-SCH or DL-SCH */
5266 dissect_ulsch_or_dlsch(tvb
, pinfo
, mac_lte_tree
, pdu_ti
, offset
,
5267 p_mac_lte_info
->direction
, p_mac_lte_info
, tap_info
,
5268 retx_ti
, context_tree
);
5272 /* BCH over DL-SCH */
5273 dissect_bch(tvb
, pinfo
, mac_lte_tree
, pdu_ti
, offset
, p_mac_lte_info
);
5278 dissect_mch(tvb
, pinfo
, mac_lte_tree
, pdu_ti
, offset
, p_mac_lte_info
);
5282 /* Must be BCH over BCH... */
5283 dissect_bch(tvb
, pinfo
, mac_lte_tree
, pdu_ti
, offset
, p_mac_lte_info
);
5291 /* Queue tap info */
5292 tap_queue_packet(mac_lte_tap
, pinfo
, tap_info
);
5298 /* Initializes the hash tables each time a new
5299 * file is loaded or re-loaded in wireshark */
5300 static void mac_lte_init_protocol(void)
5302 /* Destroy any existing tables. */
5303 if (mac_lte_msg3_hash
) {
5304 g_hash_table_destroy(mac_lte_msg3_hash
);
5306 if (mac_lte_cr_result_hash
) {
5307 g_hash_table_destroy(mac_lte_cr_result_hash
);
5310 if (mac_lte_dl_harq_hash
) {
5311 g_hash_table_destroy(mac_lte_dl_harq_hash
);
5313 if (mac_lte_dl_harq_result_hash
) {
5314 g_hash_table_destroy(mac_lte_dl_harq_result_hash
);
5316 if (mac_lte_ul_harq_hash
) {
5317 g_hash_table_destroy(mac_lte_ul_harq_hash
);
5319 if (mac_lte_ul_harq_result_hash
) {
5320 g_hash_table_destroy(mac_lte_ul_harq_result_hash
);
5322 if (mac_lte_ue_sr_state
) {
5323 g_hash_table_destroy(mac_lte_ue_sr_state
);
5325 if (mac_lte_sr_request_hash
) {
5326 g_hash_table_destroy(mac_lte_sr_request_hash
);
5328 if (mac_lte_tti_info_result_hash
) {
5329 g_hash_table_destroy(mac_lte_tti_info_result_hash
);
5331 if (mac_lte_ue_channels_hash
) {
5332 g_hash_table_destroy(mac_lte_ue_channels_hash
);
5334 if (mac_lte_drx_ue_state
) {
5335 g_hash_table_destroy(mac_lte_drx_ue_state
);
5337 if (mac_lte_drx_frame_result
) {
5338 g_hash_table_destroy(mac_lte_drx_frame_result
);
5343 memset(&UL_tti_info
, 0, sizeof(UL_tti_info
));
5344 UL_tti_info
.subframe
= 0xff; /* Invalid value */
5345 memset(&DL_tti_info
, 0, sizeof(DL_tti_info
));
5346 DL_tti_info
.subframe
= 0xff; /* Invalid value */
5348 /* Now create them over */
5349 mac_lte_msg3_hash
= g_hash_table_new(mac_lte_rnti_hash_func
, mac_lte_rnti_hash_equal
);
5350 mac_lte_cr_result_hash
= g_hash_table_new(mac_lte_framenum_hash_func
, mac_lte_framenum_hash_equal
);
5352 mac_lte_dl_harq_hash
= g_hash_table_new(mac_lte_rnti_hash_func
, mac_lte_rnti_hash_equal
);
5353 mac_lte_dl_harq_result_hash
= g_hash_table_new(mac_lte_framenum_hash_func
, mac_lte_framenum_hash_equal
);
5355 mac_lte_ul_harq_hash
= g_hash_table_new(mac_lte_rnti_hash_func
, mac_lte_rnti_hash_equal
);
5356 mac_lte_ul_harq_result_hash
= g_hash_table_new(mac_lte_framenum_hash_func
, mac_lte_framenum_hash_equal
);
5358 mac_lte_ue_sr_state
= g_hash_table_new(mac_lte_rnti_hash_func
, mac_lte_rnti_hash_equal
);
5359 mac_lte_sr_request_hash
= g_hash_table_new(mac_lte_framenum_hash_func
, mac_lte_framenum_hash_equal
);
5361 mac_lte_tti_info_result_hash
= g_hash_table_new(mac_lte_framenum_hash_func
, mac_lte_framenum_hash_equal
);
5363 mac_lte_ue_channels_hash
= g_hash_table_new(mac_lte_rnti_hash_func
, mac_lte_rnti_hash_equal
);
5365 mac_lte_drx_ue_state
= g_hash_table_new(mac_lte_rnti_hash_func
, mac_lte_rnti_hash_equal
);
5366 mac_lte_drx_frame_result
= g_hash_table_new(mac_lte_framenum_hash_func
, mac_lte_framenum_hash_equal
);
5369 /* Callback used as part of configuring a channel mapping using UAT */
5370 static void* lcid_drb_mapping_copy_cb(void* dest
, const void* orig
, size_t len _U_
)
5372 const lcid_drb_mapping_t
*o
= (const lcid_drb_mapping_t
*)orig
;
5373 lcid_drb_mapping_t
*d
= (lcid_drb_mapping_t
*)dest
;
5375 /* Copy all items over */
5377 d
->drbid
= o
->drbid
;
5378 d
->channel_type
= o
->channel_type
;
5384 /*************************************************************************/
5385 /* These functions get called from outside of this module, i.e. from RRC */
5387 /* Set LCID -> RLC channel mappings from signalling protocol (i.e. RRC or similar). */
5388 void set_mac_lte_channel_mapping(drb_mapping_t
*drb_mapping
)
5390 ue_dynamic_drb_mappings_t
*ue_mappings
;
5393 /* Check lcid range */
5394 if (drb_mapping
->lcid_present
) {
5395 lcid
= drb_mapping
->lcid
;
5397 /* Ignore if LCID is out of range */
5398 if ((lcid
< 3) || (lcid
> 10)) {
5403 /* Look for existing UE entry */
5404 ue_mappings
= (ue_dynamic_drb_mappings_t
*)g_hash_table_lookup(mac_lte_ue_channels_hash
,
5405 GUINT_TO_POINTER((guint
)drb_mapping
->ueid
));
5407 /* If not found, create & add to table */
5408 ue_mappings
= wmem_new0(wmem_file_scope(), ue_dynamic_drb_mappings_t
);
5409 g_hash_table_insert(mac_lte_ue_channels_hash
,
5410 GUINT_TO_POINTER((guint
)drb_mapping
->ueid
),
5414 /* If lcid wasn't supplied, need to try to look up from drbid */
5415 if ((lcid
== 0) && (drb_mapping
->drbid
< 32)) {
5416 lcid
= ue_mappings
->drb_to_lcid_mappings
[drb_mapping
->drbid
];
5419 /* Still no lcid - give up */
5423 /* Set array entry */
5424 ue_mappings
->mapping
[lcid
].valid
= TRUE
;
5425 ue_mappings
->mapping
[lcid
].drbid
= drb_mapping
->drbid
;
5426 ue_mappings
->drb_to_lcid_mappings
[drb_mapping
->drbid
] = lcid
;
5427 if (drb_mapping
->ul_priority_present
) {
5428 ue_mappings
->mapping
[lcid
].ul_priority
= drb_mapping
->ul_priority
;
5431 /* Fill in available RLC info */
5432 if (drb_mapping
->rlcMode_present
) {
5433 switch (drb_mapping
->rlcMode
) {
5435 ue_mappings
->mapping
[lcid
].channel_type
= rlcAM
;
5438 if (drb_mapping
->um_sn_length_present
) {
5439 if (drb_mapping
->um_sn_length
== 5) {
5440 ue_mappings
->mapping
[lcid
].channel_type
= rlcUM5
;
5443 ue_mappings
->mapping
[lcid
].channel_type
= rlcUM10
;
5454 /* Return the configured UL priority for the channel */
5455 static guint8
get_mac_lte_channel_priority(guint16 ueid
, guint8 lcid
,
5458 ue_dynamic_drb_mappings_t
*ue_mappings
;
5460 /* Priority only affects UL */
5461 if (direction
== DIRECTION_DOWNLINK
) {
5465 /* Look up the mappings for this UE */
5466 ue_mappings
= (ue_dynamic_drb_mappings_t
*)g_hash_table_lookup(mac_lte_ue_channels_hash
, GUINT_TO_POINTER((guint
)ueid
));
5471 /* Won't report value if channel not configured */
5472 if (!ue_mappings
->mapping
[lcid
].valid
) {
5476 return ue_mappings
->mapping
[lcid
].ul_priority
;
5480 /* Configure the DRX state for this UE (from RRC) */
5481 void set_mac_lte_drx_config(guint16 ueid
, drx_config_t
*drx_config
, packet_info
*pinfo
)
5483 if (global_mac_lte_show_drx
&& !pinfo
->fd
->flags
.visited
) {
5484 drx_state_t
*ue_state
;
5485 guint32 previousFrameNum
= 0;
5487 /* Find or create config/timing struct for this UE */
5488 ue_state
= (drx_state_t
*)g_hash_table_lookup(mac_lte_drx_ue_state
, GUINT_TO_POINTER((guint
)ueid
));
5489 if (ue_state
== NULL
) {
5490 ue_state
= (drx_state_t
*)wmem_new(wmem_file_scope(), drx_state_t
);
5491 g_hash_table_insert(mac_lte_drx_ue_state
, GUINT_TO_POINTER((guint
)ueid
), ue_state
);
5493 /* The signalling protocol (i.e. RRC) won't know the current SFN/SF, so
5494 don't try to set a time reference yet */
5495 /* Set time reference for this UE */
5496 /* ue_state->firstCycleStart = pinfo->fd->abs_ts;
5497 ue_state->firstCycleStartSet = TRUE;*/
5499 /* Current time starts off here */
5500 /* ue_state->currentTime = pinfo->fd->abs_ts;*/
5503 previousFrameNum
= ue_state
->config
.frameNum
;
5506 /* Clearing state when new config comes in... */
5507 init_drx_ue_state(ue_state
, TRUE
);
5509 /* Copy in new config */
5510 ue_state
->config
= *drx_config
;
5511 /* Remember frame when current settings set */
5512 ue_state
->config
.frameNum
= pinfo
->fd
->num
;
5513 /* Also remember any previous config frame number */
5514 ue_state
->config
.previousFrameNum
= previousFrameNum
;
5518 /* Release DRX config for this UE */
5519 void set_mac_lte_drx_config_release(guint16 ueid
, packet_info
*pinfo
)
5521 if (global_mac_lte_show_drx
&& !pinfo
->fd
->flags
.visited
) {
5522 /* Find or create config struct for table entry */
5523 drx_state_t
*ue_state
= (drx_state_t
*)g_hash_table_lookup(mac_lte_drx_ue_state
, GUINT_TO_POINTER((guint
)ueid
));
5524 if (ue_state
!= NULL
) {
5525 g_hash_table_remove(mac_lte_drx_ue_state
, GUINT_TO_POINTER((guint
)ueid
));
5526 /* TODO: free entry? */
5534 /* Function to be called from outside this module (e.g. in a plugin) to get per-packet data */
5535 mac_lte_info
*get_mac_lte_proto_data(packet_info
*pinfo
)
5537 return (mac_lte_info
*)p_get_proto_data(pinfo
->fd
, proto_mac_lte
, 0);
5540 /* Function to be called from outside this module (e.g. in a plugin) to set per-packet data */
5541 void set_mac_lte_proto_data(packet_info
*pinfo
, mac_lte_info
*p_mac_lte_info
)
5543 p_add_proto_data(pinfo
->fd
, proto_mac_lte
, 0, p_mac_lte_info
);
5546 void proto_register_mac_lte(void)
5548 static hf_register_info hf
[] =
5550 /**********************************/
5551 /* Items for decoding context */
5552 { &hf_mac_lte_context
,
5554 "mac-lte.context", FT_STRING
, BASE_NONE
, NULL
, 0x0,
5558 { &hf_mac_lte_context_radio_type
,
5560 "mac-lte.radio-type", FT_UINT8
, BASE_DEC
, VALS(radio_type_vals
), 0x0,
5564 { &hf_mac_lte_context_direction
,
5566 "mac-lte.direction", FT_UINT8
, BASE_DEC
, VALS(direction_vals
), 0x0,
5567 "Direction of message", HFILL
5570 { &hf_mac_lte_context_rnti
,
5572 "mac-lte.rnti", FT_UINT16
, BASE_DEC
, 0, 0x0,
5573 "RNTI associated with message", HFILL
5576 { &hf_mac_lte_context_rnti_type
,
5578 "mac-lte.rnti-type", FT_UINT8
, BASE_DEC
, VALS(rnti_type_vals
), 0x0,
5579 "Type of RNTI associated with message", HFILL
5582 { &hf_mac_lte_context_ueid
,
5584 "mac-lte.ueid", FT_UINT16
, BASE_DEC
, 0, 0x0,
5585 "User Equipment Identifier associated with message", HFILL
5588 { &hf_mac_lte_context_sysframe_number
,
5589 { "System Frame Number",
5590 "mac-lte.sfn", FT_UINT16
, BASE_DEC
, 0, 0x0,
5591 "System Frame Number associated with message", HFILL
5594 { &hf_mac_lte_context_subframe_number
,
5596 "mac-lte.subframe", FT_UINT16
, BASE_DEC
, 0, 0x0,
5597 "Subframe number associated with message", HFILL
5600 { &hf_mac_lte_context_grant_subframe_number
,
5602 "mac-lte.grant-subframe", FT_UINT16
, BASE_DEC
, 0, 0x0,
5603 "Subframe when grant for this PDU was received", HFILL
5606 { &hf_mac_lte_context_predefined_frame
,
5607 { "Predefined frame",
5608 "mac-lte.is-predefined-frame", FT_UINT8
, BASE_DEC
, VALS(predefined_frame_vals
), 0x0,
5609 "Predefined test frame (or real MAC PDU)", HFILL
5612 { &hf_mac_lte_context_length
,
5613 { "Length of frame",
5614 "mac-lte.length", FT_UINT8
, BASE_DEC
, 0, 0x0,
5615 "Original length of frame (including SDUs and padding)", HFILL
5618 { &hf_mac_lte_context_ul_grant_size
,
5619 { "Uplink grant size",
5620 "mac-lte.ul-grant-size", FT_UINT8
, BASE_DEC
, 0, 0x0,
5621 "Uplink grant size (in bytes)", HFILL
5624 { &hf_mac_lte_context_bch_transport_channel
,
5625 { "Transport channel",
5626 "mac-lte.bch-transport-channel", FT_UINT8
, BASE_DEC
, VALS(bch_transport_channel_vals
), 0x0,
5627 "Transport channel BCH data was carried on", HFILL
5630 { &hf_mac_lte_context_retx_count
,
5632 "mac-lte.retx-count", FT_UINT8
, BASE_DEC
, 0, 0x0,
5633 "Number of times this PDU has been retransmitted", HFILL
5636 { &hf_mac_lte_context_retx_reason
,
5638 "mac-lte.retx-reason", FT_UINT8
, BASE_DEC
, VALS(ul_retx_grant_vals
), 0x0,
5639 "Type of UL ReTx grant", HFILL
5642 { &hf_mac_lte_context_crc_status
,
5644 "mac-lte.crc-status", FT_UINT8
, BASE_DEC
, VALS(crc_status_vals
), 0x0,
5645 "CRC Status as reported by PHY", HFILL
5648 { &hf_mac_lte_context_carrier_id
,
5650 "mac-lte.carrier-id", FT_UINT8
, BASE_DEC
, VALS(carrier_id_vals
), 0x0,
5654 { &hf_mac_lte_context_rapid
,
5656 "mac-lte.preamble-sent.rapid", FT_UINT8
, BASE_DEC
, 0, 0x0,
5657 "RAPID sent in RACH preamble", HFILL
5660 { &hf_mac_lte_context_rach_attempt_number
,
5661 { "RACH Attempt Number",
5662 "mac-lte.preamble-sent.attempt", FT_UINT8
, BASE_DEC
, 0, 0x0,
5667 { &hf_mac_lte_ues_ul_per_tti
,
5669 "mac-lte.ul-tti-count", FT_UINT8
, BASE_DEC
, 0, 0x0,
5670 "In this TTI, this is the nth UL grant", HFILL
5673 { &hf_mac_lte_ues_dl_per_tti
,
5675 "mac-lte.dl-tti-count", FT_UINT8
, BASE_DEC
, 0, 0x0,
5676 "In this TTI, this is the nth DL PDU", HFILL
5681 /* Extra PHY context */
5682 { &hf_mac_lte_context_phy_ul
,
5683 { "UL PHY attributes",
5684 "mac-lte.ul-phy", FT_STRING
, BASE_NONE
, 0, 0x0,
5688 { &hf_mac_lte_context_phy_ul_modulation_type
,
5689 { "Modulation type",
5690 "mac-lte.ul-phy.modulation-type", FT_UINT8
, BASE_DEC
, VALS(modulation_type_vals
), 0x0,
5694 { &hf_mac_lte_context_phy_ul_tbs_index
,
5696 "mac-lte.ul-phy.tbs-index", FT_UINT8
, BASE_DEC
, 0, 0x0,
5700 { &hf_mac_lte_context_phy_ul_resource_block_length
,
5701 { "Resource Block Length",
5702 "mac-lte.ul-phy.resource-block-length", FT_UINT8
, BASE_DEC
, 0, 0x0,
5706 { &hf_mac_lte_context_phy_ul_resource_block_start
,
5707 { "Resource Block Start",
5708 "mac-lte.ul-phy.resource-block-start", FT_UINT8
, BASE_DEC
, 0, 0x0,
5712 { &hf_mac_lte_context_phy_ul_harq_id
,
5714 "mac-lte.ul-phy.harq-id", FT_UINT8
, BASE_DEC
, 0, 0x0,
5718 { &hf_mac_lte_context_phy_ul_ndi
,
5720 "mac-lte.ul-phy.ndi", FT_UINT8
, BASE_DEC
, 0, 0x0,
5721 "UL New Data Indicator", HFILL
5725 { &hf_mac_lte_context_phy_dl
,
5726 { "DL PHY attributes",
5727 "mac-lte.dl-phy", FT_STRING
, BASE_NONE
, 0, 0x0,
5731 { &hf_mac_lte_context_phy_dl_dci_format
,
5733 "mac-lte.dl-phy.dci-format", FT_UINT8
, BASE_DEC
, VALS(dci_format_vals
), 0x0,
5737 { &hf_mac_lte_context_phy_dl_resource_allocation_type
,
5738 { "Resource Allocation Type",
5739 "mac-lte.dl-phy.resource-allocation-type", FT_UINT8
, BASE_DEC
, 0, 0x0,
5743 { &hf_mac_lte_context_phy_dl_aggregation_level
,
5744 { "Aggregation Level",
5745 "mac-lte.dl-phy.aggregation-level", FT_UINT8
, BASE_DEC
, VALS(aggregation_level_vals
), 0x0,
5749 { &hf_mac_lte_context_phy_dl_mcs_index
,
5751 "mac-lte.dl-phy.mcs-index", FT_UINT8
, BASE_DEC
, 0, 0x0,
5755 { &hf_mac_lte_context_phy_dl_redundancy_version_index
,
5757 "mac-lte.dl-phy.rv-index", FT_UINT8
, BASE_DEC
, 0, 0x0,
5761 { &hf_mac_lte_context_phy_dl_retx
,
5763 "mac-lte.dl-phy.dl-retx", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
5767 { &hf_mac_lte_context_phy_dl_resource_block_length
,
5769 "mac-lte.dl-phy.rb-length", FT_UINT8
, BASE_DEC
, 0, 0x0,
5773 { &hf_mac_lte_context_phy_dl_crc_status
,
5775 "mac-lte.dl-phy.crc-status", FT_UINT8
, BASE_DEC
, VALS(crc_status_vals
), 0x0,
5779 { &hf_mac_lte_context_phy_dl_harq_id
,
5781 "mac-lte.dl-phy.harq-id", FT_UINT8
, BASE_DEC
, 0, 0x0,
5785 { &hf_mac_lte_context_phy_dl_ndi
,
5787 "mac-lte.dl-phy.ndi", FT_UINT8
, BASE_DEC
, 0, 0x0,
5788 "New Data Indicator", HFILL
5791 { &hf_mac_lte_context_phy_dl_tb
,
5793 "mac-lte.dl-phy.tb", FT_UINT8
, BASE_DEC
, 0, 0x0,
5794 "Transport Block (antenna #)", HFILL
5798 /* Out-of-band events */
5799 { &hf_mac_lte_oob_send_preamble
,
5801 "mac-lte.preamble-sent", FT_STRING
, BASE_NONE
, NULL
, 0x0,
5805 { &hf_mac_lte_number_of_srs
,
5807 "mac-lte.sr-req.count", FT_UINT32
, BASE_DEC
, 0, 0x0,
5808 "Number of UEs doing SR in this frame", HFILL
5812 /*******************************************/
5813 /* MAC shared channel header fields */
5814 { &hf_mac_lte_ulsch
,
5816 "mac-lte.ulsch", FT_STRING
, BASE_NONE
, NULL
, 0x0,
5820 { &hf_mac_lte_ulsch_header
,
5822 "mac-lte.ulsch.header", FT_STRING
, BASE_NONE
, NULL
, 0x0,
5826 { &hf_mac_lte_dlsch_header
,
5828 "mac-lte.dlsch.header", FT_STRING
, BASE_NONE
, NULL
, 0x0,
5832 { &hf_mac_lte_dlsch
,
5834 "mac-lte.dlsch", FT_STRING
, BASE_NONE
, NULL
, 0x0,
5838 { &hf_mac_lte_sch_subheader
,
5840 "mac-lte.sch.subheader", FT_STRING
, BASE_NONE
, NULL
, 0x0,
5846 "mac-lte.mch", FT_STRING
, BASE_NONE
, NULL
, 0x0,
5850 { &hf_mac_lte_mch_header
,
5852 "mac-lte.mch.header", FT_STRING
, BASE_NONE
, NULL
, 0x0,
5856 { &hf_mac_lte_mch_subheader
,
5858 "mac-lte.mch.subheader", FT_STRING
, BASE_NONE
, NULL
, 0x0,
5862 { &hf_mac_lte_sch_reserved
,
5863 { "SCH reserved bits",
5864 "mac-lte.sch.reserved", FT_UINT8
, BASE_HEX
, NULL
, 0xc0,
5868 { &hf_mac_lte_sch_extended
,
5870 "mac-lte.sch.extended", FT_UINT8
, BASE_HEX
, 0, 0x20,
5871 "Extension - i.e. further headers after this one", HFILL
5874 { &hf_mac_lte_dlsch_lcid
,
5876 "mac-lte.dlsch.lcid", FT_UINT8
, BASE_HEX
, VALS(dlsch_lcid_vals
), 0x1f,
5877 "DL-SCH Logical Channel Identifier", HFILL
5880 { &hf_mac_lte_ulsch_lcid
,
5882 "mac-lte.ulsch.lcid", FT_UINT8
, BASE_HEX
, VALS(ulsch_lcid_vals
), 0x1f,
5883 "UL-SCH Logical Channel Identifier", HFILL
5886 { &hf_mac_lte_sch_format
,
5888 "mac-lte.sch.format", FT_UINT8
, BASE_HEX
, VALS(format_vals
), 0x80,
5892 { &hf_mac_lte_sch_length
,
5894 "mac-lte.sch.length", FT_UINT16
, BASE_DEC
, 0, 0x0,
5895 "Length of MAC SDU or MAC control element", HFILL
5898 { &hf_mac_lte_mch_reserved
,
5899 { "MCH reserved bits",
5900 "mac-lte.mch.reserved", FT_UINT8
, BASE_HEX
, NULL
, 0xc0,
5904 { &hf_mac_lte_mch_extended
,
5906 "mac-lte.mch.extended", FT_UINT8
, BASE_HEX
, 0, 0x20,
5907 "Extension - i.e. further headers after this one", HFILL
5910 { &hf_mac_lte_mch_lcid
,
5912 "mac-lte.mch.lcid", FT_UINT8
, BASE_HEX
, VALS(mch_lcid_vals
), 0x1f,
5913 "MCH Logical Channel Identifier", HFILL
5916 { &hf_mac_lte_mch_format
,
5918 "mac-lte.mch.format", FT_UINT8
, BASE_HEX
, VALS(format_vals
), 0x80,
5922 { &hf_mac_lte_mch_length
,
5924 "mac-lte.mch.length", FT_UINT16
, BASE_DEC
, 0, 0x0,
5925 "Length of MAC SDU or MAC control element", HFILL
5928 { &hf_mac_lte_sch_header_only
,
5929 { "MAC PDU Header only",
5930 "mac-lte.sch.header-only", FT_UINT8
, BASE_DEC
, VALS(header_only_vals
), 0x0,
5934 { &hf_mac_lte_mch_header_only
,
5935 { "MAC PDU Header only",
5936 "mac-lte.mch.header-only", FT_UINT8
, BASE_DEC
, VALS(header_only_vals
), 0x0,
5941 /********************************/
5943 { &hf_mac_lte_sch_sdu
,
5945 "mac-lte.sch.sdu", FT_BYTES
, BASE_NONE
, 0, 0x0,
5946 "Shared channel SDU", HFILL
5949 { &hf_mac_lte_mch_sdu
,
5951 "mac-lte.mch.sdu", FT_BYTES
, BASE_NONE
, 0, 0x0,
5952 "Multicast channel SDU", HFILL
5955 { &hf_mac_lte_bch_pdu
,
5957 "mac-lte.bch.pdu", FT_BYTES
, BASE_NONE
, 0, 0x0,
5961 { &hf_mac_lte_pch_pdu
,
5963 "mac-lte.pch.pdu", FT_BYTES
, BASE_NONE
, 0, 0x0,
5967 { &hf_mac_lte_predefined_pdu
,
5968 { "Predefined data",
5969 "mac-lte.predefined-data", FT_BYTES
, BASE_NONE
, 0, 0x0,
5970 "Predefined test data", HFILL
5973 { &hf_mac_lte_raw_pdu
,
5975 "mac-lte.raw-data", FT_BYTES
, BASE_NONE
, 0, 0x0,
5976 "Raw bytes of PDU (e.g. if CRC error)", HFILL
5979 { &hf_mac_lte_padding_data
,
5981 "mac-lte.padding-data", FT_BYTES
, BASE_NONE
, 0, 0x0,
5985 { &hf_mac_lte_padding_length
,
5987 "mac-lte.padding-length", FT_INT32
, BASE_DEC
, 0, 0x0,
5988 "Length of padding data not included at end of frame", HFILL
5994 /*********************************/
5998 "mac-lte.rar", FT_NONE
, BASE_NONE
, NULL
, 0x0,
6002 { &hf_mac_lte_rar_headers
,
6004 "mac-lte.rar.headers", FT_STRING
, BASE_NONE
, NULL
, 0x0,
6008 { &hf_mac_lte_rar_header
,
6010 "mac-lte.rar.header", FT_STRING
, BASE_NONE
, NULL
, 0x0,
6014 { &hf_mac_lte_rar_extension
,
6016 "mac-lte.rar.e", FT_UINT8
, BASE_HEX
, 0, 0x80,
6017 "Extension - i.e. further RAR headers after this one", HFILL
6020 { &hf_mac_lte_rar_t
,
6022 "mac-lte.rar.t", FT_UINT8
, BASE_HEX
, VALS(rar_type_vals
), 0x40,
6023 "Type field indicating whether the payload is RAPID or BI", HFILL
6026 { &hf_mac_lte_rar_bi
,
6028 "mac-lte.rar.bi", FT_UINT8
, BASE_HEX
, VALS(rar_bi_vals
), 0x0f,
6029 "Backoff Indicator (ms)", HFILL
6032 { &hf_mac_lte_rar_rapid
,
6034 "mac-lte.rar.rapid", FT_UINT8
, BASE_HEX_DEC
, 0, 0x3f,
6035 "Random Access Preamble IDentifier", HFILL
6038 { &hf_mac_lte_rar_no_of_rapids
,
6039 { "Number of RAPIDs",
6040 "mac-lte.rar.no-of-rapids", FT_UINT8
, BASE_DEC
, 0, 0x0,
6041 "Number of RAPIDs in RAR PDU", HFILL
6044 { &hf_mac_lte_rar_reserved
,
6046 "mac-lte.rar.reserved", FT_UINT8
, BASE_HEX
, 0, 0x30,
6047 "Reserved bits in RAR header - should be 0", HFILL
6051 { &hf_mac_lte_rar_body
,
6053 "mac-lte.rar.body", FT_STRING
, BASE_NONE
, NULL
, 0x0,
6057 { &hf_mac_lte_rar_reserved2
,
6059 "mac-lte.rar.reserved2", FT_UINT8
, BASE_HEX
, 0, 0x80,
6060 "Reserved bit in RAR body - should be 0", HFILL
6063 { &hf_mac_lte_rar_ta
,
6065 "mac-lte.rar.ta", FT_UINT16
, BASE_DEC
, 0, 0x7ff0,
6066 "Required adjustment to uplink transmission timing", HFILL
6069 { &hf_mac_lte_rar_ul_grant
,
6071 "mac-lte.rar.ul-grant", FT_UINT24
, BASE_DEC
, 0, 0x0fffff,
6072 "Size of UL Grant", HFILL
6075 { &hf_mac_lte_rar_ul_grant_hopping
,
6077 "mac-lte.rar.ul-grant.hopping", FT_UINT8
, BASE_DEC
, 0, 0x08,
6081 { &hf_mac_lte_rar_ul_grant_fsrba
,
6082 { "Fixed sized resource block assignment",
6083 "mac-lte.rar.ul-grant.fsrba", FT_UINT16
, BASE_DEC
, 0, 0x07fe,
6087 { &hf_mac_lte_rar_ul_grant_tmcs
,
6088 { "Truncated Modulation and coding scheme",
6089 "mac-lte.rar.ul-grant.tmcs", FT_UINT16
, BASE_DEC
, 0, 0x01e0,
6093 { &hf_mac_lte_rar_ul_grant_tcsp
,
6094 { "TPC command for scheduled PUSCH",
6095 "mac-lte.rar.ul-grant.tcsp", FT_UINT8
, BASE_DEC
, 0, 0x01c,
6099 { &hf_mac_lte_rar_ul_grant_ul_delay
,
6101 "mac-lte.rar.ul-grant.ul-delay", FT_UINT8
, BASE_DEC
, 0, 0x02,
6105 { &hf_mac_lte_rar_ul_grant_cqi_request
,
6107 "mac-lte.rar.ul-grant.cqi-request", FT_UINT8
, BASE_DEC
, 0, 0x01,
6111 { &hf_mac_lte_rar_temporary_crnti
,
6112 { "Temporary C-RNTI",
6113 "mac-lte.rar.temporary-crnti", FT_UINT16
, BASE_DEC
, 0, 0x0,
6118 /**********************/
6119 /* Control PDU fields */
6120 { &hf_mac_lte_control_bsr
,
6122 "mac-lte.control.bsr", FT_STRING
, BASE_NONE
, 0, 0x0,
6123 "Buffer Status Report", HFILL
6126 { &hf_mac_lte_control_bsr_lcg_id
,
6127 { "Logical Channel Group ID",
6128 "mac-lte.control.bsr.lcg-id", FT_UINT8
, BASE_DEC
, 0, 0xc0,
6132 { &hf_mac_lte_control_short_bsr_buffer_size
,
6134 "mac-lte.control.bsr.buffer-size", FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
, &buffer_size_vals_ext
, 0x3f,
6135 "Buffer Size available in all channels in group", HFILL
6138 { &hf_mac_lte_control_long_bsr_buffer_size_0
,
6140 "mac-lte.control.bsr.buffer-size-0", FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
, &buffer_size_vals_ext
, 0xfc,
6141 "Buffer Size available in logical channel group 0", HFILL
6144 { &hf_mac_lte_control_long_bsr_buffer_size_1
,
6146 "mac-lte.control.bsr.buffer-size-1", FT_UINT16
, BASE_DEC
|BASE_EXT_STRING
, &buffer_size_vals_ext
, 0x03f0,
6147 "Buffer Size available in logical channel group 1", HFILL
6150 { &hf_mac_lte_control_long_bsr_buffer_size_2
,
6152 "mac-lte.control.bsr.buffer-size-2", FT_UINT16
, BASE_DEC
|BASE_EXT_STRING
, &buffer_size_vals_ext
, 0x0fc0,
6153 "Buffer Size available in logical channel group 2", HFILL
6156 { &hf_mac_lte_control_long_bsr_buffer_size_3
,
6158 "mac-lte.control.bsr.buffer-size-3", FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
, &buffer_size_vals_ext
, 0x3f,
6159 "Buffer Size available in logical channel group 3", HFILL
6162 { &hf_mac_lte_control_short_ext_bsr_buffer_size
,
6164 "mac-lte.control.bsr.buffer-size", FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
, &ext_buffer_size_vals_ext
, 0x3f,
6165 "Buffer Size available in all channels in group", HFILL
6168 { &hf_mac_lte_control_long_ext_bsr_buffer_size_0
,
6170 "mac-lte.control.bsr.buffer-size-0", FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
, &ext_buffer_size_vals_ext
, 0xfc,
6171 "Buffer Size available in logical channel group 0", HFILL
6174 { &hf_mac_lte_control_long_ext_bsr_buffer_size_1
,
6176 "mac-lte.control.bsr.buffer-size-1", FT_UINT16
, BASE_DEC
|BASE_EXT_STRING
, &ext_buffer_size_vals_ext
, 0x03f0,
6177 "Buffer Size available in logical channel group 1", HFILL
6180 { &hf_mac_lte_control_long_ext_bsr_buffer_size_2
,
6182 "mac-lte.control.bsr.buffer-size-2", FT_UINT16
, BASE_DEC
|BASE_EXT_STRING
, &ext_buffer_size_vals_ext
, 0x0fc0,
6183 "Buffer Size available in logical channel group 2", HFILL
6186 { &hf_mac_lte_control_long_ext_bsr_buffer_size_3
,
6188 "mac-lte.control.bsr.buffer-size-3", FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
, &ext_buffer_size_vals_ext
, 0x3f,
6189 "Buffer Size available in logical channel group 3", HFILL
6192 { &hf_mac_lte_control_crnti
,
6194 "mac-lte.control.crnti", FT_UINT16
, BASE_DEC
, 0, 0x0,
6195 "C-RNTI for the UE", HFILL
6198 { &hf_mac_lte_control_timing_advance
,
6200 "mac-lte.control.timing-advance", FT_STRING
, BASE_NONE
, 0, 0x0,
6204 { &hf_mac_lte_control_timing_advance_group_id
,
6205 { "Timing Advance Group Identity",
6206 "mac-lte.control.timing-advance.group-id", FT_UINT8
, BASE_DEC
, 0, 0xc0,
6210 { &hf_mac_lte_control_timing_advance_command
,
6211 { "Timing Advance Command",
6212 "mac-lte.control.timing-advance.command", FT_UINT8
, BASE_DEC
, 0, 0x3f,
6213 "Timing Advance (0-63 - see 36.213, 4.2.3)", HFILL
6216 { &hf_mac_lte_control_ue_contention_resolution
,
6217 { "UE Contention Resolution",
6218 "mac-lte.control.ue-contention-resolution", FT_STRING
, BASE_NONE
, 0, 0x0,
6222 { &hf_mac_lte_control_ue_contention_resolution_identity
,
6223 { "UE Contention Resolution Identity",
6224 "mac-lte.control.ue-contention-resolution.identity", FT_BYTES
, BASE_NONE
, 0, 0x0,
6228 { &hf_mac_lte_control_ue_contention_resolution_msg3
,
6230 "mac-lte.control.ue-contention-resolution.msg3", FT_FRAMENUM
, BASE_NONE
, 0, 0x0,
6234 { &hf_mac_lte_control_ue_contention_resolution_msg3_matched
,
6235 { "UE Contention Resolution Matches Msg3",
6236 "mac-lte.control.ue-contention-resolution.matches-msg3", FT_BOOLEAN
, BASE_NONE
, 0, 0x0,
6240 { &hf_mac_lte_control_ue_contention_resolution_time_since_msg3
,
6241 { "Time since Msg3",
6242 "mac-lte.control.ue-contention-resolution.time-since-msg3", FT_UINT32
, BASE_DEC
, 0, 0x0,
6243 "Time in ms since corresponding Msg3", HFILL
6247 { &hf_mac_lte_control_power_headroom
,
6249 "mac-lte.control.power-headroom", FT_STRING
, BASE_NONE
, 0, 0x0,
6253 { &hf_mac_lte_control_power_headroom_reserved
,
6255 "mac-lte.control.power-headroom.reserved", FT_UINT8
, BASE_DEC
, 0, 0xc0,
6256 "Reserved bits, should be 0", HFILL
6259 { &hf_mac_lte_control_power_headroom_level
,
6260 { "Power Headroom Level",
6261 "mac-lte.control.power-headroom.level", FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
,
6262 &power_headroom_vals_ext
, 0x3f, "Power Headroom Level in dB", HFILL
6266 { &hf_mac_lte_control_ext_power_headroom
,
6267 { "Extended Power Headroom",
6268 "mac-lte.control.ext-power-headroom", FT_STRING
, BASE_NONE
,
6272 { &hf_mac_lte_control_ext_power_headroom_c7
,
6273 { "SCell Index 7 Power Headroom",
6274 "mac-lte.control.ext-power-headroom.c7", FT_BOOLEAN
, 8,
6275 TFS(&mac_lte_scell_ph_vals
), 0x80, NULL
, HFILL
6278 { &hf_mac_lte_control_ext_power_headroom_c6
,
6279 { "SCell Index 6 Power Headroom",
6280 "mac-lte.control.ext-power-headroom.c6", FT_BOOLEAN
, 8,
6281 TFS(&mac_lte_scell_ph_vals
), 0x40, NULL
, HFILL
6284 { &hf_mac_lte_control_ext_power_headroom_c5
,
6285 { "SCell Index 5 Power Headroom",
6286 "mac-lte.control.ext-power-headroom.c5", FT_BOOLEAN
, 8,
6287 TFS(&mac_lte_scell_ph_vals
), 0x20, NULL
, HFILL
6290 { &hf_mac_lte_control_ext_power_headroom_c4
,
6291 { "SCell Index 4 Power Headroom",
6292 "mac-lte.control.ext-power-headroom.c4", FT_BOOLEAN
, 8,
6293 TFS(&mac_lte_scell_ph_vals
), 0x10, NULL
, HFILL
6296 { &hf_mac_lte_control_ext_power_headroom_c3
,
6297 { "SCell Index 3 Power Headroom",
6298 "mac-lte.control.ext-power-headroom.c3", FT_BOOLEAN
, 8,
6299 TFS(&mac_lte_scell_ph_vals
), 0x08, NULL
, HFILL
6302 { &hf_mac_lte_control_ext_power_headroom_c2
,
6303 { "SCell Index 2 Power Headroom",
6304 "mac-lte.control.ext-power-headroom.c2", FT_BOOLEAN
, 8,
6305 TFS(&mac_lte_scell_ph_vals
), 0x04, NULL
, HFILL
6308 { &hf_mac_lte_control_ext_power_headroom_c1
,
6309 { "SCell Index 1 Power Headroom",
6310 "mac-lte.control.ext-power-headroom.c1", FT_BOOLEAN
, 8,
6311 TFS(&mac_lte_scell_ph_vals
), 0x02, NULL
, HFILL
6314 { &hf_mac_lte_control_ext_power_headroom_reserved
,
6316 "mac-lte.control.ext-power-headroom.reserved", FT_UINT8
, BASE_DEC
,
6317 0, 0x01, "Reserved bit, should be 0", HFILL
6320 { &hf_mac_lte_control_ext_power_headroom_power_backoff
,
6322 "mac-lte.control.ext-power-headroom.power-backoff", FT_BOOLEAN
, 8,
6323 TFS(&mac_lte_power_backoff_vals
), 0x80, NULL
, HFILL
6326 { &hf_mac_lte_control_ext_power_headroom_value
,
6327 { "Power Headroom Value",
6328 "mac-lte.control.ext-power-headroom.power-headroom-value", FT_BOOLEAN
, 8,
6329 TFS(&mac_lte_ph_value_vals
), 0x40, NULL
, HFILL
6332 { &hf_mac_lte_control_ext_power_headroom_level
,
6333 { "Power Headroom Level",
6334 "mac-lte.control.ext-power-headroom.level", FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
,
6335 &power_headroom_vals_ext
, 0x3f, "Power Headroom Level in dB", HFILL
6338 { &hf_mac_lte_control_ext_power_headroom_reserved2
,
6340 "mac-lte.control.ext-power-headroom.reserved2", FT_UINT8
, BASE_DEC
,
6341 0, 0xc0, "Reserved bits, should be 0", HFILL
6344 { &hf_mac_lte_control_ext_power_headroom_pcmaxc
,
6345 { "Configured UE Transmit Power",
6346 "mac-lte.control.ext-power-headroom.pcmaxc", FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
,
6347 &pcmaxc_vals_ext
, 0x3f, "Pcmax,c in dBm", HFILL
6351 { &hf_mac_lte_control_activation_deactivation
,
6352 { "Activation/Deactivation",
6353 "mac-lte.control.activation-deactivation", FT_STRING
, BASE_NONE
,
6357 { &hf_mac_lte_control_activation_deactivation_c7
,
6358 { "SCell Index 7 Status",
6359 "mac-lte.control.activation-deactivation.c7", FT_BOOLEAN
, 8,
6360 TFS(&mac_lte_scell_status_vals
), 0x80, NULL
, HFILL
6363 { &hf_mac_lte_control_activation_deactivation_c6
,
6364 { "SCell Index 6 Status",
6365 "mac-lte.control.activation-deactivation.c6", FT_BOOLEAN
, 8,
6366 TFS(&mac_lte_scell_status_vals
), 0x40, NULL
, HFILL
6369 { &hf_mac_lte_control_activation_deactivation_c5
,
6370 { "SCell Index 5 Status",
6371 "mac-lte.control.activation-deactivation.c5", FT_BOOLEAN
, 8,
6372 TFS(&mac_lte_scell_status_vals
), 0x20, NULL
, HFILL
6375 { &hf_mac_lte_control_activation_deactivation_c4
,
6376 { "SCell Index 4 Status",
6377 "mac-lte.control.activation-deactivation.c4", FT_BOOLEAN
, 8,
6378 TFS(&mac_lte_scell_status_vals
), 0x10, NULL
, HFILL
6381 { &hf_mac_lte_control_activation_deactivation_c3
,
6382 { "SCell Index 3 Status",
6383 "mac-lte.control.activation-deactivation.c3", FT_BOOLEAN
, 8,
6384 TFS(&mac_lte_scell_status_vals
), 0x08, NULL
, HFILL
6387 { &hf_mac_lte_control_activation_deactivation_c2
,
6388 { "SCell Index 2 Status",
6389 "mac-lte.control.activation-deactivation.c2", FT_BOOLEAN
, 8,
6390 TFS(&mac_lte_scell_status_vals
), 0x04, NULL
, HFILL
6393 { &hf_mac_lte_control_activation_deactivation_c1
,
6394 { "SCell Index 1 Status",
6395 "mac-lte.control.activation-deactivation.c1", FT_BOOLEAN
, 8,
6396 TFS(&mac_lte_scell_status_vals
), 0x02, NULL
, HFILL
6399 { &hf_mac_lte_control_activation_deactivation_reserved
,
6401 "mac-lte.control.activation-deactivation.reserved", FT_UINT8
, BASE_DEC
,
6402 0, 0x01, "Reserved bit, should be 0", HFILL
6406 { &hf_mac_lte_control_mch_scheduling_info
,
6407 { "MCH Scheduling Information",
6408 "mac-lte.control.mch_scheduling_info", FT_STRING
, BASE_NONE
, 0, 0x0,
6412 { &hf_mac_lte_control_mch_scheduling_info_lcid
,
6414 "mac-lte.control.mch_scheduling_info.lcid", FT_UINT8
, BASE_HEX
, VALS(mch_lcid_vals
), 0xf8,
6415 "Logical Channel ID of the MTCH", HFILL
6418 { &hf_mac_lte_control_mch_scheduling_info_stop_mtch
,
6420 "mac-lte.control.mch_scheduling_info.stop_mtch", FT_UINT16
, BASE_DEC
, 0, 0x07ff,
6421 "Ordinal number of the subframe where the corresponding MTCH stops", HFILL
6425 /* Generated fields */
6426 { &hf_mac_lte_dl_harq_resend_original_frame
,
6427 { "Frame with previous tx",
6428 "mac-lte.dlsch.retx.original-frame", FT_FRAMENUM
, BASE_NONE
, 0, 0x0,
6432 { &hf_mac_lte_dl_harq_resend_time_since_previous_frame
,
6433 { "Time since previous tx (ms)",
6434 "mac-lte.dlsch.retx.time-since-previous", FT_UINT16
, BASE_DEC
, 0, 0x0,
6438 { &hf_mac_lte_dl_harq_resend_next_frame
,
6439 { "Frame with next tx",
6440 "mac-lte.dlsch.retx.next-frame", FT_FRAMENUM
, BASE_NONE
, 0, 0x0,
6444 { &hf_mac_lte_dl_harq_resend_time_until_next_frame
,
6445 { "Time until next tx (ms)",
6446 "mac-lte.dlsch.retx.time-until-next", FT_UINT16
, BASE_DEC
, 0, 0x0,
6451 { &hf_mac_lte_ul_harq_resend_original_frame
,
6452 { "Frame with previous tx",
6453 "mac-lte.ulsch.retx.original-frame", FT_FRAMENUM
, BASE_NONE
, 0, 0x0,
6457 { &hf_mac_lte_ul_harq_resend_time_since_previous_frame
,
6458 { "Time since previous tx (ms)",
6459 "mac-lte.ulsch.retx.time-since-previous", FT_UINT16
, BASE_DEC
, 0, 0x0,
6463 { &hf_mac_lte_ul_harq_resend_next_frame
,
6464 { "Frame with next tx",
6465 "mac-lte.ulsch.retx.next-frame", FT_FRAMENUM
, BASE_NONE
, 0, 0x0,
6469 { &hf_mac_lte_ul_harq_resend_time_until_next_frame
,
6470 { "Time until next tx (ms)",
6471 "mac-lte.ulsch.retx.time-until-next", FT_UINT16
, BASE_DEC
, 0, 0x0,
6476 { &hf_mac_lte_grant_answering_sr
,
6477 { "First Grant Following SR from",
6478 "mac-lte.ulsch.grant-answering-sr", FT_FRAMENUM
, BASE_NONE
, 0, 0x0,
6482 { &hf_mac_lte_failure_answering_sr
,
6483 { "SR which failed",
6484 "mac-lte.ulsch.failure-answering-sr", FT_FRAMENUM
, BASE_NONE
, 0, 0x0,
6488 { &hf_mac_lte_sr_leading_to_failure
,
6490 "mac-lte.ulsch.failure-answering-sr-frame", FT_FRAMENUM
, BASE_NONE
, 0, 0x0,
6494 { &hf_mac_lte_sr_leading_to_grant
,
6495 { "This SR results in a grant here",
6496 "mac-lte.ulsch.grant-answering-sr-frame", FT_FRAMENUM
, BASE_NONE
, 0, 0x0,
6500 { &hf_mac_lte_sr_time_since_request
,
6501 { "Time since SR (ms)",
6502 "mac-lte.ulsch.time-since-sr", FT_UINT32
, BASE_DEC
, 0, 0x0,
6506 { &hf_mac_lte_sr_time_until_answer
,
6507 { "Time until answer (ms)",
6508 "mac-lte.ulsch.time-until-sr-answer", FT_UINT32
, BASE_DEC
, 0, 0x0,
6513 { &hf_mac_lte_drx_config
,
6514 { "DRX Configuration",
6515 "mac-lte.drx-config", FT_STRING
, BASE_NONE
,
6519 { &hf_mac_lte_drx_config_frame_num
,
6521 "mac-lte.drx-config.config-frame", FT_FRAMENUM
, BASE_NONE
,
6525 { &hf_mac_lte_drx_config_previous_frame_num
,
6526 { "Previous Config Frame",
6527 "mac-lte.drx-config.previous-config-frame", FT_FRAMENUM
, BASE_NONE
,
6531 { &hf_mac_lte_drx_config_long_cycle
,
6533 "mac-lte.drx-config.long-cycle", FT_UINT16
, BASE_DEC
,
6537 { &hf_mac_lte_drx_config_cycle_offset
,
6539 "mac-lte.drx-config.cycle-offset", FT_UINT16
, BASE_DEC
,
6543 { &hf_mac_lte_drx_config_onduration_timer
,
6544 { "OnDuration Timer",
6545 "mac-lte.drx-config.onduration-timer", FT_UINT16
, BASE_DEC
,
6549 { &hf_mac_lte_drx_config_inactivity_timer
,
6550 { "Inactivity Timer",
6551 "mac-lte.drx-config.inactivity-timer", FT_UINT16
, BASE_DEC
,
6555 { &hf_mac_lte_drx_config_retransmission_timer
,
6556 { "Retransmission Timer",
6557 "mac-lte.drx-config.retransmission-timer", FT_UINT16
, BASE_DEC
,
6561 { &hf_mac_lte_drx_config_short_cycle
,
6563 "mac-lte.drx-config.short-cycle", FT_UINT16
, BASE_DEC
,
6567 { &hf_mac_lte_drx_config_short_cycle_timer
,
6568 { "Short cycle Timer",
6569 "mac-lte.drx-config.short-cycle-timer", FT_UINT16
, BASE_DEC
,
6574 { &hf_mac_lte_drx_state
,
6576 "mac-lte.drx-state", FT_STRING
, BASE_NONE
,
6580 { &hf_mac_lte_drx_state_long_cycle_offset
,
6581 { "Long cycle offset",
6582 "mac-lte.drx-state.long-cycle-offset", FT_UINT16
, BASE_DEC
,
6586 { &hf_mac_lte_drx_state_long_cycle_on
,
6587 { "Long cycle current on",
6588 "mac-lte.drx-state.long-cycle-on", FT_BOOLEAN
, BASE_NONE
,
6592 { &hf_mac_lte_drx_state_short_cycle_offset
,
6593 { "Short cycle offset",
6594 "mac-lte.drx-state.short-cycle-offset", FT_UINT16
, BASE_DEC
,
6598 { &hf_mac_lte_drx_state_short_cycle_on
,
6599 { "Short cycle current on",
6600 "mac-lte.drx-state.short-cycle-on", FT_BOOLEAN
, BASE_NONE
,
6604 { &hf_mac_lte_drx_state_inactivity_remaining
,
6605 { "Inactivity remaining",
6606 "mac-lte.drx-state.inactivity-remaining", FT_UINT16
, BASE_DEC
,
6610 { &hf_mac_lte_drx_state_onduration_remaining
,
6611 { "Onduration remaining",
6612 "mac-lte.drx-state.onduration-remaining", FT_UINT16
, BASE_DEC
,
6616 { &hf_mac_lte_drx_state_retransmission_remaining
,
6617 { "Retransmission remaining",
6618 "mac-lte.drx-state.retransmission-remaining", FT_UINT16
, BASE_DEC
,
6622 { &hf_mac_lte_drx_state_rtt_remaining
,
6624 "mac-lte.drx-state.rtt-remaining", FT_UINT16
, BASE_DEC
,
6628 { &hf_mac_lte_drx_state_short_cycle_remaining
,
6629 { "Short-cycle timer remaining",
6630 "mac-lte.drx-state.short-cycle-remaining", FT_UINT16
, BASE_DEC
,
6636 static gint
*ett
[] =
6639 &ett_mac_lte_context
,
6640 &ett_mac_lte_phy_context
,
6641 &ett_mac_lte_rar_headers
,
6642 &ett_mac_lte_rar_header
,
6643 &ett_mac_lte_rar_body
,
6644 &ett_mac_lte_rar_ul_grant
,
6645 &ett_mac_lte_ulsch_header
,
6646 &ett_mac_lte_dlsch_header
,
6647 &ett_mac_lte_mch_header
,
6648 &ett_mac_lte_sch_subheader
,
6649 &ett_mac_lte_mch_subheader
,
6653 &ett_mac_lte_activation_deactivation
,
6654 &ett_mac_lte_contention_resolution
,
6655 &ett_mac_lte_timing_advance
,
6656 &ett_mac_lte_power_headroom
,
6657 &ett_mac_lte_extended_power_headroom
,
6658 &ett_mac_lte_extended_power_headroom_cell
,
6659 &ett_mac_lte_mch_scheduling_info
,
6661 &ett_mac_lte_drx_config
,
6662 &ett_mac_lte_drx_state
6665 static ei_register_info ei
[] = {
6666 { &ei_mac_lte_reserved_not_zero
, { "mac-lte.reserved_not_zero", PI_MALFORMED
, PI_ERROR
, "Reserved bit not zero", EXPFILL
}},
6667 { &ei_mac_lte_rar_timing_advance_not_zero_note
, { "mac-lte.mac-lte.rar.ta.not_zero", PI_SEQUENCE
, PI_NOTE
, "RAR Timing advance not zero", EXPFILL
}},
6668 { &ei_mac_lte_rar_timing_advance_not_zero_warn
, { "mac-lte.mac-lte.rar.ta.not_zero", PI_SEQUENCE
, PI_WARN
, "RAR Timing advance not zero", EXPFILL
}},
6669 { &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
}},
6670 { &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
}},
6671 { &ei_mac_lte_bch_pdu
, { "mac-lte.bch.pdu.uplink", PI_MALFORMED
, PI_ERROR
, "BCH data should not be received in Uplink!", EXPFILL
}},
6672 { &ei_mac_lte_pch_pdu
, { "mac-lte.pch.pdu.uplink", PI_MALFORMED
, PI_ERROR
, "PCH data should not be received in Uplink!", EXPFILL
}},
6673 { &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
}},
6674 { &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
}},
6675 { &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
}},
6676 { &ei_mac_lte_sr_invalid_event
, { "mac-lte.ulsch.sr-invalid-event", PI_SEQUENCE
, PI_ERROR
, "Invalid SR event for UE", EXPFILL
}},
6677 { &ei_mac_lte_dlsch_lcid
, { "mac-lte.dlsch.lcid.DRX_received", PI_SEQUENCE
, PI_NOTE
, "DRX command received for UE", EXPFILL
}},
6678 { &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
}},
6679 { &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
}},
6680 { &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
}},
6681 { &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
}},
6682 { &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
}},
6683 { &ei_mac_lte_lcid_unexpected
, { "mac-lte.lcid_unexpected", PI_MALFORMED
, PI_ERROR
, "?L-SCH: Unexpected LCID received", EXPFILL
}},
6684 { &ei_mac_lte_too_many_subheaders
, { "mac-lte.too_many_subheaders", PI_MALFORMED
, PI_ERROR
, "Reached too many subheaders - frame obviously malformed", EXPFILL
}},
6685 { &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
}},
6686 { &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
}},
6687 { &ei_mac_lte_control_timing_advance_command_correction_needed
, { "mac-lte.control.timing-advance.command.correction_needed", PI_SEQUENCE
, PI_WARN
, "Timing Advance control element received with correction needed", EXPFILL
}},
6688 { &ei_mac_lte_control_element_size_invalid
, { "mac-lte.control_element.size_invalid", PI_MALFORMED
, PI_ERROR
, "Control Element has an unexpected size", EXPFILL
}},
6689 { &ei_mac_lte_bsr_warn_threshold_exceeded
, { "mac-lte.bsr_warn_threshold_exceeded", PI_SEQUENCE
, PI_WARN
, "BSR for LCG X exceeds threshold", EXPFILL
}},
6690 { &ei_mac_lte_sch_header_only
, { "mac-lte.sch.header-only.expert", PI_SEQUENCE
, PI_NOTE
, "MAC PDU SDUs have been omitted", EXPFILL
}},
6691 { &ei_mac_lte_context_length
, { "mac-lte.length.invalid", PI_MALFORMED
, PI_ERROR
, "MAC PDU is longer than reported length", EXPFILL
}},
6692 { &ei_mac_lte_rach_preamble_sent_warn
, { "mac-lte.rach_preamble_sent", PI_SEQUENCE
, PI_WARN
, "RACH Preamble sent", EXPFILL
}},
6693 { &ei_mac_lte_rach_preamble_sent_note
, { "mac-lte.rach_preamble_sent", PI_SEQUENCE
, PI_NOTE
, "RACH Preamble sent", EXPFILL
}},
6694 { &ei_mac_lte_oob_send_sr
, { "mac-lte.sr-req", PI_SEQUENCE
, PI_NOTE
, "Scheduling Request sent", EXPFILL
}},
6695 { &ei_mac_lte_oob_sr_failure
, { "mac-lte.sr-failure", PI_SEQUENCE
, PI_ERROR
, "Scheduling Request failed", EXPFILL
}},
6696 { &ei_mac_lte_context_sysframe_number
, { "mac-lte.sfn.out_of_range", PI_MALFORMED
, PI_ERROR
, "Sysframe number out of range", EXPFILL
}},
6697 { &ei_mac_lte_context_rnti_type
, { "mac-lte.rnti-type.invalid", PI_MALFORMED
, PI_ERROR
, "RNTI indicated, but value is not correct", EXPFILL
}},
6698 { &ei_mac_lte_ul_mac_frame_retx
, { "mac-lte.ul_mac_frame_retx", PI_SEQUENCE
, PI_WARN
, "UL MAC frame ReTX", EXPFILL
}},
6699 { &ei_mac_lte_context_crc_status
, { "mac-lte.crc-status.error", PI_MALFORMED
, PI_ERROR
, "Frame has CRC error problem", EXPFILL
}},
6702 static const enum_val_t show_info_col_vals
[] = {
6703 {"show-phy", "PHY Info", ShowPHYLayer
},
6704 {"show-mac", "MAC Info", ShowMACLayer
},
6705 {"show-rlc", "RLC Info", ShowRLCLayer
},
6709 static const enum_val_t lcid_drb_source_vals
[] = {
6710 {"from-static-stable", "From static table", FromStaticTable
},
6711 {"from-configuration-protocol", "From configuration protocol", FromConfigurationProtocol
},
6716 module_t
*mac_lte_module
;
6717 expert_module_t
* expert_mac_lte
;
6719 static uat_field_t lcid_drb_mapping_flds
[] = {
6720 UAT_FLD_VS(lcid_drb_mappings
, lcid
, "lcid", drb_lcid_vals
, "The MAC LCID"),
6721 UAT_FLD_DEC(lcid_drb_mappings
, drbid
,"drb id (1-32)", "Identifier of logical data channel"),
6722 UAT_FLD_VS(lcid_drb_mappings
, channel_type
, "RLC Channel Type", rlc_channel_type_vals
, "The MAC LCID"),
6726 /* Register protocol. */
6727 proto_mac_lte
= proto_register_protocol("MAC-LTE", "MAC-LTE", "mac-lte");
6728 proto_register_field_array(proto_mac_lte
, hf
, array_length(hf
));
6729 proto_register_subtree_array(ett
, array_length(ett
));
6730 expert_mac_lte
= expert_register_protocol(proto_mac_lte
);
6731 expert_register_field_array(expert_mac_lte
, ei
, array_length(ei
));
6733 /* Allow other dissectors to find this one by name. */
6734 register_dissector("mac-lte", dissect_mac_lte
, proto_mac_lte
);
6736 /* Register the tap name */
6737 mac_lte_tap
= register_tap("mac-lte");
6740 mac_lte_module
= prefs_register_protocol(proto_mac_lte
, NULL
);
6742 /* Obsolete preferences */
6743 prefs_register_obsolete_preference(mac_lte_module
, "single_rar");
6744 prefs_register_obsolete_preference(mac_lte_module
, "check_reserved_bits");
6745 prefs_register_obsolete_preference(mac_lte_module
, "decode_rar_ul_grant");
6746 prefs_register_obsolete_preference(mac_lte_module
, "show_rlc_info_column");
6747 prefs_register_obsolete_preference(mac_lte_module
, "attempt_to_detect_dl_harq_resend");
6748 prefs_register_obsolete_preference(mac_lte_module
, "attempt_to_track_ul_harq_resend");
6750 prefs_register_uint_preference(mac_lte_module
, "retx_count_warn",
6751 "Number of Re-Transmits before expert warning triggered",
6752 "Number of Re-Transmits before expert warning triggered",
6753 10, &global_mac_lte_retx_counter_trigger
);
6755 prefs_register_bool_preference(mac_lte_module
, "attempt_rrc_decode",
6756 "Attempt to decode BCH, PCH and CCCH data using LTE RRC dissector",
6757 "Attempt to decode BCH, PCH and CCCH data using LTE RRC dissector",
6758 &global_mac_lte_attempt_rrc_decode
);
6760 prefs_register_bool_preference(mac_lte_module
, "attempt_to_dissect_crc_failures",
6761 "Dissect frames that have failed CRC check",
6762 "Attempt to dissect frames that have failed CRC check",
6763 &global_mac_lte_dissect_crc_failures
);
6765 prefs_register_bool_preference(mac_lte_module
, "heuristic_mac_lte_over_udp",
6766 "Try Heuristic LTE-MAC over UDP framing",
6767 "When enabled, use heuristic dissector to find MAC-LTE frames sent with "
6769 &global_mac_lte_heur
);
6771 prefs_register_bool_preference(mac_lte_module
, "attempt_to_dissect_srb_sdus",
6772 "Attempt to dissect LCID 1&2 as srb1&2",
6773 "Will call LTE RLC dissector with standard settings as per RRC spec",
6774 &global_mac_lte_attempt_srb_decode
);
6776 prefs_register_bool_preference(mac_lte_module
, "attempt_to_dissect_mcch",
6777 "Attempt to dissect MCH LCID 0 as MCCH",
6778 "Will call LTE RLC dissector for MCH LCID 0",
6779 &global_mac_lte_attempt_mcch_decode
);
6781 prefs_register_bool_preference(mac_lte_module
, "call_rlc_for_mtch",
6782 "Call RLC dissector MTCH LCIDs",
6783 "Call RLC dissector MTCH LCIDs",
6784 &global_mac_lte_call_rlc_for_mtch
);
6786 prefs_register_enum_preference(mac_lte_module
, "lcid_to_drb_mapping_source",
6787 "Source of LCID -> drb channel settings",
6788 "Set whether LCID -> drb Table is taken from static table (below) or from "
6789 "info learned from control protocol (e.g. RRC)",
6790 &global_mac_lte_lcid_drb_source
, lcid_drb_source_vals
, FALSE
);
6792 lcid_drb_mappings_uat
= uat_new("Static LCID -> drb Table",
6793 sizeof(lcid_drb_mapping_t
),
6796 (void**) &lcid_drb_mappings
,
6797 &num_lcid_drb_mappings
,
6798 UAT_AFFECTS_DISSECTION
, /* affects dissection of packets, but not set of named fields */
6799 "", /* TODO: is this ref to help manual? */
6800 lcid_drb_mapping_copy_cb
,
6804 lcid_drb_mapping_flds
);
6806 prefs_register_uat_preference(mac_lte_module
,
6808 "LCID -> DRB Mappings Table",
6809 "A table that maps from configurable lcids -> RLC logical channels",
6810 lcid_drb_mappings_uat
);
6812 prefs_register_uint_preference(mac_lte_module
, "bsr_warn_threshold",
6813 "BSR size when warning should be issued (0 - 63)",
6814 "If any BSR report is >= this number, an expert warning will be added",
6815 10, &global_mac_lte_bsr_warn_threshold
);
6817 prefs_register_bool_preference(mac_lte_module
, "track_sr",
6818 "Track status of SRs within UEs",
6819 "Track status of SRs, providing links between requests, failure indications and grants",
6820 &global_mac_lte_track_sr
);
6822 prefs_register_enum_preference(mac_lte_module
, "layer_to_show",
6823 "Which layer info to show in Info column",
6824 "Can show PHY, MAC or RLC layer info in Info column",
6825 &global_mac_lte_layer_to_show
, show_info_col_vals
, FALSE
);
6827 prefs_register_bool_preference(mac_lte_module
, "decode_cr_body",
6828 "Decode CR body as UL CCCH",
6829 "Attempt to decode 6 bytes of Contention Resolution body as an UL CCCH PDU",
6830 &global_mac_lte_decode_cr_body
);
6832 prefs_register_bool_preference(mac_lte_module
, "show_drx",
6833 "Show DRX Information (Incomplete/experimental!)",
6834 "Apply DRX config and show DRX state within each UE",
6835 &global_mac_lte_show_drx
);
6838 register_init_routine(&mac_lte_init_protocol
);
6841 void proto_reg_handoff_mac_lte(void)
6843 /* Add as a heuristic UDP dissector */
6844 heur_dissector_add("udp", dissect_mac_lte_heur
, proto_mac_lte
);
6846 /* Look up RLC dissector handle once and for all */
6847 rlc_lte_handle
= find_dissector("rlc-lte");
6851 * Editor modelines - http://www.wireshark.org/tools/modelines.html
6856 * indent-tabs-mode: nil
6859 * vi: set shiftwidth=4 tabstop=8 expandtab:
6860 * :indentSize=4:tabSize=8:noTabs=true: