MSWSP: fix dissect_mswsp_smb()
[wireshark-wip.git] / epan / dissectors / packet-mac-lte.c
blob037b6420e682fa5ab522073af581d97a6a9d2ded
1 /* Routines for LTE MAC disassembly
3 * Martin Mathieson
5 * $Id$
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.
22 #include "config.h"
24 #include <string.h>
26 #include <epan/packet.h>
27 #include <epan/exceptions.h>
28 #include <epan/expert.h>
29 #include <epan/prefs.h>
30 #include <epan/tap.h>
31 #include <epan/uat.h>
32 #include <epan/wmem/wmem.h>
34 #include "packet-mac-lte.h"
35 #include "packet-rlc-lte.h"
38 /* Described in:
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;
130 /* Data */
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;
141 /* RAR fields */
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;
254 /* Subtrees. */
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[] =
321 { FDD_RADIO, "FDD"},
322 { TDD_RADIO, "TDD"},
323 { 0, NULL }
327 static const value_string direction_vals[] =
329 { DIRECTION_UPLINK, "Uplink"},
330 { DIRECTION_DOWNLINK, "Downlink"},
331 { 0, NULL }
335 static const value_string rnti_type_vals[] =
337 { NO_RNTI, "NO-RNTI"},
338 { P_RNTI, "P-RNTI"},
339 { RA_RNTI, "RA-RNTI"},
340 { C_RNTI, "C-RNTI"},
341 { SI_RNTI, "SI-RNTI"},
342 { SPS_RNTI, "SPS-RNTI"},
343 { M_RNTI, "M-RNTI"},
344 { 0, NULL }
347 static const value_string bch_transport_channel_vals[] =
349 { SI_RNTI, "DL-SCH"},
350 { NO_RNTI, "BCH"},
351 { 0, NULL }
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"},
362 { 0, NULL }
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"},
372 { 0, NULL }
375 static const value_string dci_format_vals[] =
377 { 0, "0"},
378 { 1, "1"},
379 { 2, "1A"},
380 { 3, "1B"},
381 { 4, "1C"},
382 { 5, "1D"},
383 { 6, "2"},
384 { 7, "2A"},
385 { 8, "3/3A"},
386 { 0, NULL }
389 static const value_string aggregation_level_vals[] =
391 { 0, "1"},
392 { 1, "2"},
393 { 2, "4"},
394 { 3, "8"},
395 { 0, NULL }
398 static const value_string modulation_type_vals[] =
400 { 2, "QPSK"},
401 { 4, "QAM16"},
402 { 6, "QAM64"},
403 { 0, NULL }
406 static const true_false_string mac_lte_scell_ph_vals = {
407 "Reported",
408 "Not reported"
411 static const true_false_string mac_lte_power_backoff_vals = {
412 "Applied",
413 "Not applied"
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 = {
422 "Activated",
423 "Deactivated"
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[] =
434 { 0, "CCCH"},
435 { 1, "1"},
436 { 2, "2"},
437 { 3, "3"},
438 { 4, "4"},
439 { 5, "5"},
440 { 6, "6"},
441 { 7, "7"},
442 { 8, "8"},
443 { 9, "9"},
444 { 10, "10"},
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" },
450 { 0, NULL }
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[] =
462 { 0, "CCCH"},
463 { 1, "1"},
464 { 2, "2"},
465 { 3, "3"},
466 { 4, "4"},
467 { 5, "5"},
468 { 6, "6"},
469 { 7, "7"},
470 { 8, "8"},
471 { 9, "9"},
472 { 10, "10"},
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" },
480 { 0, NULL }
483 #define MCH_SCHEDULING_INFO_LCID 0x1e
485 static const value_string mch_lcid_vals[] =
487 { 0, "MCCH"},
488 { 1, "1"},
489 { 2, "2"},
490 { 3, "3"},
491 { 4, "4"},
492 { 5, "5"},
493 { 6, "6"},
494 { 7, "7"},
495 { 8, "8"},
496 { 9, "9"},
497 { 10, "10"},
498 { 11, "11"},
499 { 12, "12"},
500 { 13, "13"},
501 { 14, "14"},
502 { 15, "15"},
503 { 16, "16"},
504 { 17, "17"},
505 { 18, "18"},
506 { 19, "19"},
507 { 20, "20"},
508 { 21, "21"},
509 { 22, "22"},
510 { 23, "23"},
511 { 24, "24"},
512 { 25, "25"},
513 { 26, "26"},
514 { 27, "27"},
515 { 28, "28"},
516 { MCH_SCHEDULING_INFO_LCID, "MCH Scheduling Information"},
517 { PADDING_LCID, "Padding" },
518 { 0, NULL }
521 static const value_string format_vals[] =
523 { 0, "Data length is < 128 bytes"},
524 { 1, "Data length is >= 128 bytes"},
525 { 0, NULL }
529 static const value_string rar_type_vals[] =
531 { 0, "Backoff Indicator present"},
532 { 1, "RAPID present"},
533 { 0, NULL }
537 static const value_string rar_bi_vals[] =
539 { 0, "0"},
540 { 1, "10"},
541 { 2, "20"},
542 { 3, "30"},
543 { 4, "40"},
544 { 5, "60"},
545 { 6, "80"},
546 { 7, "120"},
547 { 8, "160"},
548 { 9, "240"},
549 { 10, "320"},
550 { 11, "480"},
551 { 12, "960"},
552 { 0, NULL }
556 static const value_string buffer_size_vals[] =
558 { 0, "BS = 0"},
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"},
622 { 0, NULL }
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[] =
628 { 0, "BS = 0"},
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"},
692 { 0, NULL }
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"},
761 { 63, "PH >= 40"},
762 { 0, NULL }
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"},
832 { 0, NULL }
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"},
840 { 0, NULL }
843 static const value_string predefined_frame_vals[] =
845 { 0, "Real MAC PDU present - will dissect"},
846 { 1, "Predefined frame present - will not dissect"},
847 { 0, NULL }
850 static const value_string ul_retx_grant_vals[] =
852 { 0, "PDCCH ReTx"},
853 { 1, "PHICH NACK"},
854 { 0, NULL }
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 */
893 enum layer_to_show {
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[] = {
915 { 3, "LCID 3"},
916 { 4, "LCID 4"},
917 { 5, "LCID 5"},
918 { 6, "LCID 6"},
919 { 7, "LCID 7"},
920 { 8, "LCID 8"},
921 { 9, "LCID 9"},
922 { 10, "LCID 10"},
923 { 0, NULL }
926 typedef enum rlc_channel_type_t {
927 rlcRaw,
928 rlcTM,
929 rlcUM5,
930 rlcUM10,
931 rlcAM
932 } rlc_channel_type_t;
934 static const value_string rlc_channel_type_vals[] = {
935 { rlcTM, "TM"},
936 { rlcUM5 , "UM, SN Len=5"},
937 { rlcUM10, "UM, SN Len=10"},
938 { rlcAM , "AM"},
939 { 0, NULL }
943 /* Mapping type */
944 typedef struct lcid_drb_mapping_t {
945 guint16 lcid;
946 gint drbid;
947 rlc_channel_type_t channel_type;
948 } lcid_drb_mapping_t;
950 /* Mapping entity */
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")
958 /* UAT object */
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 {
964 gboolean valid;
965 gint drbid;
966 rlc_channel_type_t channel_type;
967 guint8 ul_priority;
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 {
989 guint8 data[6];
990 nstime_t msg3Time;
991 guint32 framenum;
992 } 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)
1002 return (v == v2);
1005 static guint mac_lte_rnti_hash_func(gconstpointer v)
1007 return GPOINTER_TO_UINT(v);
1011 typedef enum ContentionResolutionStatus {
1012 NoMsg3,
1013 Msg3Match,
1014 Msg3NoMatch
1015 } ContentionResolutionStatus;
1017 typedef struct ContentionResolutionResult {
1018 ContentionResolutionStatus status;
1019 guint msg3FrameNum;
1020 guint msSinceMsg3;
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)
1031 return (v == 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 */
1047 /* being logged! */
1049 /* Could be bigger, but more than enough to flag suspected resends */
1050 #define MAX_EXPECTED_PDU_LENGTH 2048
1052 typedef struct LastFrameData {
1053 gboolean inUse;
1054 guint32 framenum;
1055 gboolean ndi;
1056 nstime_t received_time;
1057 gint length;
1058 guint8 data[MAX_EXPECTED_PDU_LENGTH];
1059 } LastFrameData;
1061 typedef struct DLHarqBuffers {
1062 LastFrameData harqid[2][15]; /* 2 blocks (1 for each antenna) needed for DL */
1063 } DLHarqBuffers;
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;
1074 guint nextFrameNum;
1075 guint timeToNextFrame;
1076 } DLHARQResult;
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];
1092 } ULHarqBuffers;
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;
1103 guint nextFrameNum;
1104 guint timeToNextFrame;
1105 } ULHARQResult;
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 {
1123 SR_Grant,
1124 SR_Request,
1125 SR_Failure
1126 } SREvent;
1128 static const value_string sr_event_vals[] =
1130 { SR_Grant, "Grant"},
1131 { SR_Request, "SR Request"},
1132 { SR_Failure, "SR Failure"},
1133 { 0, NULL}
1136 typedef enum SRStatus {
1137 None,
1138 SR_Outstanding,
1139 SR_Failed
1140 } 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"},
1147 { 0, NULL}
1151 typedef struct SRState {
1152 SRStatus status;
1153 guint32 lastSRFramenum;
1154 guint32 lastGrantFramenum;
1155 nstime_t requestTime;
1156 } SRState;
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 {
1165 GrantAnsweringSR,
1166 FailureAnsweringSR,
1167 SRLeadingToGrant,
1168 SRLeadingToFailure,
1169 InvalidSREvent
1170 } SRResultType;
1173 typedef struct SRResult {
1174 SRResultType type;
1175 guint32 frameNum;
1176 guint32 timeDifference;
1178 /* These 2 are only used with InvalidSREvent */
1179 SRStatus status;
1180 SREvent event;
1181 } SRResult;
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 /**************************************************************************/
1192 /* DRX State */
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;
1209 /* Timers */
1210 nstime_t currentTime; /* absolute time of last PDU */
1211 guint16 currentSFN;
1212 guint16 currentSF;
1214 gboolean inOnDuration;
1215 guint64 onDurationTimer;
1216 guint64 inactivityTimer;
1217 guint64 RTT[8];
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;
1229 } drx_state_t;
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)
1239 int i;
1240 drx_state->state_before.inShortCycle = FALSE;
1241 if (at_init) {
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,
1255 drx_rtt_timer,
1256 drx_retx_timer,
1257 drx_short_cycle_timer
1258 } drx_timer_type_t;
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);
1267 guint64 *pTimer;
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;
1275 break;
1276 case drx_inactivity_timer:
1277 pTimer = &(p_state->state_before.inactivityTimer);
1278 timerLength = p_state->config.inactivityTimer;
1279 break;
1280 case drx_rtt_timer:
1281 pTimer = &(p_state->state_before.RTT[timer_id]);
1282 timerLength = 8;
1283 break;
1284 case drx_retx_timer:
1285 pTimer = &(p_state->state_before.retransmissionTimer[timer_id]);
1286 timerLength = p_state->config.retransmissionTimer;
1287 break;
1288 case drx_short_cycle_timer:
1289 default:
1290 pTimer = &(p_state->state_before.shortCycleTimer);
1291 timerLength = p_state->config.shortCycle * p_state->config.shortCycleTimer;
1292 break;
1295 /* Set timer */
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);
1306 break;
1307 case drx_inactivity_timer:
1308 p_state->state_before.inactivityTimer = G_GUINT64_CONSTANT(0);
1309 break;
1310 case drx_rtt_timer:
1311 p_state->state_before.RTT[timer_id] = G_GUINT64_CONSTANT(0);
1312 break;
1313 case drx_retx_timer:
1314 p_state->state_before.retransmissionTimer[timer_id] = G_GUINT64_CONSTANT(0);
1315 break;
1316 case drx_short_cycle_timer:
1317 p_state->state_before.shortCycleTimer = G_GUINT64_CONSTANT(0);
1318 break;
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;
1331 if (before_event) {
1332 state_to_use = &p_state->state_before;
1334 else {
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);
1347 break;
1348 case drx_inactivity_timer:
1349 pTimer = &(state_to_use->inactivityTimer);
1350 break;
1351 case drx_rtt_timer:
1352 pTimer = &(state_to_use->RTT[timer_id]);
1353 break;
1354 case drx_retx_timer:
1355 pTimer = &(state_to_use->retransmissionTimer[timer_id]);
1356 break;
1357 case drx_short_cycle_timer:
1358 pTimer = &(state_to_use->shortCycleTimer);
1359 break;
1361 default:
1362 return FALSE;
1365 /* TODO: verify using SFN/SF ? */
1366 if (currentTime >= *pTimer) {
1367 return TRUE;
1369 else {
1370 *time_until_expires = *pTimer - currentTime;
1371 return FALSE;
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));
1407 /* Start timer */
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));
1420 /* Start timers */
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)
1432 int harq_id;
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);
1452 else {
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;
1485 else {
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;
1523 else {
1524 ue_state->state_before.currentSFN++;
1527 else {
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 */
1549 if (before_event) {
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);
1559 else {
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;
1578 guint n;
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 */
1590 if (before_event) {
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);
1611 /* Config fields */
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,
1650 tvb, 0, 0, "",
1651 (before_event) ? "DRX State Before" : "DRX State After");
1652 /* Get appropriate state pointer to use below */
1653 if (before_event) {
1654 state_to_show = &frame_state->state_before;
1656 else {
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");
1681 else {
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,
1758 guint8 direction);
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) */
1767 TRY {
1768 call_dissector_only(handle, tvb, pinfo, tree, NULL);
1770 CATCH_ALL {
1772 ENDTRY
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,
1778 gint *p_offset)
1780 gint offset = *p_offset;
1781 guint8 tag = 0;
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;
1791 else {
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) {
1799 case M_RNTI:
1800 p_mac_lte_info->rnti = 0xFFFD;
1801 break;
1802 case P_RNTI:
1803 p_mac_lte_info->rnti = 0xFFFE;
1804 break;
1805 case SI_RNTI:
1806 p_mac_lte_info->rnti = 0xFFFF;
1807 break;
1808 case RA_RNTI:
1809 case C_RNTI:
1810 case SPS_RNTI:
1811 p_mac_lte_info->rnti = 0x0001;
1812 break;
1813 default:
1814 break;
1817 /* Read optional fields */
1818 while (tag != MAC_LTE_PAYLOAD_TAG) {
1819 /* Process next tag */
1820 tag = tvb_get_guint8(tvb, offset++);
1821 switch (tag) {
1822 case MAC_LTE_RNTI_TAG:
1823 p_mac_lte_info->rnti = tvb_get_ntohs(tvb, offset);
1824 offset += 2;
1825 break;
1826 case MAC_LTE_UEID_TAG:
1827 p_mac_lte_info->ueid = tvb_get_ntohs(tvb, offset);
1828 offset += 2;
1829 break;
1830 case MAC_LTE_SUBFRAME_TAG:
1831 p_mac_lte_info->subframeNumber = tvb_get_ntohs(tvb, offset);
1832 offset += 2;
1833 break;
1834 case MAC_LTE_PREDEFINED_DATA_TAG:
1835 p_mac_lte_info->isPredefinedData = tvb_get_guint8(tvb, offset);
1836 offset++;
1837 break;
1838 case MAC_LTE_RETX_TAG:
1839 p_mac_lte_info->reTxCount = tvb_get_guint8(tvb, offset);
1840 offset++;
1841 break;
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);
1846 offset++;
1847 break;
1848 case MAC_LTE_EXT_BSR_SIZES_TAG:
1849 p_mac_lte_info->isExtendedBSRSizes = TRUE;
1850 break;
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);
1856 continue;
1858 default:
1859 /* It must be a recognised tag */
1860 return FALSE;
1864 /* Pass out where offset is now */
1865 *p_offset = offset;
1867 return TRUE;
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_)
1874 gint offset = 0;
1875 struct mac_lte_info *p_mac_lte_info;
1876 tvbuff_t *mac_tvb;
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) {
1885 return FALSE;
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
1893 - tag for data
1894 - at least one byte of MAC PDU payload */
1895 if (tvb_length_remaining(tvb, offset) < (gint)(strlen(MAC_LTE_START_STRING)+3+2)) {
1896 return FALSE;
1899 /* OK, compare with signature string */
1900 if (tvb_strneql(tvb, offset, MAC_LTE_START_STRING, strlen(MAC_LTE_START_STRING)) != 0) {
1901 return FALSE;
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;
1912 else {
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)) {
1918 return FALSE;
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);
1934 return TRUE;
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];
1947 va_list ap;
1949 if ((ti1 == NULL) && (ti2 == NULL) && (pinfo == NULL)) {
1950 return;
1953 va_start(ap, format);
1954 g_vsnprintf(info_buffer, MAX_INFO_BUFFER, format, ap);
1955 va_end(ap);
1957 /* Add to indicated places */
1958 if (pinfo != NULL) {
1959 col_append_str(pinfo->cinfo, COL_INFO, info_buffer);
1961 if (ti1 != NULL) {
1962 proto_item_append_text(ti1, "%s", info_buffer);
1964 if (ti2 != NULL) {
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)) {
1974 return;
1977 /* Add to indicated places */
1978 if (pinfo != NULL) {
1979 col_append_str(pinfo->cinfo, COL_INFO, info_buffer);
1981 if (ti1 != NULL) {
1982 proto_item_append_text(ti1, "%s", info_buffer);
1984 if (ti2 != NULL) {
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)
1995 proto_item *phy_ti;
1996 proto_tree *phy_tree;
1997 proto_item *ti;
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) {
2007 /* Create root */
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);
2013 /* Add items */
2014 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_modulation_type,
2015 tvb, 0, 0,
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,
2020 tvb, 0, 0,
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,
2025 tvb, 0, 0,
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,
2030 tvb, 0, 0,
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,
2035 tvb, 0, 0,
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,
2040 tvb, 0, 0,
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);
2066 else {
2067 if (p_mac_lte_info->detailed_phy_info.dl_info.present) {
2069 /* Create root */
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);
2075 /* Add items */
2076 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_dci_format,
2077 tvb, 0, 0,
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,
2082 tvb, 0, 0,
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,
2087 tvb, 0, 0,
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,
2092 tvb, 0, 0,
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,
2097 tvb, 0, 0,
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,
2102 tvb, 0, 0,
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,
2107 tvb, 0, 0,
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,
2112 tvb, 0, 0,
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,
2117 tvb, 0, 0,
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,
2122 tvb, 0, 0,
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,
2127 tvb, 0, 0,
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,
2165 proto_item *pdu_ti,
2166 gint offset, guint8 rapid)
2168 guint8 reserved;
2169 guint start_body_offset = offset;
2170 proto_item *ti;
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;
2176 guint32 ul_grant;
2177 guint16 temp_crnti;
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);
2201 } else {
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);
2206 offset++;
2208 /* UL Grant */
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);
2240 offset += 3;
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);
2245 offset += 2;
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);
2253 return 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;
2266 guint8 extension;
2267 gint n;
2268 proto_tree *rar_headers_tree;
2269 proto_item *ti;
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 */
2291 do {
2292 int start_header_offset = offset;
2293 proto_tree *rar_header_tree;
2294 proto_item *rar_header_ti;
2295 guint8 type_value;
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);
2304 /* Extension */
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);
2308 /* Type */
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 */
2315 guint8 reserved;
2316 proto_item *tii;
2317 proto_item *bi_ti;
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);
2347 else {
2348 /* RAPID case */
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]);
2355 number_of_rars++;
2358 offset++;
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 "));
2373 else {
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,
2396 tvb, offset, 0,
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,
2407 proto_item *pdu_ti,
2408 int offset, mac_lte_info *p_mac_lte_info)
2410 proto_item *ti;
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,
2417 "Unknown"));
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 */
2427 /* Raw 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");
2440 else {
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)
2461 proto_item *ti;
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) {
2504 /* Uplink */
2505 switch (lcid) {
2506 case POWER_HEADROOM_REPORT_LCID:
2507 case CRNTI_LCID:
2508 case TRUNCATED_BSR_LCID:
2509 case SHORT_BSR_LCID:
2510 case LONG_BSR_LCID:
2511 return TRUE;
2513 default:
2514 return FALSE;
2517 else {
2518 /* Assume Downlink */
2519 switch (lcid) {
2520 case ACTIVATION_DEACTIVATION_LCID:
2521 case UE_CONTENTION_RESOLUTION_IDENTITY_LCID:
2522 case TIMING_ADVANCE_LCID:
2523 case DRX_COMMAND_LCID:
2524 return TRUE;
2526 default:
2527 return FALSE;
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,
2544 proto_item *pdu_ti,
2545 int offset, guint16 data_length,
2546 guint8 mode, guint8 direction, guint16 ueid,
2547 guint16 channelType, guint16 channelId,
2548 guint8 UMSequenceNumberLength,
2549 guint8 priority)
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);
2577 else {
2578 /* Clear info column before first RLC PDU */
2579 if (s_number_of_rlc_pdus_shown == 0) {
2580 col_clear(pinfo->cinfo, COL_INFO);
2582 else {
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) {
2607 return;
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)) {
2625 return;
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;
2673 else {
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;
2688 else {
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) {
2698 proto_item *gap_ti;
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) {
2709 proto_item *gap_ti;
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) {
2729 return FALSE;
2732 if (direction == DIRECTION_UPLINK) {
2733 /* For UL, retx count is stored in per-packet struct */
2734 return (p_mac_lte_info->reTxCount > 0);
2736 else {
2737 /* Use answer if told directly */
2738 if (p_mac_lte_info->dl_retx == dl_retx_yes) {
2739 return TRUE;
2741 else {
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) {
2761 return;
2764 /* Give up if harqid is out of range */
2765 if (p_mac_lte_info->detailed_phy_info.ul_info.harq_id >= 8) {
2766 return;
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;
2823 else {
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;
2838 else {
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);
2858 else {
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)
2886 SRResult *result;
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);
2893 return 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;
2903 SRState *state;
2904 SRResult *resultForSRFrame = NULL;
2906 guint16 rnti;
2907 guint16 ueid;
2908 proto_item *ti;
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];
2915 else {
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) {
2939 case None:
2940 switch (event) {
2941 case SR_Grant:
2942 /* Got another grant - fine */
2944 /* update state */
2945 state->lastGrantFramenum = pinfo->fd->num;
2946 break;
2948 case SR_Request:
2949 /* Sent an SR - fine */
2951 /* Update state */
2952 state->status = SR_Outstanding;
2953 state->lastSRFramenum = pinfo->fd->num;
2954 break;
2956 case SR_Failure:
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;
2962 break;
2964 break;
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));
2970 switch (event) {
2971 case SR_Grant:
2972 /* Got grant we were waiting for, so state goes to None */
2974 /* Update state */
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;
2988 break;
2990 case SR_Request:
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;
2996 break;
2998 case SR_Failure:
2999 /* We sent an SR but it failed */
3001 /* Update state */
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;
3015 break;
3017 break;
3019 case SR_Failed:
3020 switch (event) {
3021 case SR_Grant:
3022 /* Got a grant, presumably after a subsequent RACH - fine */
3024 /* Update state */
3025 state->status = None;
3026 break;
3028 case SR_Request:
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;
3037 break;
3039 case SR_Failure:
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;
3045 break;
3047 break;
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",
3059 ueid);
3061 return;
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);
3074 break;
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);
3083 break;
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);
3093 break;
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);
3102 break;
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",
3107 ueid,
3108 val_to_str_const(result->status, sr_status_vals, "Unknown"),
3109 val_to_str_const(result->event, sr_event_vals, "Unknown"));
3110 break;
3115 /********************************************************/
3116 /* Count number of UEs/TTI (in both directions) */
3117 /********************************************************/
3119 /* For keeping track during first pass */
3120 typedef struct tti_info_t {
3121 guint16 subframe;
3122 nstime_t ttiStartTime;
3123 guint ues_in_tti;
3124 } tti_info_t;
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 {
3131 guint ues_in_tti;
3132 } 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;
3155 else {
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) {
3171 same_tti = TRUE;
3175 /* Update global state */
3176 if (!same_tti) {
3177 tti_info->subframe = p_mac_lte_info->subframeNumber;
3178 tti_info->ttiStartTime = pinfo->fd->abs_ts;
3179 tti_info->ues_in_tti = 1;
3181 else {
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,
3214 guint8 lcid,
3215 rlc_channel_type_t *rlc_channel_type,
3216 guint8 *UM_seqnum_length,
3217 gint *drb_id)
3219 /* Zero params (in case no match is found) */
3220 *rlc_channel_type = rlcRaw;
3221 *UM_seqnum_length = 0;
3222 *drb_id = 0;
3224 if (global_mac_lte_lcid_drb_source == (int)FromStaticTable) {
3226 /* Look up in static (UAT) table */
3227 guint m;
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) {
3235 case rlcUM5:
3236 *UM_seqnum_length = 5;
3237 break;
3238 case rlcUM10:
3239 *UM_seqnum_length = 10;
3240 break;
3241 default:
3242 break;
3245 /* Set drb_id */
3246 *drb_id = lcid_drb_mappings[m].drbid;
3247 break;
3251 else {
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));
3254 if (!ue_mappings) {
3255 return;
3258 /* Look up setting gleaned from configuration protocol */
3259 if (!ue_mappings->mapping[lcid].valid) {
3260 return;
3263 *rlc_channel_type = ue_mappings->mapping[lcid].channel_type;
3265 /* Set UM_seqnum_length */
3266 switch (*rlc_channel_type) {
3267 case rlcUM5:
3268 *UM_seqnum_length = 5;
3269 break;
3270 case rlcUM10:
3271 *UM_seqnum_length = 10;
3272 break;
3273 default:
3274 break;
3277 /* Set drb_id */
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
3287 function */
3288 static void dissect_ulsch_or_dlsch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
3289 proto_item *pdu_ti,
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)
3295 guint8 extension;
3296 volatile guint16 n;
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);
3350 else {
3351 /* Downlink */
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) ?
3378 hf_mac_lte_ulsch :
3379 hf_mac_lte_dlsch,
3380 tvb, offset, 0,
3382 "Hidden header");
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,
3390 tvb, offset, 0,
3392 "MAC PDU 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. */
3401 do {
3402 guint8 reserved;
3403 guint64 length = 0;
3404 proto_item *pdu_subheader_ti;
3405 proto_tree *pdu_subheader_tree;
3406 proto_item *lcid_ti;
3407 proto_item *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,
3415 tvb, offset, 1,
3417 "Sub-header");
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');
3431 /* Extended bit */
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,
3443 "(%s",
3444 val_to_str_const(lcids[number_of_headers],
3445 ulsch_lcid_vals, "(Unknown LCID)"));
3447 else {
3448 /* Downlink */
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,
3452 "(%s",
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);
3462 offset++;
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');
3477 return;
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);
3484 return;
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) &&
3492 extension)
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
3505 at the start! */
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
3521 control element */
3522 if (!extension) {
3523 /* Last one... */
3524 if (is_fixed_sized_control_element(lcids[number_of_headers], direction)) {
3525 pdu_lengths[number_of_headers] = 0;
3527 else {
3528 pdu_lengths[number_of_headers] = -1;
3531 else {
3532 /* Not the last one */
3533 if (!is_fixed_sized_control_element(lcids[number_of_headers], direction) &&
3534 (lcids[number_of_headers] != PADDING_LCID)) {
3536 guint8 format;
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 */
3544 if (format) {
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);
3549 offset += 2;
3551 else {
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);
3555 offset++;
3557 pdu_lengths[number_of_headers] = (gint16)length;
3559 else {
3560 pdu_lengths[number_of_headers] = 0;
3565 /* Close off description in info column */
3566 switch (pdu_lengths[number_of_headers]) {
3567 case 0:
3568 write_pdu_label_and_info_literal(pdu_ti, NULL, pinfo, ") ");
3569 break;
3570 case -1:
3571 write_pdu_label_and_info_literal(pdu_ti, NULL, pinfo, ":remainder) ");
3572 break;
3573 default:
3574 write_pdu_label_and_info(pdu_ti, NULL, pinfo, ":%u bytes) ",
3575 pdu_lengths[number_of_headers]);
3576 break;
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) ?
3583 ulsch_lcid_vals :
3584 dlsch_lcid_vals,
3585 "Unknown"));
3587 switch (pdu_lengths[number_of_headers]) {
3588 case -1:
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,
3593 "Unknown"));
3594 break;
3595 case 0:
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,
3600 "Unknown"));
3601 break;
3602 default:
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,
3608 "Unknown"),
3609 pdu_lengths[number_of_headers]);
3610 break;
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);
3634 return;
3638 /* Append summary to overall PDU header root */
3639 proto_item_append_text(pdu_header_ti, " [%u subheaders]",
3640 number_of_headers);
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]]++;
3666 break;
3669 /* Process what should be a valid control PDU type */
3670 if (direction == DIRECTION_DOWNLINK) {
3672 /****************************/
3673 /* DL-SCH Control PDUs */
3674 switch (lcids[n]) {
3675 case ACTIVATION_DEACTIVATION_LCID:
3677 proto_item *ad_ti;
3678 proto_tree *ad_tree;
3679 proto_item *ti;
3680 guint8 reserved;
3682 /* Create AD root */
3683 ad_ti = proto_tree_add_string_format(tree,
3684 hf_mac_lte_control_activation_deactivation,
3685 tvb, offset, 1,
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");
3711 offset++;
3713 break;
3714 case UE_CONTENTION_RESOLUTION_IDENTITY_LCID:
3716 proto_item *cr_ti;
3717 proto_tree *cr_tree;
3718 proto_item *ti;
3719 ContentionResolutionResult *crResult;
3721 /* Create CR root */
3722 cr_ti = proto_tree_add_string_format(tree,
3723 hf_mac_lte_control_ue_contention_resolution,
3724 tvb, offset, 6,
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 */
3745 Msg3Data *msg3Data;
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);
3752 /* Look for Msg3 */
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;
3765 else {
3766 crResult->status = Msg3NoMatch;
3769 else {
3770 crResult->status = NoMsg3;
3774 /* Now show CR result in tree */
3775 switch (crResult->status) {
3776 case NoMsg3:
3777 proto_item_append_text(cr_ti, " (no corresponding Msg3 found!)");
3778 break;
3780 case Msg3Match:
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,
3789 tvb, 0, 0, TRUE);
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);
3793 break;
3795 case Msg3NoMatch:
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,
3804 tvb, 0, 0, FALSE);
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);
3811 break;
3814 offset += 6;
3816 break;
3817 case TIMING_ADVANCE_LCID:
3819 proto_item *ta_ti;
3820 proto_item *ta_value_ti;
3821 proto_tree *ta_tree;
3822 guint8 ta_value;
3824 /* Create TA root */
3825 ta_ti = proto_tree_add_string_format(tree,
3826 hf_mac_lte_control_timing_advance,
3827 tvb, offset, 1,
3829 "Timing Advance");
3830 ta_tree = proto_item_add_subtree(ta_ti, ett_mac_lte_timing_advance);
3832 /* TAG Id */
3833 proto_tree_add_item(ta_tree, hf_mac_lte_control_timing_advance_group_id,
3834 tvb, offset, 1, ENC_BIG_ENDIAN);
3836 /* TA value */
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);
3844 else {
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",
3847 ta_value,
3848 (ta_value < 31) ? "-ve" : "+ve");
3850 offset++;
3852 break;
3853 case DRX_COMMAND_LCID:
3854 /* No payload */
3855 mac_lte_drx_control_element_received(p_mac_lte_info->ueid);
3856 break;
3857 case PADDING_LCID:
3858 /* No payload (in this position) */
3859 tap_info->padding_bytes++;
3860 break;
3862 default:
3863 break;
3866 else {
3868 /**********************************/
3869 /* UL-SCH Control PDUs */
3870 switch (lcids[n]) {
3871 case EXTENDED_POWER_HEADROOM_REPORT_LCID:
3873 proto_item *ephr_ti;
3874 proto_tree *ephr_tree;
3875 proto_item *ti;
3876 proto_tree *ephr_cell_tree;
3877 proto_item *ephr_cell_ti;
3878 guint8 scell_bitmap;
3879 guint8 scell_count;
3880 guint8 byte;
3881 guint i;
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");
3920 curr_offset++;
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)) {
3926 scell_count++;
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];
3949 break;
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"));
3962 curr_offset++;
3963 if (byte & 0x80) {
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);
3969 if (byte & 0xc0) {
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"));
3978 curr_offset++;
3980 } else {
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];
3986 break;
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"));
4002 curr_offset++;
4003 if (byte & 0x80) {
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);
4009 if (byte & 0xc0) {
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"));
4018 curr_offset++;
4022 offset += pdu_lengths[n];
4024 break;
4025 case POWER_HEADROOM_REPORT_LCID:
4027 proto_item *phr_ti;
4028 proto_tree *phr_tree;
4029 proto_item *ti;
4030 guint8 reserved;
4031 guint8 level;
4033 /* Create PHR root */
4034 phr_ti = proto_tree_add_string_format(tree,
4035 hf_mac_lte_control_power_headroom,
4036 tvb, offset, 1,
4038 "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);
4050 /* Level */
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"));
4058 offset++;
4062 break;
4063 case CRNTI_LCID:
4064 proto_tree_add_item(tree, hf_mac_lte_control_crnti,
4065 tvb, offset, 2, ENC_BIG_ENDIAN);
4066 offset += 2;
4067 break;
4068 case TRUNCATED_BSR_LCID:
4069 case SHORT_BSR_LCID:
4071 proto_tree *bsr_tree;
4072 proto_item *bsr_ti;
4073 proto_item *buffer_size_ti;
4074 guint8 lcgid;
4075 guint8 buffer_size;
4076 int hfindex;
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;
4082 } else {
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,
4089 tvb, offset, 1,
4091 "Short BSR");
4092 bsr_tree = proto_item_add_subtree(bsr_ti, ett_mac_lte_bsr);
4094 /* LCG ID */
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);
4098 /* Buffer Size */
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);
4102 offset++;
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,
4107 lcgid,
4108 buffer_size,
4109 val_to_str_ext_const(buffer_size, p_vs_ext, "Unknown"));
4113 proto_item_append_text(bsr_ti, " (lcgid=%u %s)",
4114 lcgid,
4115 val_to_str_ext_const(buffer_size, &buffer_size_vals_ext, "Unknown"));
4117 break;
4118 case LONG_BSR_LCID:
4120 proto_tree *bsr_tree;
4121 proto_item *bsr_ti;
4122 proto_item *buffer_size_ti;
4123 guint8 buffer_size[4];
4124 int hfindex[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;
4133 } else {
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,
4143 tvb, offset, 3,
4145 "Long BSR");
4146 bsr_tree = proto_item_add_subtree(bsr_ti, ett_mac_lte_bsr);
4148 /* LCID Group 0 */
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,
4156 buffer_size[0],
4157 val_to_str_ext_const(buffer_size[0], p_vs_ext, "Unknown"));
4160 /* LCID Group 1 */
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);
4164 offset++;
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,
4169 buffer_size[1],
4170 val_to_str_ext_const(buffer_size[1], p_vs_ext, "Unknown"));
4173 /* LCID Group 2 */
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);
4178 offset++;
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,
4183 buffer_size[2],
4184 val_to_str_ext_const(buffer_size[2], p_vs_ext, "Unknown"));
4187 /* LCID Group 3 */
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;
4191 offset++;
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,
4196 buffer_size[3],
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"));
4207 break;
4208 case PADDING_LCID:
4209 /* No payload, in this position */
4210 tap_info->padding_bytes++;
4211 break;
4213 default:
4214 break;
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,
4222 is_truncated);
4223 if (is_truncated) {
4224 PROTO_ITEM_SET_GENERATED(truncated_ti);
4225 expert_add_info(pinfo, truncated_ti, &ei_mac_lte_sch_header_only);
4226 return;
4228 else {
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 */
4237 proto_item *sdu_ti;
4238 const guint8 *pdu_data;
4239 volatile guint16 data_length;
4240 int i;
4241 char buff[64];
4242 gboolean rlc_called_for_sdu = FALSE;
4244 /* Break out if meet padding */
4245 if (lcids[n] == PADDING_LCID) {
4246 break;
4249 /* Work out length */
4250 data_length = (pdu_lengths[n] == -1) ?
4251 tvb_length_remaining(tvb, offset) :
4252 pdu_lengths[n];
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) ?
4259 ulsch_lcid_vals :
4260 dlsch_lcid_vals,
4261 "Unknown"),
4262 data_length);
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 */
4272 if (data == NULL) {
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");
4294 else {
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;
4326 gint drb_id;
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,
4331 lcids[n],
4332 &rlc_channel_type,
4333 &UM_seqnum_length,
4334 &drb_id);
4336 /* Dissect according to channel type */
4337 switch (rlc_channel_type) {
4338 case rlcUM5:
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,
4342 priority);
4343 break;
4344 case rlcUM10:
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,
4348 priority);
4349 break;
4350 case rlcAM:
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,
4354 priority);
4355 break;
4356 case rlcTM:
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,
4360 priority);
4361 break;
4362 case rlcRaw:
4363 /* Nothing to do! */
4364 break;
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]);
4380 if (i >= 30) {
4381 g_snprintf(buff+(i*2), 4, "...");
4382 break;
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,
4402 tvb, offset, 0,
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);
4417 else {
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)
4451 guint8 extension;
4452 volatile guint16 n;
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,
4480 tvb, offset, 0,
4482 "MAC PDU Header");
4483 pdu_header_tree = proto_item_add_subtree(pdu_header_ti, ett_mac_lte_mch_header);
4486 /************************************************************************/
4487 /* Dissect each sub-header. */
4488 do {
4489 guint8 reserved;
4490 guint64 length = 0;
4491 proto_item *pdu_subheader_ti;
4492 proto_tree *pdu_subheader_tree;
4493 proto_item *lcid_ti;
4494 proto_item *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,
4502 tvb, offset, 1,
4504 "Sub-header");
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");
4517 /* Extended bit */
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);
4522 /* LCID */
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,
4530 "(%s",
4531 val_to_str_const(lcids[number_of_headers],
4532 mch_lcid_vals, "(Unknown LCID)"));
4533 offset++;
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");
4547 return;
4550 /* Should not see padding after non-padding control... */
4551 if ((lcids[number_of_headers] > 28) &&
4552 (lcids[number_of_headers] == PADDING_LCID) &&
4553 extension)
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
4575 control element */
4576 if (!extension) {
4577 /* Last one... */
4578 pdu_lengths[number_of_headers] = -1;
4580 else {
4581 /* Not the last one */
4582 if (lcids[number_of_headers] != PADDING_LCID) {
4584 guint8 format;
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 */
4592 if (format) {
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);
4597 offset += 2;
4599 else {
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);
4603 offset++;
4605 pdu_lengths[number_of_headers] = (gint16)length;
4607 else {
4608 pdu_lengths[number_of_headers] = 0;
4613 /* Close off description in info column */
4614 switch (pdu_lengths[number_of_headers]) {
4615 case 0:
4616 write_pdu_label_and_info_literal(pdu_ti, NULL, pinfo, ") ");
4617 break;
4618 case -1:
4619 write_pdu_label_and_info_literal(pdu_ti, NULL, pinfo, ":remainder) ");
4620 break;
4621 default:
4622 write_pdu_label_and_info(pdu_ti, NULL, pinfo, ":%u bytes) ",
4623 pdu_lengths[number_of_headers]);
4624 break;
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]) {
4633 case -1:
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],
4637 mch_lcid_vals,
4638 "Unknown"));
4639 break;
4640 case 0:
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],
4644 mch_lcid_vals,
4645 "Unknown"));
4646 break;
4647 default:
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],
4652 mch_lcid_vals,
4653 "Unknown"),
4654 pdu_lengths[number_of_headers]);
4655 break;
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);
4677 return;
4681 /* Append summary to overall PDU header root */
4682 proto_item_append_text(pdu_header_ti, " (%u subheaders)",
4683 number_of_headers);
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) {
4698 break;
4701 /* Process what should be a valid control PDU type */
4702 switch (lcids[n]) {
4703 case MCH_SCHEDULING_INFO_LCID:
4705 guint32 curr_offset = offset;
4706 gint16 i;
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)");
4739 curr_offset += 2;
4742 offset += pdu_lengths[n];
4744 break;
4745 case PADDING_LCID:
4746 /* No payload (in this position) */
4747 break;
4749 default:
4750 break;
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,
4758 is_truncated);
4759 if (is_truncated) {
4760 PROTO_ITEM_SET_GENERATED(truncated_ti);
4761 expert_add_info(pinfo, truncated_ti, &ei_mac_lte_sch_header_only);
4762 return;
4764 else {
4765 PROTO_ITEM_SET_HIDDEN(truncated_ti);
4769 /* Now process remaining bodies, which should all be data */
4770 for (; n < number_of_headers; n++) {
4772 proto_item *sdu_ti;
4773 const guint8 *pdu_data;
4774 volatile guint16 data_length;
4775 int i;
4776 char buff[64];
4778 /* Break out if meet padding */
4779 if (lcids[n] == PADDING_LCID) {
4780 break;
4783 /* Work out length */
4784 data_length = (pdu_lengths[n] == -1) ?
4785 tvb_length_remaining(tvb, offset) :
4786 pdu_lengths[n];
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);
4798 } else {
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"),
4803 data_length);
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]);
4809 if (i >= 30) {
4810 g_snprintf(buff+(i*2), 4, "...");
4811 break;
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,
4827 tvb, offset, 0,
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);
4838 else {
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;
4862 proto_item *pdu_ti;
4863 proto_tree *context_tree;
4864 proto_item *context_ti;
4865 proto_item *retx_ti = NULL;
4866 proto_item *ti;
4867 gint offset = 0;
4868 struct mac_lte_info *p_mac_lte_info;
4869 gint n;
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) {
4887 proto_item *tii =
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);
4891 return;
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);
4942 /* Info column */
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);
4954 break;
4955 case ltemac_send_sr:
4956 /* Count of SRs */
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++) {
4963 proto_item *sr_ti;
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,
4968 tvb, 0, 0,
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);
4973 /* RNTI */
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);
4978 /* UEID */
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]);
4988 /* Info column */
4989 if (n == 0) {
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]);
4996 else {
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);
5008 break;
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);
5019 /* Info column */
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);
5030 break;
5033 /* Our work here is done */
5034 return;
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) {
5078 case M_RNTI:
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);
5083 return;
5085 break;
5086 case P_RNTI:
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);
5091 return;
5093 break;
5094 case SI_RNTI:
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);
5099 return;
5101 break;
5102 case RA_RNTI:
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);
5107 return;
5109 break;
5110 case C_RNTI:
5111 case SPS_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);
5117 return;
5119 break;
5121 default:
5122 break;
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);
5130 else {
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) {
5163 /* Set status */
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,
5174 crc_status_vals,
5175 "Unknown"));
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,
5180 crc_status_vals,
5181 "Unknown"),
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);
5189 /* Carrier Id */
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) ?
5219 " - truncated" :
5220 ""));
5222 /* Queue tap info */
5223 if (!pinfo->flags.in_error_pkt) {
5224 tap_queue_packet(mac_lte_tap, pinfo, tap_info);
5227 return;
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));
5238 /* Queue tap info.
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);
5244 return;
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) {
5253 case P_RNTI:
5254 /* PCH PDU */
5255 dissect_pch(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info->direction, tap_info);
5256 break;
5258 case RA_RNTI:
5259 /* RAR PDU */
5260 dissect_rar(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info, tap_info);
5261 break;
5263 case C_RNTI:
5264 case SPS_RNTI:
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);
5269 break;
5271 case SI_RNTI:
5272 /* BCH over DL-SCH */
5273 dissect_bch(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info);
5274 break;
5276 case M_RNTI:
5277 /* MCH PDU */
5278 dissect_mch(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info);
5279 break;
5281 case NO_RNTI:
5282 /* Must be BCH over BCH... */
5283 dissect_bch(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info);
5284 break;
5287 default:
5288 break;
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);
5342 /* Reset structs */
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 */
5376 d->lcid = o->lcid;
5377 d->drbid = o->drbid;
5378 d->channel_type = o->channel_type;
5380 return d;
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;
5391 guint8 lcid = 0;
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)) {
5399 return;
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));
5406 if (!ue_mappings) {
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),
5411 ue_mappings);
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];
5418 if (lcid == 0) {
5419 /* Still no lcid - give up */
5420 return;
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) {
5434 case RLC_AM_MODE:
5435 ue_mappings->mapping[lcid].channel_type = rlcAM;
5436 break;
5437 case RLC_UM_MODE:
5438 if (drb_mapping->um_sn_length_present) {
5439 if (drb_mapping->um_sn_length == 5) {
5440 ue_mappings->mapping[lcid].channel_type = rlcUM5;
5442 else {
5443 ue_mappings->mapping[lcid].channel_type = rlcUM10;
5445 break;
5448 default:
5449 break;
5454 /* Return the configured UL priority for the channel */
5455 static guint8 get_mac_lte_channel_priority(guint16 ueid, guint8 lcid,
5456 guint8 direction)
5458 ue_dynamic_drb_mappings_t *ue_mappings;
5460 /* Priority only affects UL */
5461 if (direction == DIRECTION_DOWNLINK) {
5462 return 0;
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));
5467 if (!ue_mappings) {
5468 return 0;
5471 /* Won't report value if channel not configured */
5472 if (!ue_mappings->mapping[lcid].valid) {
5473 return 0;
5475 else {
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;*/
5502 else {
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,
5553 { "Context",
5554 "mac-lte.context", FT_STRING, BASE_NONE, NULL, 0x0,
5555 NULL, HFILL
5558 { &hf_mac_lte_context_radio_type,
5559 { "Radio Type",
5560 "mac-lte.radio-type", FT_UINT8, BASE_DEC, VALS(radio_type_vals), 0x0,
5561 NULL, HFILL
5564 { &hf_mac_lte_context_direction,
5565 { "Direction",
5566 "mac-lte.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
5567 "Direction of message", HFILL
5570 { &hf_mac_lte_context_rnti,
5571 { "RNTI",
5572 "mac-lte.rnti", FT_UINT16, BASE_DEC, 0, 0x0,
5573 "RNTI associated with message", HFILL
5576 { &hf_mac_lte_context_rnti_type,
5577 { "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,
5583 { "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,
5595 { "Subframe",
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,
5601 { "Grant Subframe",
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,
5631 { "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,
5637 { "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,
5643 { "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,
5649 { "Carrier Id",
5650 "mac-lte.carrier-id", FT_UINT8, BASE_DEC, VALS(carrier_id_vals), 0x0,
5651 NULL, HFILL
5654 { &hf_mac_lte_context_rapid,
5655 { "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,
5663 NULL, HFILL
5667 { &hf_mac_lte_ues_ul_per_tti,
5668 { "UL UE in 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,
5674 { "DL UE in 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,
5685 NULL, HFILL
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,
5691 NULL, HFILL
5694 { &hf_mac_lte_context_phy_ul_tbs_index,
5695 { "TBs Index",
5696 "mac-lte.ul-phy.tbs-index", FT_UINT8, BASE_DEC, 0, 0x0,
5697 NULL, HFILL
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,
5703 NULL, HFILL
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,
5709 NULL, HFILL
5712 { &hf_mac_lte_context_phy_ul_harq_id,
5713 { "HARQ Id",
5714 "mac-lte.ul-phy.harq-id", FT_UINT8, BASE_DEC, 0, 0x0,
5715 NULL, HFILL
5718 { &hf_mac_lte_context_phy_ul_ndi,
5719 { "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,
5728 NULL, HFILL
5731 { &hf_mac_lte_context_phy_dl_dci_format,
5732 { "DCI format",
5733 "mac-lte.dl-phy.dci-format", FT_UINT8, BASE_DEC, VALS(dci_format_vals), 0x0,
5734 NULL, HFILL
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,
5740 NULL, HFILL
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,
5746 NULL, HFILL
5749 { &hf_mac_lte_context_phy_dl_mcs_index,
5750 { "MCS Index",
5751 "mac-lte.dl-phy.mcs-index", FT_UINT8, BASE_DEC, 0, 0x0,
5752 NULL, HFILL
5755 { &hf_mac_lte_context_phy_dl_redundancy_version_index,
5756 { "RV Index",
5757 "mac-lte.dl-phy.rv-index", FT_UINT8, BASE_DEC, 0, 0x0,
5758 NULL, HFILL
5761 { &hf_mac_lte_context_phy_dl_retx,
5762 { "DL Retx",
5763 "mac-lte.dl-phy.dl-retx", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
5764 NULL, HFILL
5767 { &hf_mac_lte_context_phy_dl_resource_block_length,
5768 { "RB Length",
5769 "mac-lte.dl-phy.rb-length", FT_UINT8, BASE_DEC, 0, 0x0,
5770 NULL, HFILL
5773 { &hf_mac_lte_context_phy_dl_crc_status,
5774 { "CRC Status",
5775 "mac-lte.dl-phy.crc-status", FT_UINT8, BASE_DEC, VALS(crc_status_vals), 0x0,
5776 NULL, HFILL
5779 { &hf_mac_lte_context_phy_dl_harq_id,
5780 { "HARQ Id",
5781 "mac-lte.dl-phy.harq-id", FT_UINT8, BASE_DEC, 0, 0x0,
5782 NULL, HFILL
5785 { &hf_mac_lte_context_phy_dl_ndi,
5786 { "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,
5792 { "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,
5800 { "PRACH",
5801 "mac-lte.preamble-sent", FT_STRING, BASE_NONE, NULL, 0x0,
5802 NULL, HFILL
5805 { &hf_mac_lte_number_of_srs,
5806 { "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,
5815 { "UL-SCH",
5816 "mac-lte.ulsch", FT_STRING, BASE_NONE, NULL, 0x0,
5817 NULL, HFILL
5820 { &hf_mac_lte_ulsch_header,
5821 { "UL-SCH Header",
5822 "mac-lte.ulsch.header", FT_STRING, BASE_NONE, NULL, 0x0,
5823 NULL, HFILL
5826 { &hf_mac_lte_dlsch_header,
5827 { "DL-SCH Header",
5828 "mac-lte.dlsch.header", FT_STRING, BASE_NONE, NULL, 0x0,
5829 NULL, HFILL
5832 { &hf_mac_lte_dlsch,
5833 { "DL-SCH",
5834 "mac-lte.dlsch", FT_STRING, BASE_NONE, NULL, 0x0,
5835 NULL, HFILL
5838 { &hf_mac_lte_sch_subheader,
5839 { "SCH sub-header",
5840 "mac-lte.sch.subheader", FT_STRING, BASE_NONE, NULL, 0x0,
5841 NULL, HFILL
5844 { &hf_mac_lte_mch,
5845 { "MCH",
5846 "mac-lte.mch", FT_STRING, BASE_NONE, NULL, 0x0,
5847 NULL, HFILL
5850 { &hf_mac_lte_mch_header,
5851 { "MCH Header",
5852 "mac-lte.mch.header", FT_STRING, BASE_NONE, NULL, 0x0,
5853 NULL, HFILL
5856 { &hf_mac_lte_mch_subheader,
5857 { "MCH sub-header",
5858 "mac-lte.mch.subheader", FT_STRING, BASE_NONE, NULL, 0x0,
5859 NULL, HFILL
5862 { &hf_mac_lte_sch_reserved,
5863 { "SCH reserved bits",
5864 "mac-lte.sch.reserved", FT_UINT8, BASE_HEX, NULL, 0xc0,
5865 NULL, HFILL
5868 { &hf_mac_lte_sch_extended,
5869 { "Extension",
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,
5875 { "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,
5881 { "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,
5887 { "Format",
5888 "mac-lte.sch.format", FT_UINT8, BASE_HEX, VALS(format_vals), 0x80,
5889 NULL, HFILL
5892 { &hf_mac_lte_sch_length,
5893 { "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,
5901 NULL, HFILL
5904 { &hf_mac_lte_mch_extended,
5905 { "Extension",
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,
5911 { "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,
5917 { "Format",
5918 "mac-lte.mch.format", FT_UINT8, BASE_HEX, VALS(format_vals), 0x80,
5919 NULL, HFILL
5922 { &hf_mac_lte_mch_length,
5923 { "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,
5931 NULL, HFILL
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,
5937 NULL, HFILL
5941 /********************************/
5942 /* Data */
5943 { &hf_mac_lte_sch_sdu,
5944 { "SDU",
5945 "mac-lte.sch.sdu", FT_BYTES, BASE_NONE, 0, 0x0,
5946 "Shared channel SDU", HFILL
5949 { &hf_mac_lte_mch_sdu,
5950 { "SDU",
5951 "mac-lte.mch.sdu", FT_BYTES, BASE_NONE, 0, 0x0,
5952 "Multicast channel SDU", HFILL
5955 { &hf_mac_lte_bch_pdu,
5956 { "BCH PDU",
5957 "mac-lte.bch.pdu", FT_BYTES, BASE_NONE, 0, 0x0,
5958 NULL, HFILL
5961 { &hf_mac_lte_pch_pdu,
5962 { "PCH PDU",
5963 "mac-lte.pch.pdu", FT_BYTES, BASE_NONE, 0, 0x0,
5964 NULL, HFILL
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,
5974 { "Raw data",
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,
5980 { "Padding data",
5981 "mac-lte.padding-data", FT_BYTES, BASE_NONE, 0, 0x0,
5982 NULL, HFILL
5985 { &hf_mac_lte_padding_length,
5986 { "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 /*********************************/
5995 /* RAR fields */
5996 { &hf_mac_lte_rar,
5997 { "RAR",
5998 "mac-lte.rar", FT_NONE, BASE_NONE, NULL, 0x0,
5999 NULL, HFILL
6002 { &hf_mac_lte_rar_headers,
6003 { "RAR Headers",
6004 "mac-lte.rar.headers", FT_STRING, BASE_NONE, NULL, 0x0,
6005 NULL, HFILL
6008 { &hf_mac_lte_rar_header,
6009 { "RAR Header",
6010 "mac-lte.rar.header", FT_STRING, BASE_NONE, NULL, 0x0,
6011 NULL, HFILL
6014 { &hf_mac_lte_rar_extension,
6015 { "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,
6021 { "Type",
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,
6027 { "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,
6033 { "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,
6045 { "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,
6052 { "RAR Body",
6053 "mac-lte.rar.body", FT_STRING, BASE_NONE, NULL, 0x0,
6054 NULL, HFILL
6057 { &hf_mac_lte_rar_reserved2,
6058 { "Reserved",
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,
6064 { "Timing Advance",
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,
6070 { "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,
6076 { "Hopping Flag",
6077 "mac-lte.rar.ul-grant.hopping", FT_UINT8, BASE_DEC, 0, 0x08,
6078 NULL, HFILL
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,
6084 NULL, HFILL
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,
6090 NULL, HFILL
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,
6096 NULL, HFILL
6099 { &hf_mac_lte_rar_ul_grant_ul_delay,
6100 { "UL Delay",
6101 "mac-lte.rar.ul-grant.ul-delay", FT_UINT8, BASE_DEC, 0, 0x02,
6102 NULL, HFILL
6105 { &hf_mac_lte_rar_ul_grant_cqi_request,
6106 { "CQI Request",
6107 "mac-lte.rar.ul-grant.cqi-request", FT_UINT8, BASE_DEC, 0, 0x01,
6108 NULL, HFILL
6111 { &hf_mac_lte_rar_temporary_crnti,
6112 { "Temporary C-RNTI",
6113 "mac-lte.rar.temporary-crnti", FT_UINT16, BASE_DEC, 0, 0x0,
6114 NULL, HFILL
6118 /**********************/
6119 /* Control PDU fields */
6120 { &hf_mac_lte_control_bsr,
6121 { "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,
6129 NULL, HFILL
6132 { &hf_mac_lte_control_short_bsr_buffer_size,
6133 { "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,
6139 { "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,
6145 { "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,
6151 { "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,
6157 { "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,
6163 { "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,
6169 { "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,
6175 { "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,
6181 { "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,
6187 { "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,
6193 { "C-RNTI",
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,
6199 { "Timing Advance",
6200 "mac-lte.control.timing-advance", FT_STRING, BASE_NONE, 0, 0x0,
6201 NULL, HFILL
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,
6207 NULL, HFILL
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,
6219 NULL, HFILL
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,
6225 NULL, HFILL
6228 { &hf_mac_lte_control_ue_contention_resolution_msg3,
6229 { "Msg3",
6230 "mac-lte.control.ue-contention-resolution.msg3", FT_FRAMENUM, BASE_NONE, 0, 0x0,
6231 NULL, HFILL
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,
6237 NULL, HFILL
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,
6248 { "Power Headroom",
6249 "mac-lte.control.power-headroom", FT_STRING, BASE_NONE, 0, 0x0,
6250 NULL, HFILL
6253 { &hf_mac_lte_control_power_headroom_reserved,
6254 { "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,
6269 0, 0x0, NULL, HFILL
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,
6315 { "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,
6321 { "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,
6339 { "Reserved",
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,
6354 0, 0x0, NULL, HFILL
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,
6400 { "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,
6409 NULL, HFILL
6412 { &hf_mac_lte_control_mch_scheduling_info_lcid,
6413 { "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,
6419 { "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,
6429 NULL, HFILL
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,
6435 NULL, HFILL
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,
6441 NULL, HFILL
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,
6447 NULL, HFILL
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,
6454 NULL, HFILL
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,
6460 NULL, HFILL
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,
6466 NULL, HFILL
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,
6472 NULL, HFILL
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,
6479 NULL, HFILL
6482 { &hf_mac_lte_failure_answering_sr,
6483 { "SR which failed",
6484 "mac-lte.ulsch.failure-answering-sr", FT_FRAMENUM, BASE_NONE, 0, 0x0,
6485 NULL, HFILL
6488 { &hf_mac_lte_sr_leading_to_failure,
6489 { "This SR fails",
6490 "mac-lte.ulsch.failure-answering-sr-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
6491 NULL, HFILL
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,
6497 NULL, HFILL
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,
6503 NULL, HFILL
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,
6509 NULL, HFILL
6513 { &hf_mac_lte_drx_config,
6514 { "DRX Configuration",
6515 "mac-lte.drx-config", FT_STRING, BASE_NONE,
6516 0, 0x0, NULL, HFILL
6519 { &hf_mac_lte_drx_config_frame_num,
6520 { "Config Frame",
6521 "mac-lte.drx-config.config-frame", FT_FRAMENUM, BASE_NONE,
6522 0, 0x0, NULL, HFILL
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,
6528 0, 0x0, NULL, HFILL
6531 { &hf_mac_lte_drx_config_long_cycle,
6532 { "Long cycle",
6533 "mac-lte.drx-config.long-cycle", FT_UINT16, BASE_DEC,
6534 0, 0x0, NULL, HFILL
6537 { &hf_mac_lte_drx_config_cycle_offset,
6538 { "Cycle offset",
6539 "mac-lte.drx-config.cycle-offset", FT_UINT16, BASE_DEC,
6540 0, 0x0, NULL, HFILL
6543 { &hf_mac_lte_drx_config_onduration_timer,
6544 { "OnDuration Timer",
6545 "mac-lte.drx-config.onduration-timer", FT_UINT16, BASE_DEC,
6546 0, 0x0, NULL, HFILL
6549 { &hf_mac_lte_drx_config_inactivity_timer,
6550 { "Inactivity Timer",
6551 "mac-lte.drx-config.inactivity-timer", FT_UINT16, BASE_DEC,
6552 0, 0x0, NULL, HFILL
6555 { &hf_mac_lte_drx_config_retransmission_timer,
6556 { "Retransmission Timer",
6557 "mac-lte.drx-config.retransmission-timer", FT_UINT16, BASE_DEC,
6558 0, 0x0, NULL, HFILL
6561 { &hf_mac_lte_drx_config_short_cycle,
6562 { "Short cycle",
6563 "mac-lte.drx-config.short-cycle", FT_UINT16, BASE_DEC,
6564 0, 0x0, NULL, HFILL
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,
6570 0, 0x0, NULL, HFILL
6574 { &hf_mac_lte_drx_state,
6575 { "DRX State",
6576 "mac-lte.drx-state", FT_STRING, BASE_NONE,
6577 0, 0x0, NULL, HFILL
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,
6583 0, 0x0, NULL, HFILL
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,
6589 0, 0x0, NULL, HFILL
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,
6595 0, 0x0, NULL, HFILL
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,
6601 0, 0x0, NULL, HFILL
6604 { &hf_mac_lte_drx_state_inactivity_remaining,
6605 { "Inactivity remaining",
6606 "mac-lte.drx-state.inactivity-remaining", FT_UINT16, BASE_DEC,
6607 0, 0x0, NULL, HFILL
6610 { &hf_mac_lte_drx_state_onduration_remaining,
6611 { "Onduration remaining",
6612 "mac-lte.drx-state.onduration-remaining", FT_UINT16, BASE_DEC,
6613 0, 0x0, NULL, HFILL
6616 { &hf_mac_lte_drx_state_retransmission_remaining,
6617 { "Retransmission remaining",
6618 "mac-lte.drx-state.retransmission-remaining", FT_UINT16, BASE_DEC,
6619 0, 0x0, NULL, HFILL
6622 { &hf_mac_lte_drx_state_rtt_remaining,
6623 { "RTT remaining",
6624 "mac-lte.drx-state.rtt-remaining", FT_UINT16, BASE_DEC,
6625 0, 0x0, NULL, HFILL
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,
6631 0, 0x0, NULL, HFILL
6636 static gint *ett[] =
6638 &ett_mac_lte,
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,
6650 &ett_mac_lte_bch,
6651 &ett_mac_lte_bsr,
6652 &ett_mac_lte_pch,
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,
6660 &ett_mac_lte_oob,
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},
6706 {NULL, NULL, -1}
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},
6712 {NULL, NULL, -1}
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"),
6723 UAT_END_FIELDS
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");
6739 /* Preferences */
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 "
6768 "UDP framing",
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),
6794 "drb_logchans",
6795 TRUE,
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,
6801 NULL,
6802 NULL,
6803 NULL,
6804 lcid_drb_mapping_flds );
6806 prefs_register_uat_preference(mac_lte_module,
6807 "drb_table",
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
6853 * Local variables:
6854 * c-basic-offset: 4
6855 * tab-width: 8
6856 * indent-tabs-mode: nil
6857 * End:
6859 * vi: set shiftwidth=4 tabstop=8 expandtab:
6860 * :indentSize=4:tabSize=8:noTabs=true: