1 /* Routines for LTE MAC disassembly
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include <epan/packet.h>
29 #include <epan/expert.h>
30 #include <epan/prefs.h>
34 #include "packet-mac-lte.h"
35 #include "packet-rlc-lte.h"
39 * 3GPP TS 36.321 Evolved Universal Terrestrial Radio Access (E-UTRA)
40 * Medium Access Control (MAC) protocol specification (Release 10)
44 /* Initialize the protocol and registered fields. */
45 int proto_mac_lte = -1;
47 static int mac_lte_tap = -1;
49 /* Decoding context */
50 static int hf_mac_lte_context = -1;
51 static int hf_mac_lte_context_radio_type = -1;
52 static int hf_mac_lte_context_direction = -1;
53 static int hf_mac_lte_context_rnti = -1;
54 static int hf_mac_lte_context_rnti_type = -1;
55 static int hf_mac_lte_context_ueid = -1;
56 static int hf_mac_lte_context_sysframe_number = -1;
57 static int hf_mac_lte_context_subframe_number = -1;
58 static int hf_mac_lte_context_grant_subframe_number = -1;
59 static int hf_mac_lte_context_predefined_frame = -1;
60 static int hf_mac_lte_context_length = -1;
61 static int hf_mac_lte_context_ul_grant_size = -1;
62 static int hf_mac_lte_context_bch_transport_channel = -1;
63 static int hf_mac_lte_context_retx_count = -1;
64 static int hf_mac_lte_context_retx_reason = -1;
65 static int hf_mac_lte_context_crc_status = -1;
66 static int hf_mac_lte_context_rapid = -1;
67 static int hf_mac_lte_context_rach_attempt_number = -1;
69 /* Inferred context */
70 static int hf_mac_lte_ues_ul_per_tti = -1;
71 static int hf_mac_lte_ues_dl_per_tti = -1;
74 /* Extra PHY context */
75 static int hf_mac_lte_context_phy_ul = -1;
76 static int hf_mac_lte_context_phy_ul_modulation_type = -1;
77 static int hf_mac_lte_context_phy_ul_tbs_index = -1;
78 static int hf_mac_lte_context_phy_ul_resource_block_length = -1;
79 static int hf_mac_lte_context_phy_ul_resource_block_start = -1;
80 static int hf_mac_lte_context_phy_ul_harq_id = -1;
81 static int hf_mac_lte_context_phy_ul_ndi = -1;
83 static int hf_mac_lte_context_phy_dl = -1;
84 static int hf_mac_lte_context_phy_dl_dci_format = -1;
85 static int hf_mac_lte_context_phy_dl_resource_allocation_type = -1;
86 static int hf_mac_lte_context_phy_dl_aggregation_level = -1;
87 static int hf_mac_lte_context_phy_dl_mcs_index = -1;
88 static int hf_mac_lte_context_phy_dl_redundancy_version_index = -1;
89 static int hf_mac_lte_context_phy_dl_retx = -1;
90 static int hf_mac_lte_context_phy_dl_resource_block_length = -1;
91 static int hf_mac_lte_context_phy_dl_crc_status = -1;
92 static int hf_mac_lte_context_phy_dl_harq_id = -1;
93 static int hf_mac_lte_context_phy_dl_ndi = -1;
94 static int hf_mac_lte_context_phy_dl_tb = -1;
97 /* Out-of-band events */
98 static int hf_mac_lte_oob_send_preamble = -1;
99 static int hf_mac_lte_oob_send_sr = -1;
100 static int hf_mac_lte_number_of_srs = -1;
101 static int hf_mac_lte_oob_sr_failure = -1;
103 /* MAC SCH/MCH header fields */
104 static int hf_mac_lte_ulsch = -1;
105 static int hf_mac_lte_ulsch_header = -1;
106 static int hf_mac_lte_dlsch = -1;
107 static int hf_mac_lte_dlsch_header = -1;
108 static int hf_mac_lte_sch_subheader = -1;
109 static int hf_mac_lte_mch = -1;
110 static int hf_mac_lte_mch_header = -1;
111 static int hf_mac_lte_mch_subheader = -1;
113 static int hf_mac_lte_sch_reserved = -1;
114 static int hf_mac_lte_dlsch_lcid = -1;
115 static int hf_mac_lte_ulsch_lcid = -1;
116 static int hf_mac_lte_sch_extended = -1;
117 static int hf_mac_lte_sch_format = -1;
118 static int hf_mac_lte_sch_length = -1;
119 static int hf_mac_lte_mch_reserved = -1;
120 static int hf_mac_lte_mch_lcid = -1;
121 static int hf_mac_lte_mch_extended = -1;
122 static int hf_mac_lte_mch_format = -1;
123 static int hf_mac_lte_mch_length = -1;
125 static int hf_mac_lte_sch_header_only = -1;
126 static int hf_mac_lte_mch_header_only = -1;
129 static int hf_mac_lte_sch_sdu = -1;
130 static int hf_mac_lte_mch_sdu = -1;
131 static int hf_mac_lte_bch_pdu = -1;
132 static int hf_mac_lte_pch_pdu = -1;
133 static int hf_mac_lte_predefined_pdu = -1;
134 static int hf_mac_lte_raw_pdu = -1;
135 static int hf_mac_lte_padding_data = -1;
136 static int hf_mac_lte_padding_length = -1;
140 static int hf_mac_lte_rar = -1;
141 static int hf_mac_lte_rar_headers = -1;
142 static int hf_mac_lte_rar_header = -1;
143 static int hf_mac_lte_rar_extension = -1;
144 static int hf_mac_lte_rar_t = -1;
145 static int hf_mac_lte_rar_bi = -1;
146 static int hf_mac_lte_rar_rapid = -1;
147 static int hf_mac_lte_rar_reserved = -1;
148 static int hf_mac_lte_rar_body = -1;
149 static int hf_mac_lte_rar_reserved2 = -1;
150 static int hf_mac_lte_rar_ta = -1;
151 static int hf_mac_lte_rar_ul_grant = -1;
152 static int hf_mac_lte_rar_ul_grant_hopping = -1;
153 static int hf_mac_lte_rar_ul_grant_fsrba = -1;
154 static int hf_mac_lte_rar_ul_grant_tmcs = -1;
155 static int hf_mac_lte_rar_ul_grant_tcsp = -1;
156 static int hf_mac_lte_rar_ul_grant_ul_delay = -1;
157 static int hf_mac_lte_rar_ul_grant_cqi_request = -1;
158 static int hf_mac_lte_rar_temporary_crnti = -1;
160 /* Common channel control values */
161 static int hf_mac_lte_control_bsr = -1;
162 static int hf_mac_lte_control_bsr_lcg_id = -1;
163 static int hf_mac_lte_control_short_bsr_buffer_size = -1;
164 static int hf_mac_lte_control_long_bsr_buffer_size_0 = -1;
165 static int hf_mac_lte_control_long_bsr_buffer_size_1 = -1;
166 static int hf_mac_lte_control_long_bsr_buffer_size_2 = -1;
167 static int hf_mac_lte_control_long_bsr_buffer_size_3 = -1;
168 static int hf_mac_lte_control_short_ext_bsr_buffer_size = -1;
169 static int hf_mac_lte_control_long_ext_bsr_buffer_size_0 = -1;
170 static int hf_mac_lte_control_long_ext_bsr_buffer_size_1 = -1;
171 static int hf_mac_lte_control_long_ext_bsr_buffer_size_2 = -1;
172 static int hf_mac_lte_control_long_ext_bsr_buffer_size_3 = -1;
173 static int hf_mac_lte_control_crnti = -1;
174 static int hf_mac_lte_control_timing_advance = -1;
175 static int hf_mac_lte_control_timing_advance_reserved = -1;
176 static int hf_mac_lte_control_ue_contention_resolution = -1;
177 static int hf_mac_lte_control_ue_contention_resolution_identity = -1;
178 static int hf_mac_lte_control_ue_contention_resolution_msg3 = -1;
179 static int hf_mac_lte_control_ue_contention_resolution_msg3_matched = -1;
180 static int hf_mac_lte_control_ue_contention_resolution_time_since_msg3 = -1;
181 static int hf_mac_lte_control_power_headroom = -1;
182 static int hf_mac_lte_control_power_headroom_reserved = -1;
183 static int hf_mac_lte_control_power_headroom_level = -1;
184 static int hf_mac_lte_control_ext_power_headroom = -1;
185 static int hf_mac_lte_control_ext_power_headroom_c7 = -1;
186 static int hf_mac_lte_control_ext_power_headroom_c6 = -1;
187 static int hf_mac_lte_control_ext_power_headroom_c5 = -1;
188 static int hf_mac_lte_control_ext_power_headroom_c4 = -1;
189 static int hf_mac_lte_control_ext_power_headroom_c3 = -1;
190 static int hf_mac_lte_control_ext_power_headroom_c2 = -1;
191 static int hf_mac_lte_control_ext_power_headroom_c1 = -1;
192 static int hf_mac_lte_control_ext_power_headroom_reserved = -1;
193 static int hf_mac_lte_control_ext_power_headroom_power_backoff = -1;
194 static int hf_mac_lte_control_ext_power_headroom_value = -1;
195 static int hf_mac_lte_control_ext_power_headroom_level = -1;
196 static int hf_mac_lte_control_ext_power_headroom_reserved2 = -1;
197 static int hf_mac_lte_control_ext_power_headroom_pcmaxc = -1;
198 static int hf_mac_lte_control_activation_deactivation = -1;
199 static int hf_mac_lte_control_activation_deactivation_c7 = -1;
200 static int hf_mac_lte_control_activation_deactivation_c6 = -1;
201 static int hf_mac_lte_control_activation_deactivation_c5 = -1;
202 static int hf_mac_lte_control_activation_deactivation_c4 = -1;
203 static int hf_mac_lte_control_activation_deactivation_c3 = -1;
204 static int hf_mac_lte_control_activation_deactivation_c2 = -1;
205 static int hf_mac_lte_control_activation_deactivation_c1 = -1;
206 static int hf_mac_lte_control_activation_deactivation_reserved = -1;
207 static int hf_mac_lte_control_mch_scheduling_info = -1;
208 static int hf_mac_lte_control_mch_scheduling_info_lcid = -1;
209 static int hf_mac_lte_control_mch_scheduling_info_stop_mtch = -1;
211 static int hf_mac_lte_dl_harq_resend_original_frame = -1;
212 static int hf_mac_lte_dl_harq_resend_time_since_previous_frame = -1;
213 static int hf_mac_lte_dl_harq_resend_next_frame = -1;
214 static int hf_mac_lte_dl_harq_resend_time_until_next_frame = -1;
216 static int hf_mac_lte_ul_harq_resend_original_frame = -1;
217 static int hf_mac_lte_ul_harq_resend_time_since_previous_frame = -1;
218 static int hf_mac_lte_ul_harq_resend_next_frame = -1;
219 static int hf_mac_lte_ul_harq_resend_time_until_next_frame = -1;
222 static int hf_mac_lte_grant_answering_sr = -1;
223 static int hf_mac_lte_failure_answering_sr = -1;
224 static int hf_mac_lte_sr_leading_to_failure = -1;
225 static int hf_mac_lte_sr_leading_to_grant = -1;
226 static int hf_mac_lte_sr_invalid_event = -1;
227 static int hf_mac_lte_sr_time_since_request = -1;
228 static int hf_mac_lte_sr_time_until_answer = -1;
232 static int ett_mac_lte = -1;
233 static int ett_mac_lte_context = -1;
234 static int ett_mac_lte_phy_context = -1;
235 static int ett_mac_lte_ulsch_header = -1;
236 static int ett_mac_lte_dlsch_header = -1;
237 static int ett_mac_lte_mch_header = -1;
238 static int ett_mac_lte_sch_subheader = -1;
239 static int ett_mac_lte_mch_subheader = -1;
240 static int ett_mac_lte_rar_headers = -1;
241 static int ett_mac_lte_rar_header = -1;
242 static int ett_mac_lte_rar_body = -1;
243 static int ett_mac_lte_rar_ul_grant = -1;
244 static int ett_mac_lte_bsr = -1;
245 static int ett_mac_lte_bch = -1;
246 static int ett_mac_lte_pch = -1;
247 static int ett_mac_lte_activation_deactivation = -1;
248 static int ett_mac_lte_contention_resolution = -1;
249 static int ett_mac_lte_power_headroom = -1;
250 static int ett_mac_lte_extended_power_headroom = -1;
251 static int ett_mac_lte_extended_power_headroom_cell = -1;
252 static int ett_mac_lte_mch_scheduling_info = -1;
253 static int ett_mac_lte_oob = -1;
257 /* Constants and value strings */
259 static const value_string radio_type_vals[] =
267 static const value_string direction_vals[] =
269 { DIRECTION_UPLINK, "Uplink"},
270 { DIRECTION_DOWNLINK, "Downlink"},
275 static const value_string rnti_type_vals[] =
277 { NO_RNTI, "NO-RNTI"},
279 { RA_RNTI, "RA-RNTI"},
281 { SI_RNTI, "SI-RNTI"},
282 { SPS_RNTI, "SPS-RNTI"},
287 static const value_string bch_transport_channel_vals[] =
289 { SI_RNTI, "DL-SCH"},
294 static const value_string crc_status_vals[] =
296 { crc_success, "OK"},
297 { crc_fail, "Failed"},
298 { crc_high_code_rate, "High Code Rate"},
299 { crc_pdsch_lost, "PDSCH Lost"},
300 { crc_duplicate_nonzero_rv, "Duplicate_nonzero_rv"},
305 static const value_string dci_format_vals[] =
319 static const value_string aggregation_level_vals[] =
328 static const value_string modulation_type_vals[] =
336 static const true_false_string mac_lte_scell_ph_vals = {
341 static const true_false_string mac_lte_power_backoff_vals = {
346 static const true_false_string mac_lte_ph_value_vals = {
347 "Based on reference format",
348 "Based on real transmission"
351 static const true_false_string mac_lte_scell_status_vals = {
356 #define ACTIVATION_DEACTIVATION_LCID 0x1b
357 #define UE_CONTENTION_RESOLUTION_IDENTITY_LCID 0x1c
358 #define TIMING_ADVANCE_LCID 0x1d
359 #define DRX_COMMAND_LCID 0x1e
360 #define PADDING_LCID 0x1f
362 static const value_string dlsch_lcid_vals[] =
375 { ACTIVATION_DEACTIVATION_LCID , "Activation/Deactivation"},
376 { UE_CONTENTION_RESOLUTION_IDENTITY_LCID, "UE Contention Resolution Identity"},
377 { TIMING_ADVANCE_LCID , "Timing Advance"},
378 { DRX_COMMAND_LCID , "DRX Command"},
379 { PADDING_LCID , "Padding" },
383 #define EXTENDED_POWER_HEADROOM_REPORT_LCID 0x19
384 #define POWER_HEADROOM_REPORT_LCID 0x1a
385 #define CRNTI_LCID 0x1b
386 #define TRUNCATED_BSR_LCID 0x1c
387 #define SHORT_BSR_LCID 0x1d
388 #define LONG_BSR_LCID 0x1e
390 static const value_string ulsch_lcid_vals[] =
403 { EXTENDED_POWER_HEADROOM_REPORT_LCID, "Extended Power Headroom Report"},
404 { POWER_HEADROOM_REPORT_LCID, "Power Headroom Report"},
405 { CRNTI_LCID, "C-RNTI"},
406 { TRUNCATED_BSR_LCID, "Truncated BSR"},
407 { SHORT_BSR_LCID, "Short BSR"},
408 { LONG_BSR_LCID, "Long BSR"},
409 { PADDING_LCID, "Padding" },
413 #define MCH_SCHEDULING_INFO_LCID 0x1e
415 static const value_string mch_lcid_vals[] =
446 { MCH_SCHEDULING_INFO_LCID, "MCH Scheduling Information"},
447 { PADDING_LCID, "Padding" },
451 static const value_string format_vals[] =
453 { 0, "Data length is < 128 bytes"},
454 { 1, "Data length is >= 128 bytes"},
459 static const value_string rar_type_vals[] =
461 { 0, "Backoff Indicator present"},
462 { 1, "RAPID present"},
467 static const value_string rar_bi_vals[] =
486 static const value_string buffer_size_vals[] =
489 { 1, "0 < BS <= 10"},
490 { 2, "10 < BS <= 12"},
491 { 3, "12 < BS <= 14"},
492 { 4, "14 < BS <= 17"},
493 { 5, "17 < BS <= 19"},
494 { 6, "19 < BS <= 22"},
495 { 7, "22 < BS <= 26"},
496 { 8, "26 < BS <= 31"},
497 { 9, "31 < BS <= 36"},
498 { 10, "36 < BS <= 42"},
499 { 11, "42 < BS <= 49"},
500 { 12, "49 < BS <= 57"},
501 { 13, "47 < BS <= 67"},
502 { 14, "67 < BS <= 78"},
503 { 15, "78 < BS <= 91"},
504 { 16, "91 < BS <= 107"},
505 { 17, "107 < BS <= 125"},
506 { 18, "125 < BS <= 146"},
507 { 19, "146 < BS <= 171"},
508 { 20, "171 < BS <= 200"},
509 { 21, "200 < BS <= 234"},
510 { 22, "234 < BS <= 274"},
511 { 23, "274 < BS <= 321"},
512 { 24, "321 < BS <= 376"},
513 { 25, "376 < BS <= 440"},
514 { 26, "440 < BS <= 515"},
515 { 27, "515 < BS <= 603"},
516 { 28, "603 < BS <= 706"},
517 { 29, "706 < BS <= 826"},
518 { 30, "826 < BS <= 967"},
519 { 31, "967 < BS <= 1132"},
520 { 32, "1132 < BS <= 1326"},
521 { 33, "1326 < BS <= 1552"},
522 { 34, "1552 < BS <= 1817"},
523 { 35, "1817 < BS <= 2127"},
524 { 36, "2127 < BS <= 2490"},
525 { 37, "2490 < BS <= 2915"},
526 { 38, "2915 < BS <= 3413"},
527 { 39, "3413 < BS <= 3995"},
528 { 40, "3995 < BS <= 4677"},
529 { 41, "4677 < BS <= 5476"},
530 { 42, "5476 < BS <= 6411"},
531 { 43, "6411 < BS <= 7505"},
532 { 44, "7505 < BS <= 8787"},
533 { 45, "8787 < BS <= 10276"},
534 { 46, "10287 < BS <= 12043"},
535 { 47, "12043 < BS <= 14099"},
536 { 48, "14099 < BS <= 16507"},
537 { 49, "16507 < BS <= 19325"},
538 { 50, "19325 < BS <= 22624"},
539 { 51, "22624 < BS <= 26487"},
540 { 52, "26487 < BS <= 31009"},
541 { 53, "31009 < BS <= 36304"},
542 { 54, "36304 < BS <= 42502"},
543 { 55, "42502 < BS <= 49759"},
544 { 56, "49759 < BS <= 58255"},
545 { 57, "58255 < BS <= 68201"},
546 { 58, "68201 < BS <= 79846"},
547 { 59, "79846 < BS <= 93479"},
548 { 60, "93479 < BS <= 109439"},
549 { 61, "109439 < BS <= 128125"},
550 { 62, "128125 < BS <= 150000"},
551 { 63, "BS > 150000"},
554 static value_string_ext buffer_size_vals_ext = VALUE_STRING_EXT_INIT(buffer_size_vals);
556 static const value_string ext_buffer_size_vals[] =
559 { 1, "0 < BS <= 10"},
560 { 2, "10 < BS <= 13"},
561 { 3, "13 < BS <= 16"},
562 { 4, "16 < BS <= 19"},
563 { 5, "19 < BS <= 23"},
564 { 6, "23 < BS <= 29"},
565 { 7, "29 < BS <= 35"},
566 { 8, "35 < BS <= 43"},
567 { 9, "43 < BS <= 53"},
568 { 10, "53 < BS <= 65"},
569 { 11, "65 < BS <= 80"},
570 { 12, "80 < BS <= 98"},
571 { 13, "98 < BS <= 120"},
572 { 14, "120 < BS <= 147"},
573 { 15, "147 < BS <= 181"},
574 { 16, "181 < BS <= 223"},
575 { 17, "223 < BS <= 274"},
576 { 18, "274 < BS <= 337"},
577 { 19, "337 < BS <= 414"},
578 { 20, "414 < BS <= 509"},
579 { 21, "509 < BS <= 625"},
580 { 22, "625 < BS <= 769"},
581 { 23, "769 < BS <= 945"},
582 { 24, "945 < BS <= 1162"},
583 { 25, "1162 < BS <= 1429"},
584 { 26, "1429 < BS <= 1757"},
585 { 27, "1757 < BS <= 2161"},
586 { 28, "2161 < BS <= 2657"},
587 { 29, "2657 < BS <= 3267"},
588 { 30, "3267 < BS <= 4017"},
589 { 31, "4017 < BS <= 4940"},
590 { 32, "4940 < BS <= 6074"},
591 { 33, "6074 < BS <= 7469"},
592 { 34, "7469 < BS <= 9185"},
593 { 35, "9185 < BS <= 11294"},
594 { 36, "11294 < BS <= 13888"},
595 { 37, "13888 < BS <= 17077"},
596 { 38, "17077 < BS <= 20999"},
597 { 39, "20999 < BS <= 25822"},
598 { 40, "25822 < BS <= 31752"},
599 { 41, "31752 < BS <= 39045"},
600 { 42, "39045 < BS <= 48012"},
601 { 43, "48012 < BS <= 59039"},
602 { 44, "59039 < BS <= 72598"},
603 { 45, "72598 < BS <= 89272"},
604 { 46, "89272 < BS <= 109774"},
605 { 47, "109774 < BS <= 134986"},
606 { 48, "134986 < BS <= 165989"},
607 { 49, "165989 < BS <= 204111"},
608 { 50, "204111 < BS <= 250990"},
609 { 51, "250990 < BS <= 308634"},
610 { 52, "308634 < BS <= 379519"},
611 { 53, "379519 < BS <= 466683"},
612 { 54, "466683 < BS <= 573866"},
613 { 55, "573866 < BS <= 705666"},
614 { 56, "705666 < BS <= 867737"},
615 { 57, "867737 < BS <= 1067031"},
616 { 58, "1067031 < BS <= 1312097"},
617 { 59, "1312097 < BS <= 1613447"},
618 { 60, "1613447 < BS <= 1984009"},
619 { 61, "1984009 < BS <= 2439678"},
620 { 62, "2439678 < BS <= 3000000"},
621 { 63, "BS > 3000000"},
624 static value_string_ext ext_buffer_size_vals_ext = VALUE_STRING_EXT_INIT(ext_buffer_size_vals);
626 static const value_string power_headroom_vals[] =
628 { 0, "-23 <= PH < -22"},
629 { 1, "-22 <= PH < -21"},
630 { 2, "-21 <= PH < -20"},
631 { 3, "-20 <= PH < -19"},
632 { 4, "-19 <= PH < -18"},
633 { 5, "-18 <= PH < -17"},
634 { 6, "-17 <= PH < -16"},
635 { 7, "-16 <= PH < -15"},
636 { 8, "-15 <= PH < -14"},
637 { 9, "-14 <= PH < -13"},
638 { 10, "-13 <= PH < -12"},
639 { 11, "-12 <= PH < -11"},
640 { 12, "-11 <= PH < -10"},
641 { 13, "-10 <= PH < -9"},
642 { 14, "-9 <= PH < -8"},
643 { 15, "-8 <= PH < -7"},
644 { 16, "-7 <= PH < -6"},
645 { 17, "-6 <= PH < -5"},
646 { 18, "-5 <= PH < -4"},
647 { 19, "-4 <= PH < -3"},
648 { 20, "-3 <= PH < -2"},
649 { 21, "-2 <= PH < -1"},
650 { 22, "-1 <= PH < 0"},
651 { 23, "0 <= PH < 1"},
652 { 24, "1 <= PH < 2"},
653 { 25, "2 <= PH < 3"},
654 { 26, "3 <= PH < 4"},
655 { 27, "4 <= PH < 5"},
656 { 28, "5 <= PH < 6"},
657 { 29, "6 <= PH < 7"},
658 { 30, "7 <= PH < 8"},
659 { 31, "8 <= PH < 9"},
660 { 32, "9 <= PH < 10"},
661 { 33, "10 <= PH < 11"},
662 { 34, "11 <= PH < 12"},
663 { 35, "12 <= PH < 13"},
664 { 36, "13 <= PH < 14"},
665 { 37, "14 <= PH < 15"},
666 { 38, "15 <= PH < 16"},
667 { 39, "16 <= PH < 17"},
668 { 40, "17 <= PH < 18"},
669 { 41, "18 <= PH < 19"},
670 { 42, "19 <= PH < 20"},
671 { 43, "20 <= PH < 21"},
672 { 44, "21 <= PH < 22"},
673 { 45, "22 <= PH < 23"},
674 { 46, "23 <= PH < 24"},
675 { 47, "24 <= PH < 25"},
676 { 48, "25 <= PH < 26"},
677 { 49, "26 <= PH < 27"},
678 { 50, "27 <= PH < 28"},
679 { 51, "28 <= PH < 29"},
680 { 52, "29 <= PH < 30"},
681 { 53, "30 <= PH < 31"},
682 { 54, "31 <= PH < 32"},
683 { 55, "32 <= PH < 33"},
684 { 56, "33 <= PH < 34"},
685 { 57, "34 <= PH < 35"},
686 { 58, "34 <= PH < 36"},
687 { 59, "36 <= PH < 37"},
688 { 60, "37 <= PH < 38"},
689 { 61, "38 <= PH < 39"},
690 { 62, "39 <= PH < 40"},
694 static value_string_ext power_headroom_vals_ext = VALUE_STRING_EXT_INIT(power_headroom_vals);
696 static const value_string pcmaxc_vals[] =
698 { 0, "Pcmax,c < -29"},
699 { 1, "-29 <= Pcmax,c < -28"},
700 { 2, "-28 <= Pcmax,c < -27"},
701 { 3, "-27 <= Pcmax,c < -26"},
702 { 4, "-26 <= Pcmax,c < -25"},
703 { 5, "-25 <= Pcmax,c < -24"},
704 { 6, "-24 <= Pcmax,c < -23"},
705 { 7, "-23 <= Pcmax,c < -22"},
706 { 8, "-22 <= Pcmax,c < -21"},
707 { 9, "-21 <= Pcmax,c < -20"},
708 { 10, "-20 <= Pcmax,c < -19"},
709 { 11, "-19 <= Pcmax,c < -18"},
710 { 12, "-18 <= Pcmax,c < -17"},
711 { 13, "-17 <= Pcmax,c < -16"},
712 { 14, "-16 <= Pcmax,c < -15"},
713 { 15, "-15 <= Pcmax,c < -14"},
714 { 16, "-14 <= Pcmax,c < -13"},
715 { 17, "-13 <= Pcmax,c < -12"},
716 { 18, "-12 <= Pcmax,c < -11"},
717 { 19, "-11 <= Pcmax,c < -10"},
718 { 20, "-10 <= Pcmax,c < -9"},
719 { 21, "-9 <= Pcmax,c < -8"},
720 { 22, "-8 <= Pcmax,c < -7"},
721 { 23, "-7 <= Pcmax,c < -6"},
722 { 24, "-6 <= Pcmax,c < -5"},
723 { 25, "-5 <= Pcmax,c < -4"},
724 { 26, "-4 <= Pcmax,c < -3"},
725 { 27, "-3 <= Pcmax,c < -2"},
726 { 28, "-2 <= Pcmax,c < -1"},
727 { 29, "-1 <= Pcmax,c < 0"},
728 { 30, "0 <= Pcmax,c < 1"},
729 { 31, "1 <= Pcmax,c < 2"},
730 { 32, "2 <= Pcmax,c < 3"},
731 { 33, "3 <= Pcmax,c < 4"},
732 { 34, "4 <= Pcmax,c < 5"},
733 { 35, "5 <= Pcmax,c < 6"},
734 { 36, "6 <= Pcmax,c < 7"},
735 { 37, "7 <= Pcmax,c < 8"},
736 { 38, "8 <= Pcmax,c < 9"},
737 { 39, "9 <= Pcmax,c < 10"},
738 { 40, "10 <= Pcmax,c < 11"},
739 { 41, "11 <= Pcmax,c < 12"},
740 { 42, "12 <= Pcmax,c < 13"},
741 { 43, "13 <= Pcmax,c < 14"},
742 { 44, "14 <= Pcmax,c < 15"},
743 { 45, "15 <= Pcmax,c < 16"},
744 { 46, "16 <= Pcmax,c < 17"},
745 { 47, "17 <= Pcmax,c < 18"},
746 { 48, "18 <= Pcmax,c < 19"},
747 { 49, "19 <= Pcmax,c < 20"},
748 { 50, "20 <= Pcmax,c < 21"},
749 { 51, "21 <= Pcmax,c < 22"},
750 { 52, "22 <= Pcmax,c < 23"},
751 { 53, "23 <= Pcmax,c < 24"},
752 { 54, "24 <= Pcmax,c < 25"},
753 { 55, "25 <= Pcmax,c < 26"},
754 { 56, "26 <= Pcmax,c < 27"},
755 { 57, "27 <= Pcmax,c < 28"},
756 { 58, "28 <= Pcmax,c < 29"},
757 { 59, "29 <= Pcmax,c < 30"},
758 { 60, "30 <= Pcmax,c < 31"},
759 { 61, "31 <= Pcmax,c < 32"},
760 { 62, "32 <= Pcmax,c < 33"},
761 { 63, "33 <= Pcmax,c"},
764 static value_string_ext pcmaxc_vals_ext = VALUE_STRING_EXT_INIT(pcmaxc_vals);
766 static const value_string header_only_vals[] =
768 { 0, "MAC PDU Headers and body present"},
769 { 1, "MAC PDU Headers only"},
773 static const value_string predefined_frame_vals[] =
775 { 0, "Real MAC PDU present - will dissect"},
776 { 1, "Predefined frame present - will not dissect"},
780 static const value_string ul_retx_grant_vals[] =
787 /**************************************************************************/
788 /* Preferences state */
789 /**************************************************************************/
791 /* If this PDU has been NACK'd (by HARQ) more than a certain number of times,
792 we trigger an expert warning. */
793 static gint global_mac_lte_retx_counter_trigger = 3;
795 /* By default try to decode transparent data (BCH, PCH and CCCH) data using LTE RRC dissector */
796 static gboolean global_mac_lte_attempt_rrc_decode = TRUE;
798 /* Whether should attempt to dissect frames failing CRC check */
799 static gboolean global_mac_lte_dissect_crc_failures = FALSE;
801 /* Whether should attempt to decode lcid 1&2 SDUs as srb1/2 (i.e. AM RLC) */
802 static gboolean global_mac_lte_attempt_srb_decode = TRUE;
804 /* Where to take LCID -> DRB mappings from */
805 enum lcid_drb_source {
806 FromStaticTable, FromConfigurationProtocol
808 static gint global_mac_lte_lcid_drb_source = (gint)FromStaticTable;
810 /* Threshold for warning in expert info about high BSR values */
811 static gint global_mac_lte_bsr_warn_threshold = 50; /* default is 19325 -> 22624 */
813 /* Whether or not to track SRs and related frames */
814 static gboolean global_mac_lte_track_sr = TRUE;
816 /* Which layer info to show in the info column */
818 ShowPHYLayer, ShowMACLayer, ShowRLCLayer
821 /* Which layer's details to show in Info column */
822 static gint global_mac_lte_layer_to_show = (gint)ShowRLCLayer;
824 /* When showing RLC info, count PDUs so can append info column properly */
825 static guint8 s_number_of_rlc_pdus_shown = 0;
827 /***********************************************************************/
828 /* How to dissect lcid 3-10 (presume drb logical channels) */
830 static const value_string drb_lcid_vals[] = {
842 typedef enum rlc_channel_type_t {
848 } rlc_channel_type_t;
850 static const value_string rlc_channel_type_vals[] = {
852 { rlcUM5 , "UM, SN Len=5"},
853 { rlcUM10, "UM, SN Len=10"},
860 typedef struct lcid_drb_mapping_t {
863 rlc_channel_type_t channel_type;
864 } lcid_drb_mapping_t;
867 static lcid_drb_mapping_t *lcid_drb_mappings = NULL;
868 static guint num_lcid_drb_mappings = 0;
870 UAT_VS_DEF(lcid_drb_mappings, lcid, lcid_drb_mapping_t, 3, "LCID 3")
871 UAT_DEC_CB_DEF(lcid_drb_mappings, drbid, lcid_drb_mapping_t)
872 UAT_VS_DEF(lcid_drb_mappings, channel_type, lcid_drb_mapping_t, 2, "AM")
875 static uat_t* lcid_drb_mappings_uat;
877 /* Dynamic mappings (set by configuration protocol)
878 LCID is the index into the array of these */
879 typedef struct dynamic_lcid_drb_mapping_t {
882 rlc_channel_type_t channel_type;
884 } dynamic_lcid_drb_mapping_t;
886 static dynamic_lcid_drb_mapping_t dynamic_lcid_drb_mapping[11];
889 extern int proto_rlc_lte;
891 /***************************************************************/
895 /***************************************************************/
896 /* Keeping track of Msg3 bodies so they can be compared with */
897 /* Contention Resolution bodies. */
899 typedef struct Msg3Data {
906 /* This table stores (RNTI -> Msg3Data*). Will be populated when
907 Msg3 frames are first read. */
908 static GHashTable *mac_lte_msg3_hash = NULL;
910 /* Hash table functions for mac_lte_msg3_hash. Hash is just the (RNTI) key */
911 static gint mac_lte_rnti_hash_equal(gconstpointer v, gconstpointer v2)
916 static guint mac_lte_rnti_hash_func(gconstpointer v)
918 return GPOINTER_TO_UINT(v);
922 typedef enum ContentionResolutionStatus {
926 } ContentionResolutionStatus;
928 typedef struct ContentionResolutionResult {
929 ContentionResolutionStatus status;
932 } ContentionResolutionResult;
935 /* This table stores (CRFrameNum -> CRResult). It is assigned during the first
936 pass and used thereafter */
937 static GHashTable *mac_lte_cr_result_hash = NULL;
939 /* Hash table functions for mac_lte_cr_result_hash. Hash is just the (framenum) key */
940 static gint mac_lte_framenum_hash_equal(gconstpointer v, gconstpointer v2)
945 static guint mac_lte_framenum_hash_func(gconstpointer v)
947 return GPOINTER_TO_UINT(v);
950 /**************************************************************************/
954 /****************************************************************/
955 /* Keeping track of last DL frames per C-RNTI so can guess when */
956 /* there has been a HARQ retransmission */
957 /* TODO: this should be simplified now that harq-id & ndi are */
960 /* Could be bigger, but more than enough to flag suspected resends */
961 #define MAX_EXPECTED_PDU_LENGTH 2048
963 typedef struct LastFrameData {
967 nstime_t received_time;
969 guint8 data[MAX_EXPECTED_PDU_LENGTH];
972 typedef struct DLHarqBuffers {
973 LastFrameData harqid[2][15]; /* 2 blocks (1 for each antenna) needed for DL */
977 /* This table stores (RNTI -> DLHARQBuffers*). Will be populated when
978 DL frames are first read. */
979 static GHashTable *mac_lte_dl_harq_hash = NULL;
981 typedef struct DLHARQResult {
982 gboolean previousSet, nextSet;
983 guint previousFrameNum;
984 guint timeSincePreviousFrame;
986 guint timeToNextFrame;
990 /* This table stores (FrameNumber -> *DLHARQResult). It is assigned during the first
991 pass and used thereafter */
992 static GHashTable *mac_lte_dl_harq_result_hash = NULL;
994 /**************************************************************************/
997 /*****************************************************************/
998 /* Keeping track of last UL frames per C-RNTI so can verify when */
999 /* told that a frame is a retx */
1001 typedef struct ULHarqBuffers {
1002 LastFrameData harqid[8];
1006 /* This table stores (RNTI -> ULHarqBuffers*). Will be populated when
1007 UL frames are first read. */
1008 static GHashTable *mac_lte_ul_harq_hash = NULL;
1010 typedef struct ULHARQResult {
1011 gboolean previousSet, nextSet;
1012 guint previousFrameNum;
1013 guint timeSincePreviousFrame;
1015 guint timeToNextFrame;
1019 /* This table stores (FrameNum -> ULHARQResult). It is assigned during the first
1020 pass and used thereafter */
1021 static GHashTable *mac_lte_ul_harq_result_hash = NULL;
1023 /**************************************************************************/
1026 /**************************************************************************/
1027 /* Tracking of Scheduling Requests (SRs). */
1028 /* Keep track of: */
1029 /* - last grant before SR */
1030 /* - SR failures following request */
1031 /* - grant following SR */
1033 typedef enum SREvent {
1039 static const value_string sr_event_vals[] =
1041 { SR_Grant, "Grant"},
1042 { SR_Request, "SR Request"},
1043 { SR_Failure, "SR Failure"},
1047 typedef enum SRStatus {
1053 static const value_string sr_status_vals[] =
1055 { None, "Receiving grants"},
1056 { SR_Outstanding, "SR Request outstanding"},
1057 { SR_Failed, "SR has Failed"},
1062 typedef struct SRState {
1064 guint32 lastSRFramenum;
1065 guint32 lastGrantFramenum;
1066 nstime_t requestTime;
1070 /* This table keeps track of the SR state for each UE.
1071 (RNTI -> SRState) */
1072 static GHashTable *mac_lte_ue_sr_state = NULL;
1075 typedef enum SRResultType {
1084 typedef struct SRResult {
1087 guint32 timeDifference;
1089 /* These 2 are only used with InvalidSREvent */
1094 /* Entries in this table are created during the first pass
1095 It maps (SRFrameNum -> SRResult) */
1096 static GHashTable *mac_lte_sr_request_hash = NULL;
1099 /**************************************************************************/
1103 /* Forward declarations */
1104 void proto_reg_handoff_mac_lte(void);
1105 void dissect_mac_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
1107 static guint8 get_mac_lte_channel_priority(guint16 ueid _U_, guint8 lcid,
1111 /* Heuristic dissection */
1112 static gboolean global_mac_lte_heur = FALSE;
1114 static void call_with_catch_all(dissector_handle_t handle, tvbuff_t* tvb, packet_info *pinfo, proto_tree *tree)
1116 /* Call it (catch exceptions so that stats will be updated) */
1118 call_dissector_only(handle, tvb, pinfo, tree);
1125 /* Dissect context fields in the format described in packet-mac-lte.h.
1126 Return TRUE if the necessary information was successfully found */
1127 gboolean dissect_mac_lte_context_fields(struct mac_lte_info *p_mac_lte_info, tvbuff_t *tvb,
1130 gint offset = *p_offset;
1133 /* Read fixed fields */
1134 p_mac_lte_info->radioType = tvb_get_guint8(tvb, offset++);
1135 p_mac_lte_info->direction = tvb_get_guint8(tvb, offset++);
1137 /* TODO: currently no support for detailed PHY info... */
1138 if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
1139 p_mac_lte_info->detailed_phy_info.ul_info.present = FALSE;
1142 p_mac_lte_info->detailed_phy_info.dl_info.present = FALSE;
1145 p_mac_lte_info->rntiType = tvb_get_guint8(tvb, offset++);
1147 /* Initialize RNTI with a default value in case optional field is not present */
1148 switch (p_mac_lte_info->rntiType) {
1150 p_mac_lte_info->rnti = 0xFFFD;
1153 p_mac_lte_info->rnti = 0xFFFE;
1156 p_mac_lte_info->rnti = 0xFFFF;
1161 p_mac_lte_info->rnti = 0x0001;
1167 /* Read optional fields */
1168 while (tag != MAC_LTE_PAYLOAD_TAG) {
1169 /* Process next tag */
1170 tag = tvb_get_guint8(tvb, offset++);
1172 case MAC_LTE_RNTI_TAG:
1173 p_mac_lte_info->rnti = tvb_get_ntohs(tvb, offset);
1176 case MAC_LTE_UEID_TAG:
1177 p_mac_lte_info->ueid = tvb_get_ntohs(tvb, offset);
1180 case MAC_LTE_SUBFRAME_TAG:
1181 p_mac_lte_info->subframeNumber = tvb_get_ntohs(tvb, offset);
1184 case MAC_LTE_PREDEFINED_DATA_TAG:
1185 p_mac_lte_info->isPredefinedData = tvb_get_guint8(tvb, offset);
1188 case MAC_LTE_RETX_TAG:
1189 p_mac_lte_info->reTxCount = tvb_get_guint8(tvb, offset);
1192 case MAC_LTE_CRC_STATUS_TAG:
1193 p_mac_lte_info->crcStatusValid = TRUE;
1194 p_mac_lte_info->detailed_phy_info.dl_info.crc_status = tvb_get_guint8(tvb, offset);
1197 case MAC_LTE_EXT_BSR_SIZES_TAG:
1198 p_mac_lte_info->isExtendedBSRSizes = TRUE;
1201 case MAC_LTE_PAYLOAD_TAG:
1202 /* Have reached data, so set payload length and get out of loop */
1203 p_mac_lte_info->length= tvb_length_remaining(tvb, offset);
1207 /* It must be a recognised tag */
1212 /* Pass out where offset is now */
1218 /* Heuristic dissector looks for supported framing protocol (see wiki page) */
1219 static gboolean dissect_mac_lte_heur(tvbuff_t *tvb, packet_info *pinfo,
1223 struct mac_lte_info *p_mac_lte_info;
1225 gboolean infoAlreadySet = FALSE;
1227 /* This is a heuristic dissector, which means we get all the UDP
1228 * traffic not sent to a known dissector and not claimed by
1229 * a heuristic dissector called before us!
1232 if (!global_mac_lte_heur) {
1236 /* Do this again on re-dissection to re-discover offset of actual PDU */
1238 /* Needs to be at least as long as:
1239 - the signature string
1240 - fixed header bytes
1242 - at least one byte of MAC PDU payload */
1243 if ((size_t)tvb_length_remaining(tvb, offset) < (strlen(MAC_LTE_START_STRING)+3+2)) {
1247 /* OK, compare with signature string */
1248 if (tvb_strneql(tvb, offset, MAC_LTE_START_STRING, strlen(MAC_LTE_START_STRING)) != 0) {
1251 offset += (gint)strlen(MAC_LTE_START_STRING);
1253 /* If redissecting, use previous info struct (if available) */
1254 p_mac_lte_info = p_get_proto_data(pinfo->fd, proto_mac_lte);
1255 if (p_mac_lte_info == NULL) {
1256 /* Allocate new info struct for this frame */
1257 p_mac_lte_info = se_alloc0(sizeof(struct mac_lte_info));
1258 infoAlreadySet = FALSE;
1261 infoAlreadySet = TRUE;
1264 /* Dissect the fields to populate p_mac_lte */
1265 if (!dissect_mac_lte_context_fields(p_mac_lte_info, tvb, &offset)) {
1270 if (!infoAlreadySet) {
1271 /* Store info in packet */
1272 p_add_proto_data(pinfo->fd, proto_mac_lte, p_mac_lte_info);
1275 /**************************************/
1276 /* OK, now dissect as MAC LTE */
1278 /* Create tvb that starts at actual MAC PDU */
1279 mac_tvb = tvb_new_subset(tvb, offset, -1, tvb_reported_length(tvb)-offset);
1280 dissect_mac_lte(mac_tvb, pinfo, tree);
1286 /* Write the given formatted text to:
1287 - the info column (if pinfo != NULL)
1288 - 1 or 2 other labels (optional)
1290 static void write_pdu_label_and_info(proto_item *ti1, proto_item *ti2,
1291 packet_info *pinfo, const char *format, ...)
1293 #define MAX_INFO_BUFFER 256
1294 static char info_buffer[MAX_INFO_BUFFER];
1298 va_start(ap, format);
1299 g_vsnprintf(info_buffer, MAX_INFO_BUFFER, format, ap);
1302 /* Add to indicated places */
1303 if (pinfo != NULL) {
1304 col_append_str(pinfo->cinfo, COL_INFO, info_buffer);
1307 proto_item_append_text(ti1, "%s", info_buffer);
1310 proto_item_append_text(ti2, "%s", info_buffer);
1314 /* Show extra PHY parameters (if present) */
1315 static void show_extra_phy_parameters(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree,
1316 struct mac_lte_info *p_mac_lte_info)
1319 proto_tree *phy_tree;
1322 if (global_mac_lte_layer_to_show == ShowPHYLayer) {
1323 /* Clear the info column */
1324 col_clear(pinfo->cinfo, COL_INFO);
1327 if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
1328 if (p_mac_lte_info->detailed_phy_info.ul_info.present) {
1331 phy_ti = proto_tree_add_string_format(tree, hf_mac_lte_context_phy_ul,
1332 tvb, 0, 0, "", "UL PHY Context");
1333 phy_tree = proto_item_add_subtree(phy_ti, ett_mac_lte_phy_context);
1334 PROTO_ITEM_SET_GENERATED(phy_ti);
1337 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_modulation_type,
1339 p_mac_lte_info->detailed_phy_info.ul_info.modulation_type);
1340 PROTO_ITEM_SET_GENERATED(ti);
1342 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_tbs_index,
1344 p_mac_lte_info->detailed_phy_info.ul_info.tbs_index);
1345 PROTO_ITEM_SET_GENERATED(ti);
1347 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_resource_block_length,
1349 p_mac_lte_info->detailed_phy_info.ul_info.resource_block_length);
1350 PROTO_ITEM_SET_GENERATED(ti);
1352 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_resource_block_start,
1354 p_mac_lte_info->detailed_phy_info.ul_info.resource_block_start);
1355 PROTO_ITEM_SET_GENERATED(ti);
1357 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_harq_id,
1359 p_mac_lte_info->detailed_phy_info.ul_info.harq_id);
1360 PROTO_ITEM_SET_GENERATED(ti);
1362 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_ndi,
1364 p_mac_lte_info->detailed_phy_info.ul_info.ndi);
1365 PROTO_ITEM_SET_GENERATED(ti);
1368 proto_item_append_text(phy_ti, " (");
1370 write_pdu_label_and_info(phy_ti, NULL,
1371 (global_mac_lte_layer_to_show == ShowPHYLayer) ? pinfo : NULL,
1372 "UL: UEId=%u RNTI=%u %s Tbs_Index=%u RB_len=%u RB_start=%u",
1373 p_mac_lte_info->ueid,
1374 p_mac_lte_info->rnti,
1375 val_to_str_const(p_mac_lte_info->detailed_phy_info.ul_info.modulation_type,
1376 modulation_type_vals, "Unknown"),
1377 p_mac_lte_info->detailed_phy_info.ul_info.tbs_index,
1378 p_mac_lte_info->detailed_phy_info.ul_info.resource_block_length,
1379 p_mac_lte_info->detailed_phy_info.ul_info.resource_block_start);
1381 proto_item_append_text(phy_ti, ")");
1383 /* Don't want columns to be replaced now */
1384 if (global_mac_lte_layer_to_show == ShowPHYLayer) {
1385 col_set_writable(pinfo->cinfo, FALSE);
1390 if (p_mac_lte_info->detailed_phy_info.dl_info.present) {
1393 phy_ti = proto_tree_add_string_format(tree, hf_mac_lte_context_phy_dl,
1394 tvb, 0, 0, "", "DL PHY Context");
1395 phy_tree = proto_item_add_subtree(phy_ti, ett_mac_lte_phy_context);
1396 PROTO_ITEM_SET_GENERATED(phy_ti);
1399 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_dci_format,
1401 p_mac_lte_info->detailed_phy_info.dl_info.dci_format);
1402 PROTO_ITEM_SET_GENERATED(ti);
1404 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_resource_allocation_type,
1406 p_mac_lte_info->detailed_phy_info.dl_info.resource_allocation_type);
1407 PROTO_ITEM_SET_GENERATED(ti);
1409 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_aggregation_level,
1411 p_mac_lte_info->detailed_phy_info.dl_info.aggregation_level);
1412 PROTO_ITEM_SET_GENERATED(ti);
1414 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_mcs_index,
1416 p_mac_lte_info->detailed_phy_info.dl_info.mcs_index);
1417 PROTO_ITEM_SET_GENERATED(ti);
1419 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_redundancy_version_index,
1421 p_mac_lte_info->detailed_phy_info.dl_info.redundancy_version_index);
1422 PROTO_ITEM_SET_GENERATED(ti);
1424 ti = proto_tree_add_boolean(phy_tree, hf_mac_lte_context_phy_dl_retx,
1426 p_mac_lte_info->dl_retx);
1427 PROTO_ITEM_SET_GENERATED(ti);
1429 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_resource_block_length,
1431 p_mac_lte_info->detailed_phy_info.dl_info.resource_block_length);
1432 PROTO_ITEM_SET_GENERATED(ti);
1434 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_crc_status,
1436 p_mac_lte_info->detailed_phy_info.dl_info.crc_status);
1437 PROTO_ITEM_SET_GENERATED(ti);
1439 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_harq_id,
1441 p_mac_lte_info->detailed_phy_info.dl_info.harq_id);
1442 PROTO_ITEM_SET_GENERATED(ti);
1444 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_ndi,
1446 p_mac_lte_info->detailed_phy_info.dl_info.ndi);
1447 PROTO_ITEM_SET_GENERATED(ti);
1449 ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_tb,
1451 p_mac_lte_info->detailed_phy_info.dl_info.transport_block);
1452 PROTO_ITEM_SET_GENERATED(ti);
1455 proto_item_append_text(phy_ti, " (");
1457 write_pdu_label_and_info(phy_ti, NULL,
1458 (global_mac_lte_layer_to_show == ShowPHYLayer) ? pinfo : NULL,
1459 "DL: UEId=%u RNTI=%u DCI_Format=%s Res_Alloc=%u Aggr_Level=%s MCS=%u RV=%u "
1460 "Res_Block_len=%u CRC_status=%s HARQ_id=%u NDI=%u",
1461 p_mac_lte_info->ueid,
1462 p_mac_lte_info->rnti,
1463 val_to_str_const(p_mac_lte_info->detailed_phy_info.dl_info.dci_format,
1464 dci_format_vals, "Unknown"),
1465 p_mac_lte_info->detailed_phy_info.dl_info.resource_allocation_type,
1466 val_to_str_const(p_mac_lte_info->detailed_phy_info.dl_info.aggregation_level,
1467 aggregation_level_vals, "Unknown"),
1468 p_mac_lte_info->detailed_phy_info.dl_info.mcs_index,
1469 p_mac_lte_info->detailed_phy_info.dl_info.redundancy_version_index,
1470 p_mac_lte_info->detailed_phy_info.dl_info.resource_block_length,
1471 val_to_str_const(p_mac_lte_info->detailed_phy_info.dl_info.crc_status,
1472 crc_status_vals, "Unknown"),
1473 p_mac_lte_info->detailed_phy_info.dl_info.harq_id,
1474 p_mac_lte_info->detailed_phy_info.dl_info.ndi);
1475 proto_item_append_text(phy_ti, ")");
1477 /* Don't want columns to be replaced now */
1478 if (global_mac_lte_layer_to_show == ShowPHYLayer) {
1479 col_set_writable(pinfo->cinfo, FALSE);
1486 /* Dissect a single Random Access Reponse body */
1487 static gint dissect_rar_entry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1489 gint offset, guint8 rapid)
1492 guint start_body_offset = offset;
1494 proto_item *rar_body_ti;
1495 proto_tree *rar_body_tree;
1496 proto_tree *ul_grant_tree;
1497 proto_item *ul_grant_ti;
1498 guint16 timing_advance;
1502 /* Create tree for this Body */
1503 rar_body_ti = proto_tree_add_item(tree,
1504 hf_mac_lte_rar_body,
1505 tvb, offset, 0, ENC_ASCII|ENC_NA);
1506 rar_body_tree = proto_item_add_subtree(rar_body_ti, ett_mac_lte_rar_body);
1508 /* Dissect an RAR entry */
1510 /* Check reserved bit */
1511 reserved = (tvb_get_guint8(tvb, offset) & 0x80) >> 7;
1512 ti = proto_tree_add_item(rar_body_tree, hf_mac_lte_rar_reserved2, tvb, offset, 1, ENC_BIG_ENDIAN);
1513 if (reserved != 0) {
1514 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
1515 "RAR body Reserved bit not zero (found 0x%x)", reserved);
1518 /* Timing Advance */
1519 timing_advance = (tvb_get_ntohs(tvb, offset) & 0x7ff0) >> 4;
1520 ti = proto_tree_add_item(rar_body_tree, hf_mac_lte_rar_ta, tvb, offset, 2, ENC_BIG_ENDIAN);
1521 if (timing_advance != 0) {
1522 expert_add_info_format(pinfo, ti, PI_SEQUENCE, (timing_advance <= 31) ? PI_NOTE : PI_WARN,
1523 "RAR Timing advance not zero (%u)", timing_advance);
1528 ul_grant = (tvb_get_ntohl(tvb, offset) & 0x0fffff00) >> 8;
1529 ul_grant_ti = proto_tree_add_item(rar_body_tree, hf_mac_lte_rar_ul_grant, tvb, offset, 3, ENC_BIG_ENDIAN);
1531 /* Break these 20 bits down as described in 36.213, section 6.2 */
1532 /* Create subtree for UL grant break-down */
1533 ul_grant_tree = proto_item_add_subtree(ul_grant_ti, ett_mac_lte_rar_ul_grant);
1535 /* Hopping flag (1 bit) */
1536 proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_hopping,
1537 tvb, offset, 1, ENC_BIG_ENDIAN);
1539 /* Fixed sized resource block assignment (10 bits) */
1540 proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_fsrba,
1541 tvb, offset, 2, ENC_BIG_ENDIAN);
1543 /* Truncated Modulation and coding scheme (4 bits) */
1544 proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_tmcs,
1545 tvb, offset+1, 2, ENC_BIG_ENDIAN);
1547 /* TPC command for scheduled PUSCH (3 bits) */
1548 proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_tcsp,
1549 tvb, offset+2, 1, ENC_BIG_ENDIAN);
1551 /* UL delay (1 bit) */
1552 proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_ul_delay,
1553 tvb, offset+2, 1, ENC_BIG_ENDIAN);
1555 /* CQI request (1 bit) */
1556 proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_cqi_request,
1557 tvb, offset+2, 1, ENC_BIG_ENDIAN);
1561 /* Temporary C-RNTI */
1562 temp_crnti = tvb_get_ntohs(tvb, offset);
1563 proto_tree_add_item(rar_body_tree, hf_mac_lte_rar_temporary_crnti, tvb, offset, 2, ENC_BIG_ENDIAN);
1566 write_pdu_label_and_info(pdu_ti, rar_body_ti, pinfo,
1567 "(RAPID=%u: TA=%u, UL-Grant=%u, Temp C-RNTI=%u) ",
1568 rapid, timing_advance, ul_grant, temp_crnti);
1570 proto_item_set_len(rar_body_ti, offset-start_body_offset);
1576 #define MAX_RAR_PDUS 64
1577 /* Dissect Random Access Reponse (RAR) PDU */
1578 static void dissect_rar(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *pdu_ti,
1579 gint offset, mac_lte_info *p_mac_lte_info, mac_lte_tap_info *tap_info)
1581 gint number_of_rars = 0; /* No of RAR bodies expected following headers */
1582 guint8 *rapids = ep_alloc(MAX_RAR_PDUS * sizeof(guint8));
1583 gboolean backoff_indicator_seen = FALSE;
1584 guint8 backoff_indicator = 0;
1587 proto_tree *rar_headers_tree;
1589 proto_item *rar_headers_ti;
1590 proto_item *padding_length_ti;
1591 int start_headers_offset = offset;
1593 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
1594 "RAR (RA-RNTI=%u, SF=%u) ",
1595 p_mac_lte_info->rnti, p_mac_lte_info->subframeNumber);
1597 /* Create hidden 'virtual root' so can filter on mac-lte.rar */
1598 ti = proto_tree_add_item(tree, hf_mac_lte_rar, tvb, offset, -1, ENC_NA);
1599 PROTO_ITEM_SET_HIDDEN(ti);
1601 /* Create headers tree */
1602 rar_headers_ti = proto_tree_add_item(tree,
1603 hf_mac_lte_rar_headers,
1604 tvb, offset, 0, ENC_ASCII|ENC_NA);
1605 rar_headers_tree = proto_item_add_subtree(rar_headers_ti, ett_mac_lte_rar_headers);
1608 /***************************/
1609 /* Read the header entries */
1611 int start_header_offset = offset;
1612 proto_tree *rar_header_tree;
1613 proto_item *rar_header_ti;
1615 guint8 first_byte = tvb_get_guint8(tvb, offset);
1617 /* Create tree for this header */
1618 rar_header_ti = proto_tree_add_item(rar_headers_tree,
1619 hf_mac_lte_rar_header,
1620 tvb, offset, 0, ENC_ASCII|ENC_NA);
1621 rar_header_tree = proto_item_add_subtree(rar_header_ti, ett_mac_lte_rar_header);
1624 extension = (first_byte & 0x80) >> 7;
1625 proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_extension, tvb, offset, 1, ENC_BIG_ENDIAN);
1628 type_value = (first_byte & 0x40) >> 6;
1629 proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_t, tvb, offset, 1, ENC_BIG_ENDIAN);
1631 if (type_value == 0) {
1632 /* Backoff Indicator (BI) case */
1638 /* 2 Reserved bits */
1639 reserved = (tvb_get_guint8(tvb, offset) & 0x30) >> 4;
1640 tii = proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
1641 if (reserved != 0) {
1642 expert_add_info_format(pinfo, tii, PI_MALFORMED, PI_ERROR,
1643 "RAR header Reserved bits not zero (found 0x%x)", reserved);
1646 /* Backoff Indicator */
1647 backoff_indicator = tvb_get_guint8(tvb, offset) & 0x0f;
1648 bi_ti = proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_bi, tvb, offset, 1, ENC_BIG_ENDIAN);
1650 /* As of March 2009 spec, it must be first, and may only appear once */
1651 if (backoff_indicator_seen) {
1652 expert_add_info_format(pinfo, bi_ti, PI_MALFORMED, PI_ERROR,
1653 "MAC RAR PDU has > 1 Backoff Indicator subheader present");
1655 backoff_indicator_seen = TRUE;
1657 write_pdu_label_and_info(pdu_ti, rar_header_ti, pinfo,
1658 "(Backoff Indicator=%sms)",
1659 val_to_str_const(backoff_indicator, rar_bi_vals, "Illegal-value "));
1661 /* If present, it must be the first subheader */
1662 if (number_of_rars > 0) {
1663 expert_add_info_format(pinfo, bi_ti, PI_MALFORMED, PI_WARN,
1664 "Backoff Indicator must appear as first subheader");
1670 /* TODO: complain if the same RAPID appears twice in same frame? */
1671 rapids[number_of_rars] = tvb_get_guint8(tvb, offset) & 0x3f;
1672 proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_rapid, tvb, offset, 1, ENC_BIG_ENDIAN);
1674 proto_item_append_text(rar_header_ti, "(RAPID=%u)", rapids[number_of_rars]);
1681 /* Finalise length of header tree selection */
1682 proto_item_set_len(rar_header_ti, offset - start_header_offset);
1684 } while (extension && number_of_rars < MAX_RAR_PDUS);
1686 /* Append summary to headers root */
1687 proto_item_append_text(rar_headers_ti, " (%u RARs", number_of_rars);
1688 if (backoff_indicator_seen) {
1689 proto_item_append_text(rar_headers_ti, ", BI=%sms)",
1690 val_to_str_const(backoff_indicator, rar_bi_vals, "Illegal-value "));
1693 proto_item_append_text(rar_headers_ti, ")");
1696 /* Set length for headers root */
1697 proto_item_set_len(rar_headers_ti, offset-start_headers_offset);
1700 /***************************/
1701 /* Read any indicated RARs */
1702 for (n=0; n < number_of_rars; n++) {
1703 offset = dissect_rar_entry(tvb, pinfo, tree, pdu_ti, offset, rapids[n]);
1706 /* Update TAP info */
1707 tap_info->number_of_rars += number_of_rars;
1709 /* Padding may follow */
1710 if (tvb_length_remaining(tvb, offset) > 0) {
1711 proto_tree_add_item(tree, hf_mac_lte_padding_data,
1712 tvb, offset, -1, ENC_NA);
1714 padding_length_ti = proto_tree_add_int(tree, hf_mac_lte_padding_length,
1716 p_mac_lte_info->length - offset);
1717 PROTO_ITEM_SET_GENERATED(padding_length_ti);
1719 /* Update padding bytes in stats */
1720 tap_info->padding_bytes += (p_mac_lte_info->length - offset);
1724 /* Dissect BCH PDU */
1725 static void dissect_bch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1727 int offset, mac_lte_info *p_mac_lte_info)
1731 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
1732 "BCH PDU (%u bytes, on %s transport) ",
1733 tvb_length_remaining(tvb, offset),
1734 val_to_str_const(p_mac_lte_info->rntiType,
1735 bch_transport_channel_vals,
1738 /* Show which transport layer it came in on (inferred from RNTI type) */
1739 ti = proto_tree_add_uint(tree, hf_mac_lte_context_bch_transport_channel,
1740 tvb, offset, 0, p_mac_lte_info->rntiType);
1741 PROTO_ITEM_SET_GENERATED(ti);
1743 /****************************************/
1744 /* Whole frame is BCH data */
1747 ti = proto_tree_add_item(tree, hf_mac_lte_bch_pdu,
1748 tvb, offset, -1, ENC_NA);
1750 if (global_mac_lte_attempt_rrc_decode) {
1751 /* Attempt to decode payload using LTE RRC dissector */
1752 tvbuff_t *rrc_tvb = tvb_new_subset(tvb, offset, -1, tvb_length_remaining(tvb, offset));
1754 /* Get appropriate dissector handle */
1755 dissector_handle_t protocol_handle = 0;
1756 if (p_mac_lte_info->rntiType == SI_RNTI) {
1757 protocol_handle = find_dissector("lte_rrc.bcch_dl_sch");
1760 protocol_handle = find_dissector("lte_rrc.bcch_bch");
1763 /* Hide raw view of bytes */
1764 PROTO_ITEM_SET_HIDDEN(ti);
1766 call_with_catch_all(protocol_handle, rrc_tvb, pinfo, tree);
1769 /* Check that this *is* downlink! */
1770 if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
1771 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
1772 "BCH data should not be received in Uplink!");
1777 /* Dissect PCH PDU */
1778 static void dissect_pch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1779 proto_item *pdu_ti, int offset, guint8 direction)
1783 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
1784 "PCH PDU (%u bytes) ",
1785 tvb_length_remaining(tvb, offset));
1787 /****************************************/
1788 /* Whole frame is PCH data */
1790 /* Always show as raw data */
1791 ti = proto_tree_add_item(tree, hf_mac_lte_pch_pdu,
1792 tvb, offset, -1, ENC_NA);
1794 if (global_mac_lte_attempt_rrc_decode) {
1796 /* Attempt to decode payload using LTE RRC dissector */
1797 tvbuff_t *rrc_tvb = tvb_new_subset(tvb, offset, -1, tvb_length_remaining(tvb, offset));
1799 /* Get appropriate dissector handle */
1800 dissector_handle_t protocol_handle = find_dissector("lte-rrc.pcch");
1802 /* Hide raw view of bytes */
1803 PROTO_ITEM_SET_HIDDEN(ti);
1805 /* Call it (catch exceptions so that stats will be updated) */
1807 call_dissector_only(protocol_handle, rrc_tvb, pinfo, tree);
1814 /* Check that this *is* downlink! */
1815 if (direction == DIRECTION_UPLINK) {
1816 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
1817 "PCH data should not be received in Uplink!");
1822 /* Does this header entry correspond to a fixed-sized control element? */
1823 static int is_fixed_sized_control_element(guint8 lcid, guint8 direction)
1825 if (direction == DIRECTION_UPLINK) {
1828 case POWER_HEADROOM_REPORT_LCID:
1830 case TRUNCATED_BSR_LCID:
1831 case SHORT_BSR_LCID:
1840 /* Assume Downlink */
1842 case ACTIVATION_DEACTIVATION_LCID:
1843 case UE_CONTENTION_RESOLUTION_IDENTITY_LCID:
1844 case TIMING_ADVANCE_LCID:
1845 case DRX_COMMAND_LCID:
1855 /* Is this a BSR report header? */
1856 static int is_bsr_lcid(guint8 lcid)
1858 return ((lcid == TRUNCATED_BSR_LCID) ||
1859 (lcid == SHORT_BSR_LCID) ||
1860 (lcid == LONG_BSR_LCID));
1864 /* Helper function to call RLC dissector for SDUs (where channel params are known) */
1865 static void call_rlc_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1867 int offset, guint16 data_length,
1868 guint8 mode, guint8 direction, guint16 ueid,
1869 guint16 channelType, guint16 channelId,
1870 guint8 UMSequenceNumberLength,
1873 tvbuff_t *srb_tvb = tvb_new_subset(tvb, offset, data_length, data_length);
1874 struct rlc_lte_info *p_rlc_lte_info;
1876 /* Get RLC dissector handle */
1877 volatile dissector_handle_t protocol_handle = find_dissector("rlc-lte");
1879 /* Resuse or create RLC info */
1880 p_rlc_lte_info = p_get_proto_data(pinfo->fd, proto_rlc_lte);
1881 if (p_rlc_lte_info == NULL) {
1882 p_rlc_lte_info = se_alloc0(sizeof(struct rlc_lte_info));
1885 /* Fill in struct details for srb channels */
1886 p_rlc_lte_info->rlcMode = mode;
1887 p_rlc_lte_info->direction = direction;
1888 p_rlc_lte_info->priority = priority;
1889 p_rlc_lte_info->ueid = ueid;
1890 p_rlc_lte_info->channelType = channelType;
1891 p_rlc_lte_info->channelId = channelId;
1892 p_rlc_lte_info->pduLength = data_length;
1893 p_rlc_lte_info->UMSequenceNumberLength = UMSequenceNumberLength;
1895 /* Store info in packet */
1896 p_add_proto_data(pinfo->fd, proto_rlc_lte, p_rlc_lte_info);
1898 if (global_mac_lte_layer_to_show != ShowRLCLayer) {
1899 /* Don't want these columns replaced */
1900 col_set_writable(pinfo->cinfo, FALSE);
1903 /* Clear info column before first RLC PDU */
1904 if (s_number_of_rlc_pdus_shown == 0) {
1905 col_clear(pinfo->cinfo, COL_INFO);
1908 /* Add a separator and protect column contents here */
1909 write_pdu_label_and_info(pdu_ti, NULL, pinfo, " || ");
1910 col_set_fence(pinfo->cinfo, COL_INFO);
1913 s_number_of_rlc_pdus_shown++;
1915 /* Call it (catch exceptions so that stats will be updated) */
1917 call_dissector_only(protocol_handle, srb_tvb, pinfo, tree);
1923 /* Let columns be written to again */
1924 col_set_writable(pinfo->cinfo, TRUE);
1928 /* For DL frames, look for previous Tx. Add link back if found */
1929 static void TrackReportedDLHARQResend(packet_info *pinfo, tvbuff_t *tvb, volatile int length,
1930 proto_tree *tree, mac_lte_info *p_mac_lte_info)
1932 DLHARQResult *result = NULL;
1933 DLHARQResult *original_result = NULL;
1935 /* If don't have detailed DL PHy info, just give up */
1936 if (!p_mac_lte_info->detailed_phy_info.dl_info.present) {
1940 /* TDD may not work... */
1942 if (!pinfo->fd->flags.visited) {
1943 /* First time, so set result and update DL harq table */
1944 LastFrameData *lastData = NULL;
1945 LastFrameData *thisData = NULL;
1947 DLHarqBuffers *ueData;
1949 /* Read these for convenience */
1950 guint8 harq_id = p_mac_lte_info->detailed_phy_info.dl_info.harq_id;
1951 guint8 transport_block = p_mac_lte_info->detailed_phy_info.dl_info.transport_block;
1953 /* Check harq-id bounds, give up if invalid */
1954 if ((harq_id >= 15) || (transport_block+1 > 2)) {
1958 /* Look up entry for this UE/RNTI */
1959 ueData = g_hash_table_lookup(mac_lte_dl_harq_hash, GUINT_TO_POINTER((guint)p_mac_lte_info->rnti));
1961 if (ueData != NULL) {
1962 /* Get previous info for this harq-id */
1963 lastData = &(ueData->harqid[transport_block][harq_id]);
1964 if (lastData->inUse) {
1965 /* Compare time difference, ndi, data to see if this looks like a retx */
1966 if ((length == lastData->length) &&
1967 (p_mac_lte_info->detailed_phy_info.dl_info.ndi == lastData->ndi) &&
1968 tvb_memeql(tvb, 0, lastData->data, MIN(lastData->length, MAX_EXPECTED_PDU_LENGTH)) == 0) {
1970 /* Work out gap between frames */
1971 gint seconds_between_packets = (gint)
1972 (pinfo->fd->abs_ts.secs - lastData->received_time.secs);
1973 gint nseconds_between_packets =
1974 pinfo->fd->abs_ts.nsecs - lastData->received_time.nsecs;
1976 /* Round difference to nearest millisecond */
1977 gint total_gap = (seconds_between_packets*1000) +
1978 ((nseconds_between_packets+500000) / 1000000);
1980 /* Expect to be within (say) 8-13 subframes since previous */
1981 if ((total_gap >= 8) && (total_gap <= 13)) {
1983 /* Resend detected! Store result pointing back. */
1984 result = se_alloc0(sizeof(DLHARQResult));
1985 result->previousSet = TRUE;
1986 result->previousFrameNum = lastData->framenum;
1987 result->timeSincePreviousFrame = total_gap;
1988 g_hash_table_insert(mac_lte_dl_harq_result_hash, GUINT_TO_POINTER(pinfo->fd->num), result);
1990 /* Now make previous frame point forward to here */
1991 original_result = g_hash_table_lookup(mac_lte_dl_harq_result_hash, GUINT_TO_POINTER(lastData->framenum));
1992 if (original_result == NULL) {
1993 original_result = se_alloc0(sizeof(ULHARQResult));
1994 g_hash_table_insert(mac_lte_dl_harq_result_hash, GUINT_TO_POINTER(lastData->framenum), original_result);
1996 original_result->nextSet = TRUE;
1997 original_result->nextFrameNum = pinfo->fd->num;
1998 original_result->timeToNextFrame = total_gap;
2004 /* Allocate entry in table for this UE/RNTI */
2005 ueData = se_alloc0(sizeof(DLHarqBuffers));
2006 g_hash_table_insert(mac_lte_dl_harq_hash, GUINT_TO_POINTER((guint)p_mac_lte_info->rnti), ueData);
2009 /* Store this frame's details in table */
2010 thisData = &(ueData->harqid[transport_block][harq_id]);
2011 thisData->inUse = TRUE;
2012 thisData->length = length;
2013 tvb_memcpy(tvb, thisData->data, 0, MIN(thisData->length, MAX_EXPECTED_PDU_LENGTH));
2014 thisData->ndi = p_mac_lte_info->detailed_phy_info.dl_info.ndi;
2015 thisData->framenum = pinfo->fd->num;
2016 thisData->received_time = pinfo->fd->abs_ts;
2019 /* Not first time, so just set whats already stored in result */
2020 result = g_hash_table_lookup(mac_lte_dl_harq_result_hash, GUINT_TO_POINTER(pinfo->fd->num));
2024 /***************************************************/
2025 /* Show link back to original frame (if available) */
2026 if (result != NULL) {
2027 if (result->previousSet) {
2029 proto_item *original_ti = proto_tree_add_uint(tree, hf_mac_lte_dl_harq_resend_original_frame,
2030 tvb, 0, 0, result->previousFrameNum);
2031 PROTO_ITEM_SET_GENERATED(original_ti);
2033 gap_ti = proto_tree_add_uint(tree, hf_mac_lte_dl_harq_resend_time_since_previous_frame,
2034 tvb, 0, 0, result->timeSincePreviousFrame);
2035 PROTO_ITEM_SET_GENERATED(gap_ti);
2038 if (result->nextSet) {
2040 proto_item *next_ti = proto_tree_add_uint(tree, hf_mac_lte_dl_harq_resend_next_frame,
2041 tvb, 0, 0, result->nextFrameNum);
2042 PROTO_ITEM_SET_GENERATED(next_ti);
2044 gap_ti = proto_tree_add_uint(tree, hf_mac_lte_dl_harq_resend_time_until_next_frame,
2045 tvb, 0, 0, result->timeToNextFrame);
2046 PROTO_ITEM_SET_GENERATED(gap_ti);
2053 /* Return TRUE if the given packet is thought to be a retx */
2054 int is_mac_lte_frame_retx(packet_info *pinfo, guint8 direction)
2056 struct mac_lte_info *p_mac_lte_info = p_get_proto_data(pinfo->fd, proto_mac_lte);
2058 if (direction == DIRECTION_UPLINK) {
2059 /* For UL, retx count is stored in per-packet struct */
2060 return ((p_mac_lte_info != NULL) && (p_mac_lte_info->reTxCount > 0));
2063 /* Use answer if told directly */
2064 if (p_mac_lte_info->dl_retx == dl_retx_yes) {
2068 /* Otherwise look up in table */
2069 DLHARQResult *result = g_hash_table_lookup(mac_lte_dl_harq_result_hash, GUINT_TO_POINTER(pinfo->fd->num));
2070 return ((result != NULL) && result->previousSet);
2076 /* Track UL frames, so that when a retx is indicated, we can search for
2077 the original tx. We will either find it, and provide a link back to it,
2078 or flag that we couldn't find as an expert error */
2079 static void TrackReportedULHARQResend(packet_info *pinfo, tvbuff_t *tvb, volatile int offset,
2080 proto_tree *tree, mac_lte_info *p_mac_lte_info,
2081 proto_item *retx_ti)
2083 ULHARQResult *result = NULL;
2085 /* If don't have detailed DL PHY info, just give up */
2086 if (!p_mac_lte_info->detailed_phy_info.ul_info.present) {
2090 /* Give up if harqid is out of range */
2091 if (p_mac_lte_info->detailed_phy_info.ul_info.harq_id >= 8) {
2095 if (!pinfo->fd->flags.visited) {
2096 /* First time, so set result and update UL harq table */
2097 LastFrameData *lastData = NULL;
2098 LastFrameData *thisData = NULL;
2100 /* Look up entry for this UE/RNTI */
2101 ULHarqBuffers *ueData =
2102 g_hash_table_lookup(mac_lte_ul_harq_hash, GUINT_TO_POINTER((guint)p_mac_lte_info->rnti));
2103 if (ueData != NULL) {
2104 if (p_mac_lte_info->reTxCount >= 1) {
2105 /* Looking for frame previously on this harq-id */
2106 lastData = &(ueData->harqid[p_mac_lte_info->detailed_phy_info.ul_info.harq_id]);
2107 if (lastData->inUse) {
2108 /* Compare time, sf, data to see if this looks like a retx */
2109 if ((tvb_length_remaining(tvb, offset) == lastData->length) &&
2110 (p_mac_lte_info->detailed_phy_info.ul_info.ndi == lastData->ndi) &&
2111 tvb_memeql(tvb, offset, lastData->data, MIN(lastData->length, MAX_EXPECTED_PDU_LENGTH)) == 0) {
2113 /* Work out gap between frames */
2114 gint seconds_between_packets = (gint)
2115 (pinfo->fd->abs_ts.secs - lastData->received_time.secs);
2116 gint nseconds_between_packets =
2117 pinfo->fd->abs_ts.nsecs - lastData->received_time.nsecs;
2119 /* Round to nearest ms */
2120 gint total_gap = (seconds_between_packets*1000) +
2121 ((nseconds_between_packets+500000) / 1000000);
2123 /* Could be as many as max-tx (which we don't know) * 8ms ago.
2124 32 is the most I've seen... */
2125 if (total_gap <= 33) {
2126 ULHARQResult *original_result = NULL;
2128 /* Original detected!!! Store result pointing back */
2129 result = se_alloc0(sizeof(ULHARQResult));
2130 result->previousSet = TRUE;
2131 result->previousFrameNum = lastData->framenum;
2132 result->timeSincePreviousFrame = total_gap;
2133 g_hash_table_insert(mac_lte_ul_harq_result_hash, GUINT_TO_POINTER(pinfo->fd->num), result);
2135 /* Now make previous frame point forward to here */
2136 original_result = g_hash_table_lookup(mac_lte_ul_harq_result_hash, GUINT_TO_POINTER(lastData->framenum));
2137 if (original_result == NULL) {
2138 original_result = se_alloc0(sizeof(ULHARQResult));
2139 g_hash_table_insert(mac_lte_ul_harq_result_hash, GUINT_TO_POINTER(lastData->framenum), original_result);
2141 original_result->nextSet = TRUE;
2142 original_result->nextFrameNum = pinfo->fd->num;
2143 original_result->timeToNextFrame = total_gap;
2150 /* Allocate entry in table for this UE/RNTI */
2151 ueData = se_alloc0(sizeof(ULHarqBuffers));
2152 g_hash_table_insert(mac_lte_ul_harq_hash, GUINT_TO_POINTER((guint)p_mac_lte_info->rnti), ueData);
2155 /* Store this frame's details in table */
2156 thisData = &(ueData->harqid[p_mac_lte_info->detailed_phy_info.ul_info.harq_id]);
2157 thisData->inUse = TRUE;
2158 thisData->length = tvb_length_remaining(tvb, offset);
2159 tvb_memcpy(tvb, thisData->data, offset, MIN(thisData->length, MAX_EXPECTED_PDU_LENGTH));
2160 thisData->ndi = p_mac_lte_info->detailed_phy_info.ul_info.ndi;
2161 thisData->framenum = pinfo->fd->num;
2162 thisData->received_time = pinfo->fd->abs_ts;
2165 /* Not first time, so just get whats already stored in result */
2166 result = g_hash_table_lookup(mac_lte_ul_harq_result_hash, GUINT_TO_POINTER(pinfo->fd->num));
2169 /* Show any link back to previous Tx */
2170 if (retx_ti != NULL) {
2171 if (result != NULL) {
2172 if (result->previousSet) {
2173 proto_item *original_ti, *gap_ti;
2175 original_ti = proto_tree_add_uint(tree, hf_mac_lte_ul_harq_resend_original_frame,
2176 tvb, 0, 0, result->previousFrameNum);
2177 PROTO_ITEM_SET_GENERATED(original_ti);
2179 gap_ti = proto_tree_add_uint(tree, hf_mac_lte_ul_harq_resend_time_since_previous_frame,
2180 tvb, 0, 0, result->timeSincePreviousFrame);
2181 PROTO_ITEM_SET_GENERATED(gap_ti);
2185 expert_add_info_format(pinfo, retx_ti, PI_SEQUENCE, PI_ERROR,
2186 "Original Tx of UL frame not found (UE %u) !!", p_mac_lte_info->ueid);
2190 /* Show link forward to any known next Tx */
2191 if ((result != NULL) && result->nextSet) {
2192 proto_item *next_ti, *gap_ti;
2194 next_ti = proto_tree_add_uint(tree, hf_mac_lte_ul_harq_resend_next_frame,
2195 tvb, 0, 0, result->nextFrameNum);
2196 expert_add_info_format(pinfo, next_ti, PI_SEQUENCE, PI_WARN,
2197 "UL MAC PDU (UE %u) needed to be retransmitted", p_mac_lte_info->ueid);
2199 PROTO_ITEM_SET_GENERATED(next_ti);
2201 gap_ti = proto_tree_add_uint(tree, hf_mac_lte_ul_harq_resend_time_until_next_frame,
2202 tvb, 0, 0, result->timeToNextFrame);
2203 PROTO_ITEM_SET_GENERATED(gap_ti);
2208 /* Look up SRResult associated with a given frame. Will create one if necessary
2209 if can_create is set */
2210 static SRResult *GetSRResult(guint32 frameNum, gboolean can_create)
2213 result = g_hash_table_lookup(mac_lte_sr_request_hash, GUINT_TO_POINTER(frameNum));
2215 if ((result == NULL) && can_create) {
2216 result = se_alloc0(sizeof(SRResult));
2217 g_hash_table_insert(mac_lte_sr_request_hash, GUINT_TO_POINTER((guint)frameNum), result);
2223 /* Keep track of SR requests, failures and related grants, in order to show them
2224 as generated fields in these frames */
2225 static void TrackSRInfo(SREvent event, packet_info *pinfo, proto_tree *tree,
2226 tvbuff_t *tvb, mac_lte_info *p_mac_lte_info, gint idx, proto_item *event_ti)
2228 SRResult *result = NULL;
2230 SRResult *resultForSRFrame = NULL;
2236 /* Get appropriate identifiers */
2237 if (event == SR_Request) {
2238 rnti = p_mac_lte_info->oob_rnti[idx];
2239 ueid = p_mac_lte_info->oob_ueid[idx];
2242 rnti = p_mac_lte_info->rnti;
2243 ueid = p_mac_lte_info->ueid;
2246 /* Create state for this RNTI if necessary */
2247 state = g_hash_table_lookup(mac_lte_ue_sr_state, GUINT_TO_POINTER((guint)rnti));
2248 if (state == NULL) {
2249 /* Allocate status for this RNTI */
2250 state = se_alloc(sizeof(SRState));
2251 state->status = None;
2252 g_hash_table_insert(mac_lte_ue_sr_state, GUINT_TO_POINTER((guint)rnti), state);
2255 /* First time through - update state with new info */
2256 if (!pinfo->fd->flags.visited) {
2257 guint32 timeSinceRequest;
2259 /* Store time of request */
2260 if (event == SR_Request) {
2261 state->requestTime = pinfo->fd->abs_ts;
2264 switch (state->status) {
2268 /* Got another grant - fine */
2271 state->lastGrantFramenum = pinfo->fd->num;
2275 /* Sent an SR - fine */
2278 state->status = SR_Outstanding;
2279 state->lastSRFramenum = pinfo->fd->num;
2283 /* This is an error, since we hadn't send an SR... */
2284 result = GetSRResult(pinfo->fd->num, TRUE);
2285 result->type = InvalidSREvent;
2286 result->status = None;
2287 result->event = SR_Failure;
2292 case SR_Outstanding:
2293 timeSinceRequest = (guint32)(((pinfo->fd->abs_ts.secs - state->requestTime.secs) * 1000) +
2294 ((pinfo->fd->abs_ts.nsecs - state->requestTime.nsecs) / 1000000));
2298 /* Got grant we were waiting for, so state goes to None */
2301 state->status = None;
2303 /* Set result info */
2304 result = GetSRResult(pinfo->fd->num, TRUE);
2305 result->type = GrantAnsweringSR;
2306 result->frameNum = state->lastSRFramenum;
2307 result->timeDifference = timeSinceRequest;
2309 /* Also set forward link for SR */
2310 resultForSRFrame = GetSRResult(state->lastSRFramenum, TRUE);
2311 resultForSRFrame->type = SRLeadingToGrant;
2312 resultForSRFrame->frameNum = pinfo->fd->num;
2313 resultForSRFrame->timeDifference = timeSinceRequest;
2317 /* Another request when already have one pending */
2318 result = GetSRResult(pinfo->fd->num, TRUE);
2319 result->type = InvalidSREvent;
2320 result->status = SR_Outstanding;
2321 result->event = SR_Request;
2325 /* We sent an SR but it failed */
2328 state->status = SR_Failed;
2330 /* Set result info for failure frame */
2331 result = GetSRResult(pinfo->fd->num, TRUE);
2332 result->type = FailureAnsweringSR;
2333 result->frameNum = state->lastSRFramenum;
2334 result->timeDifference = timeSinceRequest;
2336 /* Also set forward link for SR */
2337 resultForSRFrame = GetSRResult(state->lastSRFramenum, TRUE);
2338 resultForSRFrame->type = SRLeadingToFailure;
2339 resultForSRFrame->frameNum = pinfo->fd->num;
2340 resultForSRFrame->timeDifference = timeSinceRequest;
2348 /* Got a grant, presumably after a subsequent RACH - fine */
2351 state->status = None;
2355 /* Tried another SR after previous one failed.
2356 Presumably a subsequent RACH was tried in-between... */
2358 state->status = SR_Outstanding;
2360 result = GetSRResult(pinfo->fd->num, TRUE);
2361 result->status = SR_Outstanding;
2362 result->event = SR_Request;
2366 /* 2 failures in a row.... */
2367 result = GetSRResult(pinfo->fd->num, TRUE);
2368 result->type = InvalidSREvent;
2369 result->status = SR_Failed;
2370 result->event = SR_Failure;
2377 /* Get stored result for this frame */
2378 result = GetSRResult(pinfo->fd->num, FALSE);
2379 if (result == NULL) {
2380 /* For an SR frame, there should always be either a PDCCH grant or indication
2381 that the SR has failed */
2382 if (event == SR_Request) {
2383 expert_add_info_format(pinfo, event_ti, PI_SEQUENCE, PI_ERROR,
2384 "UE %u: SR results in neither a grant nor a failure indication",
2391 /* Show result info */
2392 switch (result->type) {
2393 case GrantAnsweringSR:
2394 ti = proto_tree_add_uint(tree, hf_mac_lte_grant_answering_sr,
2395 tvb, 0, 0, result->frameNum);
2396 PROTO_ITEM_SET_GENERATED(ti);
2397 ti = proto_tree_add_uint(tree, hf_mac_lte_sr_time_since_request,
2398 tvb, 0, 0, result->timeDifference);
2399 PROTO_ITEM_SET_GENERATED(ti);
2402 case FailureAnsweringSR:
2403 ti = proto_tree_add_uint(tree, hf_mac_lte_failure_answering_sr,
2404 tvb, 0, 0, result->frameNum);
2405 PROTO_ITEM_SET_GENERATED(ti);
2406 ti = proto_tree_add_uint(tree, hf_mac_lte_sr_time_since_request,
2407 tvb, 0, 0, result->timeDifference);
2408 PROTO_ITEM_SET_GENERATED(ti);
2411 case SRLeadingToGrant:
2412 ti = proto_tree_add_uint(tree, hf_mac_lte_sr_leading_to_grant,
2413 tvb, 0, 0, result->frameNum);
2414 PROTO_ITEM_SET_GENERATED(ti);
2415 ti = proto_tree_add_uint(tree, hf_mac_lte_sr_time_until_answer,
2416 tvb, 0, 0, result->timeDifference);
2417 PROTO_ITEM_SET_GENERATED(ti);
2421 case SRLeadingToFailure:
2422 ti = proto_tree_add_uint(tree, hf_mac_lte_sr_leading_to_failure,
2423 tvb, 0, 0, result->frameNum);
2424 PROTO_ITEM_SET_GENERATED(ti);
2425 ti = proto_tree_add_uint(tree, hf_mac_lte_sr_time_until_answer,
2426 tvb, 0, 0, result->timeDifference);
2427 PROTO_ITEM_SET_GENERATED(ti);
2430 case InvalidSREvent:
2431 ti = proto_tree_add_none_format(tree, hf_mac_lte_sr_invalid_event,
2432 tvb, 0, 0, "UE %u: Invalid SR event - state=%s, event=%s",
2434 val_to_str_const(result->status, sr_status_vals, "Unknown"),
2435 val_to_str_const(result->event, sr_event_vals, "Unknown"));
2436 PROTO_ITEM_SET_GENERATED(ti);
2437 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_ERROR,
2438 "Invalid SR event for UE %u (C-RNTI %u) - state=%s, event=%s",
2440 val_to_str_const(result->status, sr_status_vals, "Unknown"),
2441 val_to_str_const(result->event, sr_event_vals, "Unknown"));
2447 /********************************************************/
2448 /* Count number of UEs/TTI (in both directions) */
2449 /********************************************************/
2451 /* For keeping track during first pass */
2452 typedef struct tti_info_t {
2454 nstime_t ttiStartTime;
2458 static tti_info_t UL_tti_info;
2459 static tti_info_t DL_tti_info;
2461 /* For associating with frame and displaying */
2462 typedef struct TTIInfoResult_t {
2466 /* This table stores (FrameNumber -> *TTIInfoResult_t). It is assigned during the first
2467 pass and used thereafter */
2468 static GHashTable *mac_lte_tti_info_result_hash = NULL;
2471 /* Work out which UE this is within TTI (within direction). Return answer */
2472 static guint16 count_ues_tti(mac_lte_info *p_mac_lte_info, packet_info *pinfo)
2474 gboolean same_tti = FALSE;
2475 tti_info_t *tti_info;
2477 /* Just return any previous result */
2478 TTIInfoResult_t *result = g_hash_table_lookup(mac_lte_tti_info_result_hash, GUINT_TO_POINTER(pinfo->fd->num));
2479 if (result != NULL) {
2480 return result->ues_in_tti;
2483 /* Set tti_info based upon direction */
2484 if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
2485 tti_info = &UL_tti_info;
2488 tti_info = &DL_tti_info;
2491 /* Work out if we are still in the same tti as before */
2492 if (tti_info->subframe == p_mac_lte_info->subframeNumber) {
2493 gint seconds_between_packets = (gint)
2494 (pinfo->fd->abs_ts.secs - tti_info->ttiStartTime.secs);
2495 gint nseconds_between_packets =
2496 pinfo->fd->abs_ts.nsecs - tti_info->ttiStartTime.nsecs;
2498 /* Round difference to nearest microsecond */
2499 gint total_us_gap = (seconds_between_packets*1000000) +
2500 ((nseconds_between_packets+500) / 1000);
2502 if (total_us_gap < 1000) {
2507 /* Update global state */
2509 tti_info->subframe = p_mac_lte_info->subframeNumber;
2510 tti_info->ttiStartTime = pinfo->fd->abs_ts;
2511 tti_info->ues_in_tti = 1;
2514 tti_info->ues_in_tti++;
2517 /* Set result state for this frame */
2518 result = se_alloc(sizeof(TTIInfoResult_t));
2519 result->ues_in_tti = tti_info->ues_in_tti;
2520 g_hash_table_insert(mac_lte_tti_info_result_hash,
2521 GUINT_TO_POINTER(pinfo->fd->num), result);
2523 return tti_info->ues_in_tti;
2527 /* Show which UE this is (within direction) for this TTI */
2528 static void show_ues_tti(packet_info *pinfo, mac_lte_info *p_mac_lte_info, tvbuff_t *tvb, proto_tree *context_tree)
2530 /* Look up result */
2531 TTIInfoResult_t *result = g_hash_table_lookup(mac_lte_tti_info_result_hash, GUINT_TO_POINTER(pinfo->fd->num));
2532 if (result != NULL) {
2533 proto_item *ti = proto_tree_add_uint(context_tree,
2534 (p_mac_lte_info->direction == DIRECTION_UPLINK) ?
2535 hf_mac_lte_ues_ul_per_tti :
2536 hf_mac_lte_ues_dl_per_tti,
2537 tvb, 0, 0, result->ues_in_tti);
2538 PROTO_ITEM_SET_GENERATED(ti);
2544 /* Lookup channel details for lcid */
2545 static void lookup_rlc_channel_from_lcid(guint8 lcid,
2546 rlc_channel_type_t *rlc_channel_type,
2547 guint8 *UM_seqnum_length,
2550 /* Zero params (in case no match is found) */
2551 *rlc_channel_type = rlcRaw;
2552 *UM_seqnum_length = 0;
2555 if (global_mac_lte_lcid_drb_source == (int)FromStaticTable) {
2557 /* Look up in static (UAT) table */
2559 for (m=0; m < num_lcid_drb_mappings; m++) {
2560 if (lcid == lcid_drb_mappings[m].lcid) {
2562 *rlc_channel_type = lcid_drb_mappings[m].channel_type;
2564 /* Set UM_seqnum_length */
2565 switch (*rlc_channel_type) {
2567 *UM_seqnum_length = 5;
2570 *UM_seqnum_length = 10;
2577 *drb_id = lcid_drb_mappings[m].drbid;
2583 /* Look up setting gleaned from configuration protocol */
2584 if (!dynamic_lcid_drb_mapping[lcid].valid) {
2588 *rlc_channel_type = dynamic_lcid_drb_mapping[lcid].channel_type;
2590 /* Set UM_seqnum_length */
2591 switch (*rlc_channel_type) {
2593 *UM_seqnum_length = 5;
2596 *UM_seqnum_length = 10;
2603 *drb_id = dynamic_lcid_drb_mapping[lcid].drbid;
2609 #define MAX_HEADERS_IN_PDU 1024
2611 /* UL-SCH and DL-SCH formats have much in common, so handle them in a common
2613 static void dissect_ulsch_or_dlsch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2615 volatile guint32 offset, guint8 direction,
2616 mac_lte_info *p_mac_lte_info, mac_lte_tap_info *tap_info,
2617 proto_item *retx_ti,
2618 proto_tree *context_tree)
2622 proto_item *truncated_ti;
2623 proto_item *padding_length_ti;
2624 proto_item *hidden_root_ti;
2626 /* Keep track of LCIDs and lengths as we dissect the header */
2627 volatile guint16 number_of_headers = 0;
2628 guint8 lcids[MAX_HEADERS_IN_PDU];
2629 gint16 pdu_lengths[MAX_HEADERS_IN_PDU];
2631 proto_item *pdu_header_ti;
2632 proto_tree *pdu_header_tree;
2634 gboolean have_seen_data_header = FALSE;
2635 guint8 number_of_padding_subheaders = 0;
2636 gboolean have_seen_non_padding_control = FALSE;
2637 gboolean have_seen_bsr = FALSE;
2638 gboolean expecting_body_data = FALSE;
2639 volatile guint32 is_truncated = FALSE;
2641 /* Maintain/show UEs/TTI count */
2642 tap_info->ueInTTI = count_ues_tti(p_mac_lte_info, pinfo);
2643 show_ues_tti(pinfo, p_mac_lte_info, tvb, context_tree);
2645 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
2646 "%s: (SF=%u) UEId=%-3u ",
2647 (direction == DIRECTION_UPLINK) ? "UL-SCH" : "DL-SCH",
2648 p_mac_lte_info->subframeNumber,
2649 p_mac_lte_info->ueid);
2651 tap_info->raw_length = p_mac_lte_info->length;
2653 /* For uplink frames, if this is logged as a resend, look for original tx */
2654 if (direction == DIRECTION_UPLINK) {
2655 TrackReportedULHARQResend(pinfo, tvb, offset, tree, p_mac_lte_info, retx_ti);
2658 /* For uplink grants, update SR status. N.B. only newTx grant should stop SR */
2659 if ((direction == DIRECTION_UPLINK) && (p_mac_lte_info->reTxCount == 0) &&
2660 global_mac_lte_track_sr) {
2662 TrackSRInfo(SR_Grant, pinfo, tree, tvb, p_mac_lte_info, 0, NULL);
2665 /* Add hidden item to filter on */
2666 hidden_root_ti = proto_tree_add_string_format(tree,
2667 (direction == DIRECTION_UPLINK) ?
2673 PROTO_ITEM_SET_HIDDEN(hidden_root_ti);
2675 /* Add PDU block header subtree */
2676 pdu_header_ti = proto_tree_add_string_format(tree,
2677 (direction == DIRECTION_UPLINK) ?
2678 hf_mac_lte_ulsch_header :
2679 hf_mac_lte_dlsch_header,
2683 pdu_header_tree = proto_item_add_subtree(pdu_header_ti,
2684 (direction == DIRECTION_UPLINK) ?
2685 ett_mac_lte_ulsch_header :
2686 ett_mac_lte_dlsch_header);
2689 /************************************************************************/
2690 /* Dissect each sub-header. */
2694 proto_item *pdu_subheader_ti;
2695 proto_tree *pdu_subheader_tree;
2696 proto_item *lcid_ti;
2698 gint offset_start_subheader = offset;
2699 guint8 first_byte = tvb_get_guint8(tvb, offset);
2701 /* Add PDU block header subtree.
2702 Default with length of 1 byte. */
2703 pdu_subheader_ti = proto_tree_add_string_format(pdu_header_tree,
2704 hf_mac_lte_sch_subheader,
2708 pdu_subheader_tree = proto_item_add_subtree(pdu_subheader_ti,
2709 ett_mac_lte_sch_subheader);
2711 /* Check 1st 2 reserved bits */
2712 reserved = (first_byte & 0xc0) >> 6;
2713 ti = proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_sch_reserved,
2714 tvb, offset, 1, ENC_BIG_ENDIAN);
2715 if (reserved != 0) {
2716 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
2717 "%cL-SCH header Reserved bits not zero",
2718 (p_mac_lte_info->direction == DIRECTION_UPLINK) ? 'U' : 'D');
2722 extension = (first_byte & 0x20) >> 5;
2723 proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_sch_extended,
2724 tvb, offset, 1, ENC_BIG_ENDIAN);
2726 /* LCID. Has different meaning depending upon direction. */
2727 lcids[number_of_headers] = first_byte & 0x1f;
2728 if (direction == DIRECTION_UPLINK) {
2730 lcid_ti = proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_ulsch_lcid,
2731 tvb, offset, 1, ENC_BIG_ENDIAN);
2732 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
2734 val_to_str_const(lcids[number_of_headers],
2735 ulsch_lcid_vals, "(Unknown LCID)"));
2739 lcid_ti = proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_dlsch_lcid,
2740 tvb, offset, 1, ENC_BIG_ENDIAN);
2741 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
2743 val_to_str_const(lcids[number_of_headers],
2744 dlsch_lcid_vals, "(Unknown LCID)"));
2746 if (lcids[number_of_headers] == DRX_COMMAND_LCID) {
2747 expert_add_info_format(pinfo, lcid_ti, PI_SEQUENCE, PI_NOTE,
2748 "DRX command received for UE %u (RNTI %u)",
2749 p_mac_lte_info->ueid, p_mac_lte_info->rnti);
2754 /* Remember if we've seen a data subheader */
2755 if (lcids[number_of_headers] <= 10) {
2756 have_seen_data_header = TRUE;
2757 expecting_body_data = TRUE;
2760 /* Show an expert item if a contol subheader (except Padding) appears
2761 *after* a data PDU */
2762 if (have_seen_data_header &&
2763 (lcids[number_of_headers] > 10) && (lcids[number_of_headers] != PADDING_LCID)) {
2764 expert_add_info_format(pinfo, lcid_ti, PI_MALFORMED, PI_ERROR,
2765 "%cL-SCH Control subheaders should not appear after data subheaders",
2766 (p_mac_lte_info->direction == DIRECTION_UPLINK) ? 'U' : 'D');
2770 /* Show an expert item if we're seeing more then one BSR in a frame */
2771 if ((direction == DIRECTION_UPLINK) && is_bsr_lcid(lcids[number_of_headers])) {
2772 if (have_seen_bsr) {
2773 expert_add_info_format(pinfo, lcid_ti, PI_MALFORMED, PI_ERROR,
2774 "There shouldn't be > 1 BSR in a frame");
2777 have_seen_bsr = TRUE;
2780 /* Should not see padding after non-padding control... */
2781 if ((lcids[number_of_headers] > 10) &&
2782 (lcids[number_of_headers] == PADDING_LCID) &&
2785 number_of_padding_subheaders++;
2786 if (number_of_padding_subheaders > 2) {
2787 expert_add_info_format(pinfo, lcid_ti, PI_MALFORMED, PI_WARN,
2788 "Should not see more than 2 padding subheaders in one frame");
2791 if (have_seen_non_padding_control) {
2792 expert_add_info_format(pinfo, lcid_ti, PI_MALFORMED, PI_ERROR,
2793 "Padding should come before other control subheaders!");
2797 /* Remember that we've seen non-padding control */
2798 if ((lcids[number_of_headers] > 10) &&
2799 (lcids[number_of_headers] != PADDING_LCID)) {
2800 have_seen_non_padding_control = TRUE;
2805 /********************************************************************/
2806 /* Length field follows if not the last header or for a fixed-sized
2810 if (is_fixed_sized_control_element(lcids[number_of_headers], direction)) {
2811 pdu_lengths[number_of_headers] = 0;
2814 pdu_lengths[number_of_headers] = -1;
2818 /* Not the last one */
2819 if (!is_fixed_sized_control_element(lcids[number_of_headers], direction) &&
2820 (lcids[number_of_headers] != PADDING_LCID)) {
2824 /* F(ormat) bit tells us how long the length field is */
2825 format = (tvb_get_guint8(tvb, offset) & 0x80) >> 7;
2826 proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_sch_format,
2827 tvb, offset, 1, ENC_BIG_ENDIAN);
2829 /* Now read length field itself */
2831 /* >= 128 - use 15 bits */
2832 proto_tree_add_bits_ret_val(pdu_subheader_tree, hf_mac_lte_sch_length,
2833 tvb, offset*8 + 1, 15, &length, ENC_BIG_ENDIAN);
2838 /* Less than 128 - only 7 bits */
2839 proto_tree_add_bits_ret_val(pdu_subheader_tree, hf_mac_lte_sch_length,
2840 tvb, offset*8 + 1, 7, &length, ENC_BIG_ENDIAN);
2843 pdu_lengths[number_of_headers] = (gint16)length;
2846 pdu_lengths[number_of_headers] = 0;
2851 /* Close off description in info column */
2852 switch (pdu_lengths[number_of_headers]) {
2854 write_pdu_label_and_info(pdu_ti, NULL, pinfo, ") ");
2857 write_pdu_label_and_info(pdu_ti, NULL, pinfo, ":remainder) ");
2860 write_pdu_label_and_info(pdu_ti, NULL, pinfo, ":%u bytes) ",
2861 pdu_lengths[number_of_headers]);
2865 /* Append summary to subheader root */
2866 proto_item_append_text(pdu_subheader_ti, " (lcid=%s",
2867 val_to_str_const(lcids[number_of_headers],
2868 (direction == DIRECTION_UPLINK) ?
2873 switch (pdu_lengths[number_of_headers]) {
2875 proto_item_append_text(pdu_subheader_ti, ", length is remainder)");
2876 proto_item_append_text(pdu_header_ti, " (%s:remainder)",
2877 val_to_str_const(lcids[number_of_headers],
2878 (direction == DIRECTION_UPLINK) ? ulsch_lcid_vals : dlsch_lcid_vals,
2882 proto_item_append_text(pdu_subheader_ti, ")");
2883 proto_item_append_text(pdu_header_ti, " (%s)",
2884 val_to_str_const(lcids[number_of_headers],
2885 (direction == DIRECTION_UPLINK) ? ulsch_lcid_vals : dlsch_lcid_vals,
2889 proto_item_append_text(pdu_subheader_ti, ", length=%u)",
2890 pdu_lengths[number_of_headers]);
2891 proto_item_append_text(pdu_header_ti, " (%s:%u)",
2892 val_to_str_const(lcids[number_of_headers],
2893 (direction == DIRECTION_UPLINK) ? ulsch_lcid_vals : dlsch_lcid_vals,
2895 pdu_lengths[number_of_headers]);
2900 /* Flag unknown lcid values in expert info */
2901 if (match_strval(lcids[number_of_headers],
2902 (direction == DIRECTION_UPLINK) ? ulsch_lcid_vals : dlsch_lcid_vals) == NULL) {
2903 expert_add_info_format(pinfo, pdu_subheader_ti, PI_MALFORMED, PI_ERROR,
2904 "%cL-SCH: Unexpected LCID received (%u)",
2905 (p_mac_lte_info->direction == DIRECTION_UPLINK) ? 'U' : 'D',
2906 lcids[number_of_headers]);
2909 /* Set length of this subheader */
2910 proto_item_set_len(pdu_subheader_ti, offset - offset_start_subheader);
2912 number_of_headers++;
2913 } while ((number_of_headers < MAX_HEADERS_IN_PDU) && extension);
2915 /* Check that we didn't reach the end of the subheader array... */
2916 if (number_of_headers >= MAX_HEADERS_IN_PDU) {
2917 proto_item *ti = proto_tree_add_text(tree, tvb, offset, 1,
2918 "Reached %u subheaders - frame obviously malformed",
2919 MAX_HEADERS_IN_PDU);
2920 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
2921 "Reached %u subheaders - frame obviously malformed",
2922 MAX_HEADERS_IN_PDU);
2927 /* Append summary to overall PDU header root */
2928 proto_item_append_text(pdu_header_ti, " [%u subheaders]",
2931 /* And set its length to offset */
2932 proto_item_set_len(pdu_header_ti, offset);
2935 /* For DL, see if this is a retx. Use whole PDU present (i.e. ignore padding if not logged) */
2936 if (direction == DIRECTION_DOWNLINK) {
2937 /* Result will be added to context tree */
2938 TrackReportedDLHARQResend(pinfo, tvb, tvb_length_remaining(tvb, 0), context_tree, p_mac_lte_info);
2940 tap_info->isPHYRetx = (p_mac_lte_info->dl_retx == dl_retx_yes);
2944 /************************************************************************/
2945 /* Dissect SDUs / control elements / padding. */
2946 /************************************************************************/
2948 /* Dissect control element bodies first */
2950 for (n=0; n < number_of_headers; n++) {
2951 /* Get out of loop once see any data SDU subheaders */
2952 if (lcids[n] <= 10) {
2956 /* Process what should be a valid control PDU type */
2957 if (direction == DIRECTION_DOWNLINK) {
2959 /****************************/
2960 /* DL-SCH Control PDUs */
2962 case ACTIVATION_DEACTIVATION_LCID:
2965 proto_tree *ad_tree;
2969 /* Create AD root */
2970 ad_ti = proto_tree_add_string_format(tree,
2971 hf_mac_lte_control_activation_deactivation,
2974 "Activation/Deactivation");
2975 ad_tree = proto_item_add_subtree(ad_ti, ett_mac_lte_activation_deactivation);
2977 proto_tree_add_item(ad_tree, hf_mac_lte_control_activation_deactivation_c7,
2978 tvb, offset, 1, ENC_BIG_ENDIAN);
2979 proto_tree_add_item(ad_tree, hf_mac_lte_control_activation_deactivation_c6,
2980 tvb, offset, 1, ENC_BIG_ENDIAN);
2981 proto_tree_add_item(ad_tree, hf_mac_lte_control_activation_deactivation_c5,
2982 tvb, offset, 1, ENC_BIG_ENDIAN);
2983 proto_tree_add_item(ad_tree, hf_mac_lte_control_activation_deactivation_c4,
2984 tvb, offset, 1, ENC_BIG_ENDIAN);
2985 proto_tree_add_item(ad_tree, hf_mac_lte_control_activation_deactivation_c3,
2986 tvb, offset, 1, ENC_BIG_ENDIAN);
2987 proto_tree_add_item(ad_tree, hf_mac_lte_control_activation_deactivation_c2,
2988 tvb, offset, 1, ENC_BIG_ENDIAN);
2989 proto_tree_add_item(ad_tree, hf_mac_lte_control_activation_deactivation_c1,
2990 tvb, offset, 1, ENC_BIG_ENDIAN);
2991 ti = proto_tree_add_item(ad_tree, hf_mac_lte_control_activation_deactivation_reserved,
2992 tvb, offset, 1, ENC_BIG_ENDIAN);
2993 reserved = tvb_get_guint8(tvb, offset) & 0x01;
2994 if (reserved != 0) {
2995 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
2996 "Activation/Deactivation Reserved bit not zero");
3001 case UE_CONTENTION_RESOLUTION_IDENTITY_LCID:
3004 proto_tree *cr_tree;
3006 ContentionResolutionResult *crResult;
3008 /* Create CR root */
3009 cr_ti = proto_tree_add_string_format(tree,
3010 hf_mac_lte_control_ue_contention_resolution,
3013 "Contention Resolution");
3014 cr_tree = proto_item_add_subtree(cr_ti, ett_mac_lte_contention_resolution);
3017 proto_tree_add_item(cr_tree, hf_mac_lte_control_ue_contention_resolution_identity,
3018 tvb, offset, 6, ENC_NA);
3020 /* Get pointer to result struct for this frame */
3021 crResult = g_hash_table_lookup(mac_lte_cr_result_hash, GUINT_TO_POINTER(pinfo->fd->num));
3022 if (crResult == NULL) {
3024 /* Need to set result by looking for and comparing with Msg3 */
3026 guint msg3Key = p_mac_lte_info->rnti;
3028 /* Allocate result and add it to the table */
3029 crResult = se_alloc(sizeof(ContentionResolutionResult));
3030 g_hash_table_insert(mac_lte_cr_result_hash, GUINT_TO_POINTER(pinfo->fd->num), crResult);
3033 msg3Data = g_hash_table_lookup(mac_lte_msg3_hash, GUINT_TO_POINTER(msg3Key));
3035 /* Compare CCCH bytes */
3036 if (msg3Data != NULL) {
3037 crResult->msSinceMsg3 = (guint32)(((pinfo->fd->abs_ts.secs - msg3Data->msg3Time.secs) * 1000) +
3038 ((pinfo->fd->abs_ts.nsecs - msg3Data->msg3Time.nsecs) / 1000000));
3039 crResult->msg3FrameNum = msg3Data->framenum;
3041 /* Compare the 6 bytes */
3042 if (tvb_memeql(tvb, offset, msg3Data->data, 6) == 0) {
3043 crResult->status = Msg3Match;
3046 crResult->status = Msg3NoMatch;
3050 crResult->status = NoMsg3;
3054 /* Now show CR result in tree */
3055 switch (crResult->status) {
3057 proto_item_append_text(cr_ti, " (no corresponding Msg3 found!)");
3061 ti = proto_tree_add_uint(cr_tree, hf_mac_lte_control_ue_contention_resolution_msg3,
3062 tvb, 0, 0, crResult->msg3FrameNum);
3063 PROTO_ITEM_SET_GENERATED(ti);
3064 ti = proto_tree_add_uint(cr_tree, hf_mac_lte_control_ue_contention_resolution_time_since_msg3,
3065 tvb, 0, 0, crResult->msSinceMsg3);
3066 PROTO_ITEM_SET_GENERATED(ti);
3068 ti = proto_tree_add_boolean(cr_tree, hf_mac_lte_control_ue_contention_resolution_msg3_matched,
3070 PROTO_ITEM_SET_GENERATED(ti);
3071 proto_item_append_text(cr_ti, " (matches Msg3 from frame %u, %ums ago)",
3072 crResult->msg3FrameNum, crResult->msSinceMsg3);
3076 ti = proto_tree_add_uint(cr_tree, hf_mac_lte_control_ue_contention_resolution_msg3,
3077 tvb, 0, 0, crResult->msg3FrameNum);
3078 PROTO_ITEM_SET_GENERATED(ti);
3079 ti = proto_tree_add_uint(cr_tree, hf_mac_lte_control_ue_contention_resolution_time_since_msg3,
3080 tvb, 0, 0, crResult->msSinceMsg3);
3081 PROTO_ITEM_SET_GENERATED(ti);
3083 ti = proto_tree_add_boolean(cr_tree, hf_mac_lte_control_ue_contention_resolution_msg3_matched,
3085 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
3086 "CR body in Msg4 doesn't match Msg3 CCCH in frame %u",
3087 crResult->msg3FrameNum);
3088 PROTO_ITEM_SET_GENERATED(ti);
3089 proto_item_append_text(cr_ti, " (doesn't match Msg3 from frame %u, %u ago)",
3090 crResult->msg3FrameNum, crResult->msSinceMsg3);
3097 case TIMING_ADVANCE_LCID:
3100 proto_item *reserved_ti;
3104 /* Check 2 reserved bits */
3105 reserved = (tvb_get_guint8(tvb, offset) & 0xc0) >> 6;
3106 reserved_ti = proto_tree_add_item(tree, hf_mac_lte_control_timing_advance_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
3107 if (reserved != 0) {
3108 expert_add_info_format(pinfo, reserved_ti, PI_MALFORMED, PI_ERROR,
3109 "Timing Advance Reserved bits not zero (found 0x%x)", reserved);
3113 ta_value = tvb_get_guint8(tvb, offset) & 0x3f;
3114 ta_ti = proto_tree_add_item(tree, hf_mac_lte_control_timing_advance,
3115 tvb, offset, 1, ENC_BIG_ENDIAN);
3117 if (ta_value == 31) {
3118 expert_add_info_format(pinfo, ta_ti, PI_SEQUENCE,
3120 "Timing Advance control element received (no correction needed)");
3123 expert_add_info_format(pinfo, ta_ti, PI_SEQUENCE,
3125 "Timing Advance control element received (%u) %s correction needed",
3127 (ta_value < 31) ? "-ve" : "+ve");
3132 case DRX_COMMAND_LCID:
3136 /* No payload (in this position) */
3137 tap_info->padding_bytes++;
3146 /**********************************/
3147 /* UL-SCH Control PDUs */
3149 case EXTENDED_POWER_HEADROOM_REPORT_LCID:
3151 proto_item *ephr_ti;
3152 proto_tree *ephr_tree;
3154 proto_tree *ephr_cell_tree;
3155 proto_item *ephr_cell_ti;
3156 guint8 scell_bitmap;
3160 guint32 curr_offset = offset;
3161 guint32 computed_header_offset;
3163 if (pdu_lengths[n] == -1) {
3164 /* Control Element size is the remaining PDU */
3165 pdu_lengths[n] = (gint16)tvb_length_remaining(tvb, curr_offset);
3168 /* Create EPHR root */
3169 ephr_ti = proto_tree_add_string_format(tree,
3170 hf_mac_lte_control_ext_power_headroom,
3171 tvb, curr_offset, pdu_lengths[n],
3173 "Extended Power Headroom");
3174 ephr_tree = proto_item_add_subtree(ephr_ti, ett_mac_lte_extended_power_headroom);
3176 scell_bitmap = tvb_get_guint8(tvb, curr_offset);
3177 proto_tree_add_item(ephr_tree, hf_mac_lte_control_ext_power_headroom_c7,
3178 tvb, curr_offset, 1, ENC_BIG_ENDIAN);
3179 proto_tree_add_item(ephr_tree, hf_mac_lte_control_ext_power_headroom_c6,
3180 tvb, curr_offset, 1, ENC_BIG_ENDIAN);
3181 proto_tree_add_item(ephr_tree, hf_mac_lte_control_ext_power_headroom_c5,
3182 tvb, curr_offset, 1, ENC_BIG_ENDIAN);
3183 proto_tree_add_item(ephr_tree, hf_mac_lte_control_ext_power_headroom_c4,
3184 tvb, curr_offset, 1, ENC_BIG_ENDIAN);
3185 proto_tree_add_item(ephr_tree, hf_mac_lte_control_ext_power_headroom_c3,
3186 tvb, curr_offset, 1, ENC_BIG_ENDIAN);
3187 proto_tree_add_item(ephr_tree, hf_mac_lte_control_ext_power_headroom_c2,
3188 tvb, curr_offset, 1, ENC_BIG_ENDIAN);
3189 proto_tree_add_item(ephr_tree, hf_mac_lte_control_ext_power_headroom_c1,
3190 tvb, curr_offset, 1, ENC_BIG_ENDIAN);
3191 /* Check Reserved bit */
3192 ti = proto_tree_add_item(ephr_tree, hf_mac_lte_control_ext_power_headroom_reserved,
3193 tvb, curr_offset, 1, ENC_BIG_ENDIAN);
3194 if (scell_bitmap & 0x01) {
3195 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
3196 "Extended Power Headroom Reserved bit not zero");
3200 /* Compute expected header size to deduce if PH Type 2 report is present or not */
3201 /* First count the number of SCells */
3202 for (i = 0, scell_count = 0; i < 7; i++) {
3203 if (scell_bitmap & (0x80>>i)) {
3207 /* Now quickly parse the header */
3208 computed_header_offset = curr_offset;
3209 for (i = 0; i < scell_count; i++) {
3210 if (tvb_get_guint8(tvb, computed_header_offset) & 0x80) {
3211 computed_header_offset++;
3213 computed_header_offset++;
3216 if ((gint16)(computed_header_offset + 1 - curr_offset) != pdu_lengths[n]) {
3217 /* PH Type 2 is present */
3218 if (tvb_get_guint8(tvb, computed_header_offset) & 0x80) {
3219 computed_header_offset++;
3221 computed_header_offset++;
3222 if ((gint16)(computed_header_offset + 1 - curr_offset) != pdu_lengths[n]) {
3223 expert_add_info_format(pinfo, ephr_ti, PI_MALFORMED, PI_ERROR,
3224 "Control Element has an unexpected size (computed=%d, actual=%d)",
3225 computed_header_offset + 1 - curr_offset, pdu_lengths[n]);
3226 offset += pdu_lengths[n];
3229 byte = tvb_get_guint8(tvb, curr_offset);
3230 ephr_cell_ti = proto_tree_add_text(ephr_tree, tvb, curr_offset, ((byte&0x80)?2:1), "PCell");
3231 ephr_cell_tree = proto_item_add_subtree(ephr_cell_ti, ett_mac_lte_extended_power_headroom_cell);
3232 proto_tree_add_item(ephr_cell_tree, hf_mac_lte_control_ext_power_headroom_power_backoff,
3233 tvb, curr_offset, 1, ENC_BIG_ENDIAN);
3234 proto_tree_add_item(ephr_cell_tree, hf_mac_lte_control_ext_power_headroom_value,
3235 tvb, curr_offset, 1, ENC_BIG_ENDIAN);
3236 proto_tree_add_item(ephr_cell_tree, hf_mac_lte_control_ext_power_headroom_level,
3237 tvb, curr_offset, 1, ENC_BIG_ENDIAN);
3238 proto_item_append_text(ephr_cell_ti, " (%s)",
3239 val_to_str_ext_const((byte&0x3f), &power_headroom_vals_ext, "Unknown"));
3242 /* Pcmax,c field is present */
3243 byte = tvb_get_guint8(tvb, curr_offset);
3244 /* Check 2 Reserved bits */
3245 ti = proto_tree_add_item(ephr_cell_tree, hf_mac_lte_control_ext_power_headroom_reserved2,
3246 tvb, curr_offset, 1, ENC_BIG_ENDIAN);
3248 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
3249 "Extended Power Headroom Reserved bits not zero (found 0x%x)",
3250 (byte & 0xc0) >> 6);
3252 proto_tree_add_item(ephr_cell_tree, hf_mac_lte_control_ext_power_headroom_pcmaxc,
3253 tvb, curr_offset, 1, ENC_BIG_ENDIAN);
3254 proto_item_append_text(ephr_cell_ti, " (%s)",
3255 val_to_str_ext_const((byte&0x3f), &pcmaxc_vals_ext, "Unknown"));
3259 if ((gint16)(computed_header_offset + 1 - curr_offset) != pdu_lengths[n]) {
3260 expert_add_info_format(pinfo, ephr_ti, PI_MALFORMED, PI_ERROR,
3261 "Control Element has an unexpected size (computed=%d, actual=%d)",
3262 computed_header_offset + 1 - curr_offset, pdu_lengths[n]);
3263 offset += pdu_lengths[n];
3267 for (i = 1, scell_bitmap>>=1; i <= 7; i++, scell_bitmap>>=1) {
3268 if (scell_bitmap & 0x01) {
3269 byte = tvb_get_guint8(tvb, curr_offset);
3270 ephr_cell_ti = proto_tree_add_text(ephr_tree, tvb, curr_offset, ((byte&0x80)?2:1), "SCell Index %u", i);
3271 ephr_cell_tree = proto_item_add_subtree(ephr_cell_ti, ett_mac_lte_extended_power_headroom_cell);
3272 proto_tree_add_item(ephr_cell_tree, hf_mac_lte_control_ext_power_headroom_power_backoff,
3273 tvb, curr_offset, 1, ENC_BIG_ENDIAN);
3274 proto_tree_add_item(ephr_cell_tree, hf_mac_lte_control_ext_power_headroom_value,
3275 tvb, curr_offset, 1, ENC_BIG_ENDIAN);
3276 proto_tree_add_item(ephr_cell_tree, hf_mac_lte_control_ext_power_headroom_level,
3277 tvb, curr_offset, 1, ENC_BIG_ENDIAN);
3278 proto_item_append_text(ephr_cell_ti, " (%s)",
3279 val_to_str_ext_const((byte&0x3f), &power_headroom_vals_ext, "Unknown"));
3282 /* Pcmax,c field is present */
3283 byte = tvb_get_guint8(tvb, curr_offset);
3284 /* Check 2 Reserved bits */
3285 ti = proto_tree_add_item(ephr_cell_tree, hf_mac_lte_control_ext_power_headroom_reserved2,
3286 tvb, curr_offset, 1, ENC_BIG_ENDIAN);
3288 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
3289 "Extended Power Headroom Reserved bits not zero (found 0x%x)",
3290 (byte & 0xc0) >> 6);
3292 proto_tree_add_item(ephr_cell_tree, hf_mac_lte_control_ext_power_headroom_pcmaxc,
3293 tvb, curr_offset, 1, ENC_BIG_ENDIAN);
3294 proto_item_append_text(ephr_cell_ti, " (%s)",
3295 val_to_str_ext_const((byte&0x3f), &pcmaxc_vals_ext, "Unknown"));
3300 offset += pdu_lengths[n];
3303 case POWER_HEADROOM_REPORT_LCID:
3306 proto_tree *phr_tree;
3311 /* Create PHR root */
3312 phr_ti = proto_tree_add_string_format(tree,
3313 hf_mac_lte_control_power_headroom,
3317 phr_tree = proto_item_add_subtree(phr_ti, ett_mac_lte_power_headroom);
3319 /* Check 2 Reserved bits */
3320 reserved = (tvb_get_guint8(tvb, offset) & 0xc0) >> 6;
3321 ti = proto_tree_add_item(phr_tree, hf_mac_lte_control_power_headroom_reserved,
3322 tvb, offset, 1, ENC_BIG_ENDIAN);
3323 if (reserved != 0) {
3324 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
3325 "Power Headroom Reserved bits not zero (found 0x%x)", reserved);
3329 level = tvb_get_guint8(tvb, offset) & 0x3f;
3330 proto_tree_add_item(phr_tree, hf_mac_lte_control_power_headroom_level,
3331 tvb, offset, 1, ENC_BIG_ENDIAN);
3333 /* Show value in root label */
3334 proto_item_append_text(phr_ti, " (%s)",
3335 val_to_str_ext_const(level, &power_headroom_vals_ext, "Unknown"));
3342 proto_tree_add_item(tree, hf_mac_lte_control_crnti,
3343 tvb, offset, 2, ENC_BIG_ENDIAN);
3346 case TRUNCATED_BSR_LCID:
3347 case SHORT_BSR_LCID:
3349 proto_tree *bsr_tree;
3351 proto_item *buffer_size_ti;
3355 value_string_ext *p_vs_ext;
3357 if (p_mac_lte_info->isExtendedBSRSizes) {
3358 hfindex = hf_mac_lte_control_short_ext_bsr_buffer_size;
3359 p_vs_ext = &ext_buffer_size_vals_ext;
3361 hfindex = hf_mac_lte_control_short_bsr_buffer_size;
3362 p_vs_ext = &buffer_size_vals_ext;
3365 bsr_ti = proto_tree_add_string_format(tree,
3366 hf_mac_lte_control_bsr,
3370 bsr_tree = proto_item_add_subtree(bsr_ti, ett_mac_lte_bsr);
3373 lcgid = (tvb_get_guint8(tvb, offset) & 0xc0) >> 6;
3374 proto_tree_add_item(bsr_tree, hf_mac_lte_control_bsr_lcg_id,
3375 tvb, offset, 1, ENC_BIG_ENDIAN);
3377 buffer_size = tvb_get_guint8(tvb, offset) & 0x3f;
3378 buffer_size_ti = proto_tree_add_item(bsr_tree, hfindex,
3379 tvb, offset, 1, ENC_BIG_ENDIAN);
3381 if (buffer_size >= global_mac_lte_bsr_warn_threshold) {
3382 expert_add_info_format(pinfo, buffer_size_ti, PI_SEQUENCE, PI_WARN,
3383 "UE %u - BSR for LCG %u exceeds threshold: %u (%s)",
3384 p_mac_lte_info->ueid,
3387 val_to_str_ext_const(buffer_size, p_vs_ext, "Unknown"));
3391 proto_item_append_text(bsr_ti, " (lcgid=%u %s)",
3393 val_to_str_ext_const(buffer_size, &buffer_size_vals_ext, "Unknown"));
3398 proto_tree *bsr_tree;
3400 proto_item *buffer_size_ti;
3401 guint8 buffer_size[4];
3403 value_string_ext *p_vs_ext;
3405 if (p_mac_lte_info->isExtendedBSRSizes) {
3406 hfindex[0] = hf_mac_lte_control_long_ext_bsr_buffer_size_0;
3407 hfindex[1] = hf_mac_lte_control_long_ext_bsr_buffer_size_1;
3408 hfindex[2] = hf_mac_lte_control_long_ext_bsr_buffer_size_2;
3409 hfindex[3] = hf_mac_lte_control_long_ext_bsr_buffer_size_3;
3410 p_vs_ext = &ext_buffer_size_vals_ext;
3412 hfindex[0] = hf_mac_lte_control_long_bsr_buffer_size_0;
3413 hfindex[1] = hf_mac_lte_control_long_bsr_buffer_size_1;
3414 hfindex[2] = hf_mac_lte_control_long_bsr_buffer_size_2;
3415 hfindex[3] = hf_mac_lte_control_long_bsr_buffer_size_3;
3416 p_vs_ext = &buffer_size_vals_ext;
3419 bsr_ti = proto_tree_add_string_format(tree,
3420 hf_mac_lte_control_bsr,
3424 bsr_tree = proto_item_add_subtree(bsr_ti, ett_mac_lte_bsr);
3427 buffer_size_ti = proto_tree_add_item(bsr_tree, hfindex[0],
3428 tvb, offset, 1, ENC_BIG_ENDIAN);
3429 buffer_size[0] = (tvb_get_guint8(tvb, offset) & 0xfc) >> 2;
3430 if (buffer_size[0] >= global_mac_lte_bsr_warn_threshold) {
3431 expert_add_info_format(pinfo, buffer_size_ti, PI_SEQUENCE, PI_WARN,
3432 "UE %u - BSR for LCG 0 exceeds threshold: %u (%s)",
3433 p_mac_lte_info->ueid,
3435 val_to_str_ext_const(buffer_size[0], p_vs_ext, "Unknown"));
3439 buffer_size_ti = proto_tree_add_item(bsr_tree, hfindex[1],
3440 tvb, offset, 2, ENC_BIG_ENDIAN);
3441 buffer_size[1] = ((tvb_get_guint8(tvb, offset) & 0x03) << 4) | ((tvb_get_guint8(tvb, offset+1) & 0xf0) >> 4);
3443 if (buffer_size[1] >= global_mac_lte_bsr_warn_threshold) {
3444 expert_add_info_format(pinfo, buffer_size_ti, PI_SEQUENCE, PI_WARN,
3445 "UE %u - BSR for LCG 1 exceeds threshold: %u (%s)",
3446 p_mac_lte_info->ueid,
3448 val_to_str_ext_const(buffer_size[1], p_vs_ext, "Unknown"));
3452 buffer_size_ti = proto_tree_add_item(bsr_tree, hfindex[2],
3453 tvb, offset, 2, ENC_BIG_ENDIAN);
3455 buffer_size[2] = ((tvb_get_guint8(tvb, offset) & 0x0f) << 2) | ((tvb_get_guint8(tvb, offset+1) & 0xc0) >> 6);
3457 if (buffer_size[2] >= global_mac_lte_bsr_warn_threshold) {
3458 expert_add_info_format(pinfo, buffer_size_ti, PI_SEQUENCE, PI_WARN,
3459 "UE %u - BSR for LCG 2 exceeds threshold: %u (%s)",
3460 p_mac_lte_info->ueid,
3462 val_to_str_ext_const(buffer_size[2], p_vs_ext, "Unknown"));
3466 buffer_size_ti = proto_tree_add_item(bsr_tree, hfindex[3],
3467 tvb, offset, 1, ENC_BIG_ENDIAN);
3468 buffer_size[3] = tvb_get_guint8(tvb, offset) & 0x3f;
3470 if (buffer_size[3] >= global_mac_lte_bsr_warn_threshold) {
3471 expert_add_info_format(pinfo, buffer_size_ti, PI_SEQUENCE, PI_WARN,
3472 "UE %u - BSR for LCG 3 exceeds threshold: %u (%s)",
3473 p_mac_lte_info->ueid,
3475 val_to_str_ext_const(buffer_size[3], p_vs_ext, "Unknown"));
3478 /* Append summary to parent */
3479 proto_item_append_text(bsr_ti, " 0:(%s) 1:(%s) 2:(%s) 3:(%s)",
3480 val_to_str_ext_const(buffer_size[0], p_vs_ext, "Unknown"),
3481 val_to_str_ext_const(buffer_size[1], p_vs_ext, "Unknown"),
3482 val_to_str_ext_const(buffer_size[2], p_vs_ext, "Unknown"),
3483 val_to_str_ext_const(buffer_size[3], p_vs_ext, "Unknown"));
3487 /* No payload, in this position */
3488 tap_info->padding_bytes++;
3497 /* There might not be any data, if only headers (plus control data) were logged */
3498 is_truncated = ((tvb_length_remaining(tvb, offset) == 0) && expecting_body_data);
3499 truncated_ti = proto_tree_add_uint(tree, hf_mac_lte_sch_header_only, tvb, 0, 0,
3502 PROTO_ITEM_SET_GENERATED(truncated_ti);
3503 expert_add_info_format(pinfo, truncated_ti, PI_SEQUENCE, PI_NOTE,
3504 "MAC PDU SDUs have been omitted");
3508 PROTO_ITEM_SET_HIDDEN(truncated_ti);
3512 /* Now process remaining bodies, which should all be data */
3513 for (; n < number_of_headers; n++) {
3515 /* Data SDUs treated identically for Uplink or downlink channels */
3517 const guint8 *pdu_data;
3518 volatile guint16 data_length;
3522 /* Break out if meet padding */
3523 if (lcids[n] == PADDING_LCID) {
3527 /* Work out length */
3528 data_length = (pdu_lengths[n] == -1) ?
3529 tvb_length_remaining(tvb, offset) :
3532 /* Dissect SDU as raw bytes */
3533 sdu_ti = proto_tree_add_bytes_format(tree, hf_mac_lte_sch_sdu, tvb, offset, pdu_lengths[n],
3534 NULL, "SDU (%s, length=%u bytes): ",
3535 val_to_str_const(lcids[n],
3536 (direction == DIRECTION_UPLINK) ?
3541 /* Show bytes too. There must be a nicer way of doing this! */
3542 pdu_data = tvb_get_ptr(tvb, offset, pdu_lengths[n]);
3543 for (i=0; i < data_length; i++) {
3544 g_snprintf(buff+(i*2), 3, "%02x", pdu_data[i]);
3546 g_snprintf(buff+(i*2), 4, "...");
3550 proto_item_append_text(sdu_ti, "%s", buff);
3553 /* Look for Msg3 data so that it may be compared with later
3554 Contention Resolution body */
3555 if ((lcids[n] == 0) && (direction == DIRECTION_UPLINK) && (data_length == 6)) {
3556 if (!pinfo->fd->flags.visited) {
3557 guint key = p_mac_lte_info->rnti;
3558 Msg3Data *data = g_hash_table_lookup(mac_lte_msg3_hash, GUINT_TO_POINTER(key));
3560 /* Look for previous entry for this UE */
3562 /* Allocate space for data and add to table */
3563 data = se_alloc(sizeof(Msg3Data));
3564 g_hash_table_insert(mac_lte_msg3_hash, GUINT_TO_POINTER(key), data);
3567 /* Fill in data details */
3568 data->framenum = pinfo->fd->num;
3569 tvb_memcpy(tvb, data->data, offset, data_length);
3570 data->msg3Time = pinfo->fd->abs_ts;
3574 /* CCCH frames can be dissected directly by LTE RRC... */
3575 if ((lcids[n] == 0) && global_mac_lte_attempt_rrc_decode) {
3576 tvbuff_t *rrc_tvb = tvb_new_subset(tvb, offset, data_length, data_length);
3578 /* Get appropriate dissector handle */
3579 volatile dissector_handle_t protocol_handle = 0;
3580 if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
3581 protocol_handle = find_dissector("lte_rrc.ul_ccch");
3584 protocol_handle = find_dissector("lte_rrc.dl_ccch");
3587 /* Hide raw view of bytes */
3588 PROTO_ITEM_SET_HIDDEN(sdu_ti);
3590 call_with_catch_all(protocol_handle, rrc_tvb, pinfo, tree);
3593 /* LCID 1 and 2 can be assumed to be srb1&2, so can dissect as RLC AM */
3594 else if ((lcids[n] == 1) || (lcids[n] == 2)) {
3595 if (global_mac_lte_attempt_srb_decode) {
3596 /* Call RLC dissector */
3597 call_rlc_dissector(tvb, pinfo, tree, pdu_ti, offset, data_length,
3598 RLC_AM_MODE, direction, p_mac_lte_info->ueid,
3599 CHANNEL_TYPE_SRB, lcids[n], 0,
3600 get_mac_lte_channel_priority(p_mac_lte_info->ueid,
3601 lcids[n], direction));
3603 /* Hide raw view of bytes */
3604 PROTO_ITEM_SET_HIDDEN(sdu_ti);
3608 else if ((lcids[n] >= 2) && (lcids[n] <= 10)) {
3610 /* Look for mapping for this LCID to drb channel set by UAT table */
3611 rlc_channel_type_t rlc_channel_type;
3612 guint8 UM_seqnum_length;
3614 guint8 priority = get_mac_lte_channel_priority(p_mac_lte_info->ueid,
3615 lcids[n], direction);
3617 lookup_rlc_channel_from_lcid(lcids[n],
3622 /* Dissect according to channel type */
3623 switch (rlc_channel_type) {
3625 call_rlc_dissector(tvb, pinfo, tree, pdu_ti, offset, data_length,
3626 RLC_UM_MODE, direction, p_mac_lte_info->ueid,
3627 CHANNEL_TYPE_DRB, (guint16)drb_id, UM_seqnum_length,
3631 call_rlc_dissector(tvb, pinfo, tree, pdu_ti, offset, data_length,
3632 RLC_UM_MODE, direction, p_mac_lte_info->ueid,
3633 CHANNEL_TYPE_DRB, (guint16)drb_id, UM_seqnum_length,
3637 call_rlc_dissector(tvb, pinfo, tree, pdu_ti, offset, data_length,
3638 RLC_AM_MODE, direction, p_mac_lte_info->ueid,
3639 CHANNEL_TYPE_DRB, (guint16)drb_id, 0,
3643 call_rlc_dissector(tvb, pinfo, tree, pdu_ti, offset, data_length,
3644 RLC_TM_MODE, direction, p_mac_lte_info->ueid,
3645 CHANNEL_TYPE_DRB, (guint16)drb_id, 0,
3649 /* Nothing to do! */
3653 if (rlc_channel_type != rlcRaw) {
3654 /* Hide raw view of bytes */
3655 PROTO_ITEM_SET_HIDDEN(sdu_ti);
3660 offset += data_length;
3662 /* Update tap byte count for this channel */
3663 tap_info->bytes_for_lcid[lcids[n]] += data_length;
3664 tap_info->sdus_for_lcid[lcids[n]]++;
3668 /* Now padding, if present, extends to the end of the PDU */
3669 if (lcids[number_of_headers-1] == PADDING_LCID) {
3670 if (tvb_length_remaining(tvb, offset) > 0) {
3671 proto_tree_add_item(tree, hf_mac_lte_padding_data,
3672 tvb, offset, -1, ENC_NA);
3674 padding_length_ti = proto_tree_add_int(tree, hf_mac_lte_padding_length,
3676 p_mac_lte_info->length - offset);
3677 PROTO_ITEM_SET_GENERATED(padding_length_ti);
3679 /* Update padding bytes in stats */
3680 tap_info->padding_bytes += (p_mac_lte_info->length - offset);
3682 /* Make sure the PDU isn't bigger than reported! */
3683 if (offset > p_mac_lte_info->length) {
3684 expert_add_info_format(pinfo, padding_length_ti, PI_MALFORMED, PI_ERROR,
3685 "%s MAC PDU is longer than reported length (reported=%u, actual=%u)",
3686 (direction == DIRECTION_UPLINK) ? "UL-SCH" : "DL-SCH",
3687 p_mac_lte_info->length, offset);
3691 /* There is no padding at the end of the frame */
3692 if (!is_truncated && (offset < p_mac_lte_info->length)) {
3693 /* There is a problem if we haven't used all of the PDU */
3694 expert_add_info_format(pinfo, pdu_ti, PI_MALFORMED, PI_ERROR,
3695 "%s PDU for UE %u is shorter than reported length (reported=%u, actual=%u)",
3696 (direction == DIRECTION_UPLINK) ? "UL-SCH" : "DL-SCH",
3697 p_mac_lte_info->ueid, p_mac_lte_info->length, offset);
3700 if (!is_truncated && (offset > p_mac_lte_info->length)) {
3701 /* There is a problem if the PDU is longer than rpeported */
3702 expert_add_info_format(pinfo, pdu_ti, PI_MALFORMED, PI_ERROR,
3703 "%s PDU for UE %u is longer than reported length (reported=%u, actual=%u)",
3704 (direction == DIRECTION_UPLINK) ? "UL-SCH" : "DL-SCH",
3705 p_mac_lte_info->ueid, p_mac_lte_info->length, offset);
3710 static void dissect_mch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *pdu_ti,
3711 volatile guint32 offset, mac_lte_info *p_mac_lte_info)
3715 proto_item *truncated_ti;
3716 proto_item *padding_length_ti;
3717 proto_item *hidden_root_ti;
3719 /* Keep track of LCIDs and lengths as we dissect the header */
3720 volatile guint16 number_of_headers = 0;
3721 guint8 lcids[MAX_HEADERS_IN_PDU];
3722 gint16 pdu_lengths[MAX_HEADERS_IN_PDU];
3724 proto_item *pdu_header_ti;
3725 proto_tree *pdu_header_tree;
3727 gboolean have_seen_data_header = FALSE;
3728 guint8 number_of_padding_subheaders = 0;
3729 gboolean have_seen_non_padding_control = FALSE;
3730 gboolean expecting_body_data = FALSE;
3731 volatile guint32 is_truncated = FALSE;
3733 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
3735 p_mac_lte_info->subframeNumber);
3737 /* Add hidden item to filter on */
3738 hidden_root_ti = proto_tree_add_string_format(tree, hf_mac_lte_mch, tvb,
3739 offset, 0, "", "Hidden header");
3740 PROTO_ITEM_SET_HIDDEN(hidden_root_ti);
3742 /* Add PDU block header subtree */
3743 pdu_header_ti = proto_tree_add_string_format(tree, hf_mac_lte_mch_header,
3747 pdu_header_tree = proto_item_add_subtree(pdu_header_ti, ett_mac_lte_mch_header);
3750 /************************************************************************/
3751 /* Dissect each sub-header. */
3755 proto_item *pdu_subheader_ti;
3756 proto_tree *pdu_subheader_tree;
3757 proto_item *lcid_ti;
3759 gint offset_start_subheader = offset;
3760 guint8 first_byte = tvb_get_guint8(tvb, offset);
3762 /* Add PDU block header subtree.
3763 Default with length of 1 byte. */
3764 pdu_subheader_ti = proto_tree_add_string_format(pdu_header_tree,
3765 hf_mac_lte_mch_subheader,
3769 pdu_subheader_tree = proto_item_add_subtree(pdu_subheader_ti,
3770 ett_mac_lte_mch_subheader);
3772 /* Check 1st 2 reserved bits */
3773 reserved = (first_byte & 0xc0) >> 6;
3774 ti = proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_mch_reserved,
3775 tvb, offset, 1, ENC_BIG_ENDIAN);
3776 if (reserved != 0) {
3777 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
3778 "MCH header Reserved bits not zero");
3782 extension = (first_byte & 0x20) >> 5;
3783 proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_mch_extended,
3784 tvb, offset, 1, ENC_BIG_ENDIAN);
3787 lcids[number_of_headers] = first_byte & 0x1f;
3788 lcid_ti = proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_mch_lcid,
3789 tvb, offset, 1, ENC_BIG_ENDIAN);
3790 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
3792 val_to_str_const(lcids[number_of_headers],
3793 mch_lcid_vals, "(Unknown LCID)"));
3796 /* Remember if we've seen a data subheader */
3797 if (lcids[number_of_headers] <= 28) {
3798 have_seen_data_header = TRUE;
3799 expecting_body_data = TRUE;
3802 /* Show an expert item if a contol subheader (except Padding) appears
3803 *after* a data PDU */
3804 if (have_seen_data_header &&
3805 (lcids[number_of_headers] > 28) && (lcids[number_of_headers] != PADDING_LCID)) {
3806 expert_add_info_format(pinfo, lcid_ti, PI_MALFORMED, PI_ERROR,
3807 "MCH Control subheaders should not appear after data subheaders");
3811 /* Should not see padding after non-padding control... */
3812 if ((lcids[number_of_headers] > 28) &&
3813 (lcids[number_of_headers] == PADDING_LCID) &&
3816 number_of_padding_subheaders++;
3817 if (number_of_padding_subheaders > 2) {
3818 expert_add_info_format(pinfo, lcid_ti, PI_MALFORMED, PI_WARN,
3819 "Should not see more than 2 padding subheaders in one frame");
3822 if (have_seen_non_padding_control) {
3823 expert_add_info_format(pinfo, lcid_ti, PI_MALFORMED, PI_ERROR,
3824 "Padding should come before other control subheaders!");
3828 /* Remember that we've seen non-padding control */
3829 if ((lcids[number_of_headers] > 28) &&
3830 (lcids[number_of_headers] != PADDING_LCID)) {
3831 have_seen_non_padding_control = TRUE;
3836 /********************************************************************/
3837 /* Length field follows if not the last header or for a fixed-sized
3841 pdu_lengths[number_of_headers] = -1;
3844 /* Not the last one */
3845 if (lcids[number_of_headers] != PADDING_LCID) {
3849 /* F(ormat) bit tells us how long the length field is */
3850 format = (tvb_get_guint8(tvb, offset) & 0x80) >> 7;
3851 proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_mch_format,
3852 tvb, offset, 1, ENC_BIG_ENDIAN);
3854 /* Now read length field itself */
3856 /* >= 128 - use 15 bits */
3857 proto_tree_add_bits_ret_val(pdu_subheader_tree, hf_mac_lte_mch_length,
3858 tvb, offset*8 + 1, 15, &length, ENC_BIG_ENDIAN);
3863 /* Less than 128 - only 7 bits */
3864 proto_tree_add_bits_ret_val(pdu_subheader_tree, hf_mac_lte_mch_length,
3865 tvb, offset*8 + 1, 7, &length, ENC_BIG_ENDIAN);
3868 if ((lcids[number_of_headers] == MCH_SCHEDULING_INFO_LCID) && (length & 0x01)) {
3869 expert_add_info_format(pinfo, lcid_ti, PI_MALFORMED, PI_WARN,
3870 "MCH Scheduling Information MAC Control Element should have an even size");
3872 pdu_lengths[number_of_headers] = (gint16)length;
3875 pdu_lengths[number_of_headers] = 0;
3880 /* Close off description in info column */
3881 switch (pdu_lengths[number_of_headers]) {
3883 write_pdu_label_and_info(pdu_ti, NULL, pinfo, ") ");
3886 write_pdu_label_and_info(pdu_ti, NULL, pinfo, ":remainder) ");
3889 write_pdu_label_and_info(pdu_ti, NULL, pinfo, ":%u bytes) ",
3890 pdu_lengths[number_of_headers]);
3894 /* Append summary to subheader root */
3895 proto_item_append_text(pdu_subheader_ti, " (lcid=%s",
3896 val_to_str_const(lcids[number_of_headers],
3897 mch_lcid_vals, "Unknown"));
3899 switch (pdu_lengths[number_of_headers]) {
3901 proto_item_append_text(pdu_subheader_ti, ", length is remainder)");
3902 proto_item_append_text(pdu_header_ti, " (%s:remainder)",
3903 val_to_str_const(lcids[number_of_headers],
3908 proto_item_append_text(pdu_subheader_ti, ")");
3909 proto_item_append_text(pdu_header_ti, " (%s)",
3910 val_to_str_const(lcids[number_of_headers],
3915 proto_item_append_text(pdu_subheader_ti, ", length=%u)",
3916 pdu_lengths[number_of_headers]);
3917 proto_item_append_text(pdu_header_ti, " (%s:%u)",
3918 val_to_str_const(lcids[number_of_headers],
3921 pdu_lengths[number_of_headers]);
3926 /* Flag unknown lcid values in expert info */
3927 if (match_strval(lcids[number_of_headers],mch_lcid_vals) == NULL) {
3928 expert_add_info_format(pinfo, pdu_subheader_ti, PI_MALFORMED, PI_ERROR,
3929 "MCH: Unexpected LCID received (%u)",
3930 lcids[number_of_headers]);
3933 /* Set length of this subheader */
3934 proto_item_set_len(pdu_subheader_ti, offset - offset_start_subheader);
3936 number_of_headers++;
3937 } while ((number_of_headers < MAX_HEADERS_IN_PDU) && extension);
3939 /* Check that we didn't reach the end of the subheader array... */
3940 if (number_of_headers >= MAX_HEADERS_IN_PDU) {
3941 proto_item *ti = proto_tree_add_text(tree, tvb, offset, 1,
3942 "Reached %u subheaders - frame obviously malformed",
3943 MAX_HEADERS_IN_PDU);
3944 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
3945 "Reached %u subheaders - frame obviously malformed",
3946 MAX_HEADERS_IN_PDU);
3951 /* Append summary to overall PDU header root */
3952 proto_item_append_text(pdu_header_ti, " (%u subheaders)",
3955 /* And set its length to offset */
3956 proto_item_set_len(pdu_header_ti, offset);
3959 /************************************************************************/
3960 /* Dissect SDUs / control elements / padding. */
3961 /************************************************************************/
3963 /* Dissect control element bodies first */
3965 for (n=0; n < number_of_headers; n++) {
3966 /* Get out of loop once see any data SDU subheaders */
3967 if (lcids[n] <= 28) {
3971 /* Process what should be a valid control PDU type */
3973 case MCH_SCHEDULING_INFO_LCID:
3975 guint32 curr_offset = offset;
3977 guint16 stop_mtch_val;
3978 proto_item *mch_sched_info_ti, *ti;
3979 proto_tree *mch_sched_info_tree;
3981 mch_sched_info_ti = proto_tree_add_string_format(tree,
3982 hf_mac_lte_control_mch_scheduling_info,
3983 tvb, curr_offset, pdu_lengths[n],
3985 "MCH Scheduling Information");
3986 mch_sched_info_tree = proto_item_add_subtree(mch_sched_info_ti, ett_mac_lte_mch_scheduling_info);
3988 for (i=0; i<(pdu_lengths[n]/2); i++) {
3989 proto_tree_add_item(mch_sched_info_tree, hf_mac_lte_control_mch_scheduling_info_lcid,
3990 tvb, curr_offset, 1, ENC_BIG_ENDIAN);
3991 stop_mtch_val = tvb_get_ntohs(tvb, curr_offset) & 0x7ff;
3992 ti = proto_tree_add_item(mch_sched_info_tree, hf_mac_lte_control_mch_scheduling_info_stop_mtch,
3993 tvb, curr_offset, 2, ENC_BIG_ENDIAN);
3994 if ((stop_mtch_val >= 2043) && (stop_mtch_val <= 2046)) {
3995 proto_item_append_text(ti, " (reserved)");
3997 else if (stop_mtch_val == 2047) {
3998 proto_item_append_text(ti, " (MTCH is not scheduled)");
4003 offset += pdu_lengths[n];
4007 /* No payload (in this position) */
4016 /* There might not be any data, if only headers (plus control data) were logged */
4017 is_truncated = ((tvb_length_remaining(tvb, offset) == 0) && expecting_body_data);
4018 truncated_ti = proto_tree_add_uint(tree, hf_mac_lte_mch_header_only, tvb, 0, 0,
4021 PROTO_ITEM_SET_GENERATED(truncated_ti);
4022 expert_add_info_format(pinfo, truncated_ti, PI_SEQUENCE, PI_NOTE,
4023 "MAC PDU SDUs have been omitted");
4027 PROTO_ITEM_SET_HIDDEN(truncated_ti);
4031 /* Now process remaining bodies, which should all be data */
4032 for (; n < number_of_headers; n++) {
4035 const guint8 *pdu_data;
4036 volatile guint16 data_length;
4040 /* Break out if meet padding */
4041 if (lcids[n] == PADDING_LCID) {
4045 /* Work out length */
4046 data_length = (pdu_lengths[n] == -1) ?
4047 tvb_length_remaining(tvb, offset) :
4050 /* Dissect SDU as raw bytes */
4051 sdu_ti = proto_tree_add_bytes_format(tree, hf_mac_lte_mch_sdu, tvb, offset, pdu_lengths[n],
4052 NULL, "SDU (%s, length=%u bytes): ",
4053 val_to_str_const(lcids[n], mch_lcid_vals, "Unknown"),
4055 /* Show bytes too. There must be a nicer way of doing this! */
4056 pdu_data = tvb_get_ptr(tvb, offset, pdu_lengths[n]);
4057 for (i=0; i < data_length; i++) {
4058 g_snprintf(buff+(i*2), 3, "%02x", pdu_data[i]);
4060 g_snprintf(buff+(i*2), 4, "...");
4064 proto_item_append_text(sdu_ti, "%s", buff);
4066 offset += data_length;
4069 /* Now padding, if present, extends to the end of the PDU */
4070 if (lcids[number_of_headers-1] == PADDING_LCID) {
4071 if (tvb_length_remaining(tvb, offset) > 0) {
4072 proto_tree_add_item(tree, hf_mac_lte_padding_data,
4073 tvb, offset, -1, ENC_NA);
4075 padding_length_ti = proto_tree_add_int(tree, hf_mac_lte_padding_length,
4077 p_mac_lte_info->length - offset);
4078 PROTO_ITEM_SET_GENERATED(padding_length_ti);
4080 /* Make sure the PDU isn't bigger than reported! */
4081 if (offset > p_mac_lte_info->length) {
4082 expert_add_info_format(pinfo, padding_length_ti, PI_MALFORMED, PI_ERROR,
4083 "MAC PDU is longer than reported length (reported=%u, actual=%u)",
4084 p_mac_lte_info->length, offset);
4088 /* There is no padding at the end of the frame */
4089 if (!is_truncated && (offset < p_mac_lte_info->length)) {
4090 /* There is a problem if we haven't used all of the PDU */
4091 expert_add_info_format(pinfo, pdu_ti, PI_MALFORMED, PI_ERROR,
4092 "PDU is shorter than reported length (reported=%u, actual=%u)",
4093 p_mac_lte_info->length, offset);
4096 if (!is_truncated && (offset > p_mac_lte_info->length)) {
4097 /* There is a problem if the PDU is longer than rpeported */
4098 expert_add_info_format(pinfo, pdu_ti, PI_MALFORMED, PI_ERROR,
4099 "PDU is longer than reported length (reported=%u, actual=%u)",
4100 p_mac_lte_info->length, offset);
4106 /*****************************/
4107 /* Main dissection function. */
4108 void dissect_mac_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4110 proto_tree *mac_lte_tree;
4112 proto_tree *context_tree;
4113 proto_item *context_ti;
4114 proto_item *retx_ti = NULL;
4117 struct mac_lte_info *p_mac_lte_info = NULL;
4120 /* Allocate and zero tap struct */
4121 mac_lte_tap_info *tap_info = ep_alloc0(sizeof(mac_lte_tap_info));
4123 /* Set protocol name */
4124 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MAC-LTE");
4126 /* Create protocol tree. */
4127 pdu_ti = proto_tree_add_item(tree, proto_mac_lte, tvb, offset, -1, ENC_NA);
4128 proto_item_append_text(pdu_ti, " ");
4129 mac_lte_tree = proto_item_add_subtree(pdu_ti, ett_mac_lte);
4132 /* Look for packet info! */
4133 p_mac_lte_info = p_get_proto_data(pinfo->fd, proto_mac_lte);
4135 /* Can't dissect anything without it... */
4136 if (p_mac_lte_info == NULL) {
4138 proto_tree_add_text(mac_lte_tree, tvb, offset, -1,
4139 "Can't dissect LTE MAC frame because no per-frame info was attached!");
4140 PROTO_ITEM_SET_GENERATED(tii);
4144 /* Clear info column */
4145 col_clear(pinfo->cinfo, COL_INFO);
4148 /*****************************************/
4149 /* Show context information */
4151 /* Create context root */
4152 context_ti = proto_tree_add_string_format(mac_lte_tree, hf_mac_lte_context,
4153 tvb, offset, 0, "", "Context");
4154 context_tree = proto_item_add_subtree(context_ti, ett_mac_lte_context);
4155 PROTO_ITEM_SET_GENERATED(context_ti);
4157 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_radio_type,
4158 tvb, 0, 0, p_mac_lte_info->radioType);
4159 PROTO_ITEM_SET_GENERATED(ti);
4161 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_direction,
4162 tvb, 0, 0, p_mac_lte_info->direction);
4163 PROTO_ITEM_SET_GENERATED(ti);
4165 if (p_mac_lte_info->ueid != 0) {
4166 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_ueid,
4167 tvb, 0, 0, p_mac_lte_info->ueid);
4168 PROTO_ITEM_SET_GENERATED(ti);
4171 /* There are several out-of-band MAC events that may be indicated in the context info. */
4172 /* Handle them here */
4173 if (p_mac_lte_info->length == 0) {
4174 proto_item *preamble_ti;
4175 proto_tree *preamble_tree;
4177 switch (p_mac_lte_info->oob_event) {
4178 case ltemac_send_preamble:
4179 preamble_ti = proto_tree_add_item(mac_lte_tree, hf_mac_lte_oob_send_preamble,
4180 tvb, 0, 0, ENC_ASCII|ENC_NA);
4181 preamble_tree = proto_item_add_subtree(preamble_ti, ett_mac_lte_oob);
4182 PROTO_ITEM_SET_GENERATED(ti);
4184 ti = proto_tree_add_uint(preamble_tree, hf_mac_lte_context_rapid,
4185 tvb, 0, 0, p_mac_lte_info->rapid);
4186 PROTO_ITEM_SET_GENERATED(ti);
4188 ti = proto_tree_add_uint(preamble_tree, hf_mac_lte_context_rach_attempt_number,
4189 tvb, 0, 0, p_mac_lte_info->rach_attempt_number);
4190 PROTO_ITEM_SET_GENERATED(ti);
4193 write_pdu_label_and_info(pdu_ti, preamble_ti, pinfo,
4194 "RACH Preamble sent for UE %u (RAPID=%u, attempt=%u)",
4195 p_mac_lte_info->ueid, p_mac_lte_info->rapid, p_mac_lte_info->rach_attempt_number);
4197 /* Add expert info (a note, unless attempt > 1) */
4198 expert_add_info_format(pinfo, ti, PI_SEQUENCE,
4199 (p_mac_lte_info->rach_attempt_number > 1) ? PI_WARN : PI_NOTE,
4200 "RACH Preamble sent for UE %u (RAPID=%u, attempt=%u)",
4201 p_mac_lte_info->ueid, p_mac_lte_info->rapid,
4202 p_mac_lte_info->rach_attempt_number);
4204 case ltemac_send_sr:
4206 ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_number_of_srs,
4207 tvb, 0, 0, p_mac_lte_info->number_of_srs);
4208 PROTO_ITEM_SET_GENERATED(ti);
4211 for (n=0; n < p_mac_lte_info->number_of_srs; n++) {
4213 proto_tree *sr_tree;
4215 /* SR event is subtree */
4216 sr_ti = proto_tree_add_item(mac_lte_tree, hf_mac_lte_oob_send_sr,
4218 sr_tree = proto_item_add_subtree(sr_ti, ett_mac_lte_oob);
4219 PROTO_ITEM_SET_GENERATED(sr_ti);
4223 ti = proto_tree_add_uint(sr_tree, hf_mac_lte_context_rnti,
4224 tvb, 0, 0, p_mac_lte_info->oob_rnti[n]);
4225 PROTO_ITEM_SET_GENERATED(ti);
4228 ti = proto_tree_add_uint(sr_tree, hf_mac_lte_context_ueid,
4229 tvb, 0, 0, p_mac_lte_info->oob_ueid[n]);
4230 PROTO_ITEM_SET_GENERATED(ti);
4232 /* Add summary to root. */
4233 proto_item_append_text(sr_ti, " (UE=%u C-RNTI=%u)",
4234 p_mac_lte_info->oob_ueid[n],
4235 p_mac_lte_info->oob_rnti[n]);
4239 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
4240 "Scheduling Requests (%u) sent: (UE=%u C-RNTI=%u)",
4241 p_mac_lte_info->number_of_srs,
4242 p_mac_lte_info->oob_ueid[n],
4243 p_mac_lte_info->oob_rnti[n]);
4246 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
4247 " (UE=%u C-RNTI=%u)",
4248 p_mac_lte_info->oob_ueid[n],
4249 p_mac_lte_info->oob_rnti[n]);
4252 /* Add expert info (a note) */
4253 expert_add_info_format(pinfo, sr_ti, PI_SEQUENCE, PI_NOTE,
4254 "Scheduling Request sent for UE %u (RNTI %u)",
4255 p_mac_lte_info->oob_ueid[n],
4256 p_mac_lte_info->oob_rnti[n]);
4258 /* Update SR status for this UE */
4259 if (global_mac_lte_track_sr) {
4260 TrackSRInfo(SR_Request, pinfo, mac_lte_tree, tvb, p_mac_lte_info, n, sr_ti);
4264 case ltemac_sr_failure:
4265 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_rnti,
4266 tvb, 0, 0, p_mac_lte_info->rnti);
4267 PROTO_ITEM_SET_GENERATED(ti);
4269 ti = proto_tree_add_item(mac_lte_tree, hf_mac_lte_oob_sr_failure,
4271 PROTO_ITEM_SET_GENERATED(ti);
4274 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
4275 "Scheduling Request FAILED for UE %u (C-RNTI=%u)",
4276 p_mac_lte_info->ueid,
4277 p_mac_lte_info->rnti);
4279 /* Add expert info (an error) */
4280 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_ERROR,
4281 "Scheduling Request failed for UE %u (RNTI %u)",
4282 p_mac_lte_info->ueid,
4283 p_mac_lte_info->rnti);
4285 /* Update SR status */
4286 if (global_mac_lte_track_sr) {
4287 TrackSRInfo(SR_Failure, pinfo, mac_lte_tree, tvb, p_mac_lte_info, 0, ti);
4293 /* Our work here is done */
4297 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_sysframe_number,
4298 tvb, 0, 0, p_mac_lte_info->sysframeNumber);
4299 PROTO_ITEM_SET_GENERATED(ti);
4301 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_subframe_number,
4302 tvb, 0, 0, p_mac_lte_info->subframeNumber);
4303 PROTO_ITEM_SET_GENERATED(ti);
4304 if (p_mac_lte_info->subframeNumber > 9) {
4305 /* N.B. if we set it to valid value, it won't trigger when we rescan
4306 (at least with DCT2000 files where the context struct isn't re-read). */
4307 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
4308 "Subframe number (%u) was out of range - valid range is 0-9",
4309 p_mac_lte_info->subframeNumber);
4312 if (p_mac_lte_info->subframeNumberOfGrantPresent) {
4313 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_grant_subframe_number,
4314 tvb, 0, 0, p_mac_lte_info->subframeNumberOfGrant);
4315 PROTO_ITEM_SET_GENERATED(ti);
4318 if (p_mac_lte_info->rntiType != NO_RNTI) {
4319 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_rnti,
4320 tvb, 0, 0, p_mac_lte_info->rnti);
4321 PROTO_ITEM_SET_GENERATED(ti);
4324 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_rnti_type,
4325 tvb, 0, 0, p_mac_lte_info->rntiType);
4326 PROTO_ITEM_SET_GENERATED(ti);
4328 /* Check that RNTI value is consistent with given RNTI type */
4329 switch (p_mac_lte_info->rntiType) {
4331 if (p_mac_lte_info->rnti != 0xFFFD) {
4332 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
4333 "M-RNTI indicated, but value is %u (0x%x) (must be 0x%x)",
4334 p_mac_lte_info->rnti, p_mac_lte_info->rnti, 0xFFFD);
4339 if (p_mac_lte_info->rnti != 0xFFFE) {
4340 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
4341 "P-RNTI indicated, but value is %u (0x%x) (must be 0x%x)",
4342 p_mac_lte_info->rnti, p_mac_lte_info->rnti, 0xFFFE);
4347 if (p_mac_lte_info->rnti != 0xFFFF) {
4348 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
4349 "SI-RNTI indicated, but value is %u (0x%x) (must be 0x%x)",
4350 p_mac_lte_info->rnti, p_mac_lte_info->rnti, 0xFFFE);
4355 if ((p_mac_lte_info->rnti < 0x0001) || (p_mac_lte_info->rnti > 0x003C)) {
4356 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
4357 "RA_RNTI indicated, but given value %u (0x%x)is out of range",
4358 p_mac_lte_info->rnti, p_mac_lte_info->rnti);
4364 if ((p_mac_lte_info->rnti < 0x0001) || (p_mac_lte_info->rnti > 0xFFF3)) {
4365 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
4366 "%s indicated, but given value %u (0x%x)is out of range",
4367 val_to_str_const(p_mac_lte_info->rntiType, rnti_type_vals, "Unknown"),
4368 p_mac_lte_info->rnti, p_mac_lte_info->rnti);
4377 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_predefined_frame,
4378 tvb, 0, 0, p_mac_lte_info->isPredefinedData);
4379 if (p_mac_lte_info->isPredefinedData) {
4380 PROTO_ITEM_SET_GENERATED(ti);
4383 PROTO_ITEM_SET_HIDDEN(ti);
4386 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_length,
4387 tvb, 0, 0, p_mac_lte_info->length);
4388 PROTO_ITEM_SET_GENERATED(ti);
4389 /* Infer uplink grant size */
4390 if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
4391 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_ul_grant_size,
4392 tvb, 0, 0, p_mac_lte_info->length);
4393 PROTO_ITEM_SET_GENERATED(ti);
4396 /* Retx count goes in top-level tree to make it more visible */
4397 if (p_mac_lte_info->reTxCount) {
4398 proto_item *retx_reason_ti;
4399 retx_ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_context_retx_count,
4400 tvb, 0, 0, p_mac_lte_info->reTxCount);
4401 PROTO_ITEM_SET_GENERATED(retx_ti);
4403 if (p_mac_lte_info->reTxCount >= global_mac_lte_retx_counter_trigger) {
4404 expert_add_info_format(pinfo, retx_ti, PI_SEQUENCE, PI_WARN,
4405 "UE %u: UL MAC frame ReTX no. %u",
4406 p_mac_lte_info->ueid, p_mac_lte_info->reTxCount);
4409 retx_reason_ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_context_retx_reason,
4410 tvb, 0, 0, p_mac_lte_info->isPHICHNACK);
4411 PROTO_ITEM_SET_GENERATED(retx_reason_ti);
4414 if (p_mac_lte_info->crcStatusValid) {
4416 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_crc_status,
4417 tvb, 0, 0, p_mac_lte_info->detailed_phy_info.dl_info.crc_status);
4418 PROTO_ITEM_SET_GENERATED(ti);
4420 /* Report non-success */
4421 if (p_mac_lte_info->detailed_phy_info.dl_info.crc_status != crc_success) {
4422 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
4423 "%s Frame has CRC error problem (%s)",
4424 (p_mac_lte_info->direction == DIRECTION_UPLINK) ? "UL" : "DL",
4425 val_to_str_const(p_mac_lte_info->detailed_phy_info.dl_info.crc_status,
4428 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
4429 "%s: <CRC %s> UEId=%u %s=%u ",
4430 (p_mac_lte_info->direction == DIRECTION_UPLINK) ? "UL" : "DL",
4431 val_to_str_const(p_mac_lte_info->detailed_phy_info.dl_info.crc_status,
4434 p_mac_lte_info->ueid,
4435 val_to_str_const(p_mac_lte_info->rntiType, rnti_type_vals,
4436 "Unknown RNTI type"),
4437 p_mac_lte_info->rnti);
4441 /* May also have extra Physical layer attributes set for this frame */
4442 show_extra_phy_parameters(pinfo, tvb, mac_lte_tree, p_mac_lte_info);
4444 /* Set context-info parts of tap struct */
4445 tap_info->rnti = p_mac_lte_info->rnti;
4446 tap_info->ueid = p_mac_lte_info->ueid;
4447 tap_info->rntiType = p_mac_lte_info->rntiType;
4448 tap_info->isPredefinedData = p_mac_lte_info->isPredefinedData;
4449 tap_info->isPHYRetx = (p_mac_lte_info->reTxCount >= 1);
4450 tap_info->crcStatusValid = p_mac_lte_info->crcStatusValid;
4451 tap_info->crcStatus = p_mac_lte_info->detailed_phy_info.dl_info.crc_status;
4452 tap_info->direction = p_mac_lte_info->direction;
4454 tap_info->time = pinfo->fd->abs_ts;
4456 /* Also set total number of bytes (won't be used for UL/DL-SCH) */
4457 tap_info->single_number_of_bytes = tvb_length_remaining(tvb, offset);
4459 /* If we know its predefined data, don't try to decode any further */
4460 if (p_mac_lte_info->isPredefinedData) {
4461 proto_tree_add_item(mac_lte_tree, hf_mac_lte_predefined_pdu, tvb, offset, -1, ENC_NA);
4462 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
4463 "Predefined data (%u bytes%s)",
4464 p_mac_lte_info->length,
4465 (p_mac_lte_info->length > tvb_length_remaining(tvb, offset) ?
4469 /* Queue tap info */
4470 if (!pinfo->flags.in_error_pkt) {
4471 tap_queue_packet(mac_lte_tap, pinfo, tap_info);
4477 /* IF CRC status failed, just do decode as raw bytes */
4478 if (!global_mac_lte_dissect_crc_failures &&
4479 (p_mac_lte_info->crcStatusValid &&
4480 (p_mac_lte_info->detailed_phy_info.dl_info.crc_status != crc_success))) {
4482 proto_tree_add_item(mac_lte_tree, hf_mac_lte_raw_pdu, tvb, offset, -1, ENC_NA);
4483 write_pdu_label_and_info(pdu_ti, NULL, pinfo, "Raw data (%u bytes)", tvb_length_remaining(tvb, offset));
4486 TODO: unfortunately DL retx detection won't get done if we return here... */
4487 if (!pinfo->flags.in_error_pkt) {
4488 tap_queue_packet(mac_lte_tap, pinfo, tap_info);
4494 /* Reset this counter */
4495 s_number_of_rlc_pdus_shown = 0;
4497 /* Dissect the MAC PDU itself. Format depends upon RNTI type. */
4498 switch (p_mac_lte_info->rntiType) {
4502 dissect_pch(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info->direction);
4507 dissect_rar(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info, tap_info);
4512 /* Can be UL-SCH or DL-SCH */
4513 dissect_ulsch_or_dlsch(tvb, pinfo, mac_lte_tree, pdu_ti, offset,
4514 p_mac_lte_info->direction, p_mac_lte_info, tap_info,
4515 retx_ti, context_tree);
4519 /* BCH over DL-SCH */
4520 dissect_bch(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info);
4525 dissect_mch(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info);
4529 /* Must be BCH over BCH... */
4530 dissect_bch(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info);
4538 /* Queue tap info */
4539 tap_queue_packet(mac_lte_tap, pinfo, tap_info);
4545 /* Initializes the hash tables each time a new
4546 * file is loaded or re-loaded in wireshark */
4547 static void mac_lte_init_protocol(void)
4549 /* Destroy any existing tables. */
4550 if (mac_lte_msg3_hash) {
4551 g_hash_table_destroy(mac_lte_msg3_hash);
4553 if (mac_lte_cr_result_hash) {
4554 g_hash_table_destroy(mac_lte_cr_result_hash);
4557 if (mac_lte_dl_harq_hash) {
4558 g_hash_table_destroy(mac_lte_dl_harq_hash);
4560 if (mac_lte_dl_harq_result_hash) {
4561 g_hash_table_destroy(mac_lte_dl_harq_result_hash);
4563 if (mac_lte_ul_harq_hash) {
4564 g_hash_table_destroy(mac_lte_ul_harq_hash);
4566 if (mac_lte_ul_harq_result_hash) {
4567 g_hash_table_destroy(mac_lte_ul_harq_result_hash);
4569 if (mac_lte_ue_sr_state) {
4570 g_hash_table_destroy(mac_lte_ue_sr_state);
4572 if (mac_lte_sr_request_hash) {
4573 g_hash_table_destroy(mac_lte_sr_request_hash);
4575 if (mac_lte_tti_info_result_hash) {
4576 g_hash_table_destroy(mac_lte_tti_info_result_hash);
4580 memset(&UL_tti_info, 0, sizeof(UL_tti_info));
4581 UL_tti_info.subframe = 0xff; /* Invalid value */
4582 memset(&DL_tti_info, 0, sizeof(DL_tti_info));
4583 DL_tti_info.subframe = 0xff; /* Invalid value */
4585 /* Now create them over */
4586 mac_lte_msg3_hash = g_hash_table_new(mac_lte_rnti_hash_func, mac_lte_rnti_hash_equal);
4587 mac_lte_cr_result_hash = g_hash_table_new(mac_lte_framenum_hash_func, mac_lte_framenum_hash_equal);
4589 mac_lte_dl_harq_hash = g_hash_table_new(mac_lte_rnti_hash_func, mac_lte_rnti_hash_equal);
4590 mac_lte_dl_harq_result_hash = g_hash_table_new(mac_lte_framenum_hash_func, mac_lte_framenum_hash_equal);
4592 mac_lte_ul_harq_hash = g_hash_table_new(mac_lte_rnti_hash_func, mac_lte_rnti_hash_equal);
4593 mac_lte_ul_harq_result_hash = g_hash_table_new(mac_lte_framenum_hash_func, mac_lte_framenum_hash_equal);
4595 mac_lte_ue_sr_state = g_hash_table_new(mac_lte_rnti_hash_func, mac_lte_rnti_hash_equal);
4596 mac_lte_sr_request_hash = g_hash_table_new(mac_lte_framenum_hash_func, mac_lte_framenum_hash_equal);
4598 mac_lte_tti_info_result_hash = g_hash_table_new(mac_lte_framenum_hash_func, mac_lte_framenum_hash_equal);
4602 static void* lcid_drb_mapping_copy_cb(void* dest, const void* orig, size_t len _U_)
4604 const lcid_drb_mapping_t *o = orig;
4605 lcid_drb_mapping_t *d = dest;
4607 /* Copy all items over */
4609 d->drbid = o->drbid;
4610 d->channel_type = o->channel_type;
4617 void proto_register_mac_lte(void)
4619 static hf_register_info hf[] =
4621 /**********************************/
4622 /* Items for decoding context */
4623 { &hf_mac_lte_context,
4625 "mac-lte.context", FT_STRING, BASE_NONE, NULL, 0x0,
4629 { &hf_mac_lte_context_radio_type,
4631 "mac-lte.radio-type", FT_UINT8, BASE_DEC, VALS(radio_type_vals), 0x0,
4635 { &hf_mac_lte_context_direction,
4637 "mac-lte.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
4638 "Direction of message", HFILL
4641 { &hf_mac_lte_context_rnti,
4643 "mac-lte.rnti", FT_UINT16, BASE_DEC, 0, 0x0,
4644 "RNTI associated with message", HFILL
4647 { &hf_mac_lte_context_rnti_type,
4649 "mac-lte.rnti-type", FT_UINT8, BASE_DEC, VALS(rnti_type_vals), 0x0,
4650 "Type of RNTI associated with message", HFILL
4653 { &hf_mac_lte_context_ueid,
4655 "mac-lte.ueid", FT_UINT16, BASE_DEC, 0, 0x0,
4656 "User Equipment Identifier associated with message", HFILL
4659 { &hf_mac_lte_context_sysframe_number,
4660 { "System Frame Number",
4661 "mac-lte.sfn", FT_UINT16, BASE_DEC, 0, 0x0,
4662 "System Frame Number associated with message", HFILL
4665 { &hf_mac_lte_context_subframe_number,
4667 "mac-lte.subframe", FT_UINT16, BASE_DEC, 0, 0x0,
4668 "Subframe number associated with message", HFILL
4671 { &hf_mac_lte_context_grant_subframe_number,
4673 "mac-lte.grant-subframe", FT_UINT16, BASE_DEC, 0, 0x0,
4674 "Subframe when grant for this PDU was received", HFILL
4677 { &hf_mac_lte_context_predefined_frame,
4678 { "Predefined frame",
4679 "mac-lte.is-predefined-frame", FT_UINT8, BASE_DEC, VALS(predefined_frame_vals), 0x0,
4680 "Predefined test frame (or real MAC PDU)", HFILL
4683 { &hf_mac_lte_context_length,
4684 { "Length of frame",
4685 "mac-lte.length", FT_UINT8, BASE_DEC, 0, 0x0,
4686 "Original length of frame (including SDUs and padding)", HFILL
4689 { &hf_mac_lte_context_ul_grant_size,
4690 { "Uplink grant size",
4691 "mac-lte.ul-grant-size", FT_UINT8, BASE_DEC, 0, 0x0,
4692 "Uplink grant size (in bytes)", HFILL
4695 { &hf_mac_lte_context_bch_transport_channel,
4696 { "Transport channel",
4697 "mac-lte.bch-transport-channel", FT_UINT8, BASE_DEC, VALS(bch_transport_channel_vals), 0x0,
4698 "Transport channel BCH data was carried on", HFILL
4701 { &hf_mac_lte_context_retx_count,
4703 "mac-lte.retx-count", FT_UINT8, BASE_DEC, 0, 0x0,
4704 "Number of times this PDU has been retransmitted", HFILL
4707 { &hf_mac_lte_context_retx_reason,
4709 "mac-lte.retx-reason", FT_UINT8, BASE_DEC, VALS(ul_retx_grant_vals), 0x0,
4710 "Type of UL ReTx grant", HFILL
4713 { &hf_mac_lte_context_crc_status,
4715 "mac-lte.crc-status", FT_UINT8, BASE_DEC, VALS(crc_status_vals), 0x0,
4716 "CRC Status as reported by PHY", HFILL
4719 { &hf_mac_lte_context_rapid,
4721 "mac-lte.preamble-sent.rapid", FT_UINT8, BASE_DEC, 0, 0x0,
4722 "RAPID sent in RACH preamble", HFILL
4725 { &hf_mac_lte_context_rach_attempt_number,
4726 { "RACH Attempt Number",
4727 "mac-lte.preamble-sent.attempt", FT_UINT8, BASE_DEC, 0, 0x0,
4732 { &hf_mac_lte_ues_ul_per_tti,
4734 "mac-lte.ul-tti-count", FT_UINT8, BASE_DEC, 0, 0x0,
4735 "In this TTI, this is the nth UL grant", HFILL
4738 { &hf_mac_lte_ues_dl_per_tti,
4740 "mac-lte.dl-tti-count", FT_UINT8, BASE_DEC, 0, 0x0,
4741 "In this TTI, this is the nth DL PDU", HFILL
4746 /* Extra PHY context */
4747 { &hf_mac_lte_context_phy_ul,
4748 { "UL PHY attributes",
4749 "mac-lte.ul-phy", FT_STRING, BASE_NONE, 0, 0x0,
4753 { &hf_mac_lte_context_phy_ul_modulation_type,
4754 { "Modulation type",
4755 "mac-lte.ul-phy.modulation-type", FT_UINT8, BASE_DEC, VALS(modulation_type_vals), 0x0,
4759 { &hf_mac_lte_context_phy_ul_tbs_index,
4761 "mac-lte.ul-phy.tbs-index", FT_UINT8, BASE_DEC, 0, 0x0,
4765 { &hf_mac_lte_context_phy_ul_resource_block_length,
4766 { "Resource Block Length",
4767 "mac-lte.ul-phy.resource-block-length", FT_UINT8, BASE_DEC, 0, 0x0,
4771 { &hf_mac_lte_context_phy_ul_resource_block_start,
4772 { "Resource Block Start",
4773 "mac-lte.ul-phy.resource-block-start", FT_UINT8, BASE_DEC, 0, 0x0,
4777 { &hf_mac_lte_context_phy_ul_harq_id,
4779 "mac-lte.ul-phy.harq-id", FT_UINT8, BASE_DEC, 0, 0x0,
4783 { &hf_mac_lte_context_phy_ul_ndi,
4785 "mac-lte.ul-phy.ndi", FT_UINT8, BASE_DEC, 0, 0x0,
4786 "UL New Data Indicator", HFILL
4790 { &hf_mac_lte_context_phy_dl,
4791 { "DL PHY attributes",
4792 "mac-lte.dl-phy", FT_STRING, BASE_NONE, 0, 0x0,
4796 { &hf_mac_lte_context_phy_dl_dci_format,
4798 "mac-lte.dl-phy.dci-format", FT_UINT8, BASE_DEC, VALS(dci_format_vals), 0x0,
4802 { &hf_mac_lte_context_phy_dl_resource_allocation_type,
4803 { "Resource Allocation Type",
4804 "mac-lte.dl-phy.resource-allocation-type", FT_UINT8, BASE_DEC, 0, 0x0,
4808 { &hf_mac_lte_context_phy_dl_aggregation_level,
4809 { "Aggregation Level",
4810 "mac-lte.dl-phy.aggregation-level", FT_UINT8, BASE_DEC, VALS(aggregation_level_vals), 0x0,
4814 { &hf_mac_lte_context_phy_dl_mcs_index,
4816 "mac-lte.dl-phy.mcs-index", FT_UINT8, BASE_DEC, 0, 0x0,
4820 { &hf_mac_lte_context_phy_dl_redundancy_version_index,
4822 "mac-lte.dl-phy.rv-index", FT_UINT8, BASE_DEC, 0, 0x0,
4826 { &hf_mac_lte_context_phy_dl_retx,
4828 "mac-lte.dl-phy.dl-retx", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4832 { &hf_mac_lte_context_phy_dl_resource_block_length,
4834 "mac-lte.dl-phy.rb-length", FT_UINT8, BASE_DEC, 0, 0x0,
4838 { &hf_mac_lte_context_phy_dl_crc_status,
4840 "mac-lte.dl-phy.crc-status", FT_UINT8, BASE_DEC, VALS(crc_status_vals), 0x0,
4844 { &hf_mac_lte_context_phy_dl_harq_id,
4846 "mac-lte.dl-phy.harq-id", FT_UINT8, BASE_DEC, 0, 0x0,
4850 { &hf_mac_lte_context_phy_dl_ndi,
4852 "mac-lte.dl-phy.ndi", FT_UINT8, BASE_DEC, 0, 0x0,
4853 "New Data Indicator", HFILL
4856 { &hf_mac_lte_context_phy_dl_tb,
4858 "mac-lte.dl-phy.tb", FT_UINT8, BASE_DEC, 0, 0x0,
4859 "Transport Block (antenna #)", HFILL
4863 /* Out-of-band events */
4864 { &hf_mac_lte_oob_send_preamble,
4866 "mac-lte.preamble-sent", FT_STRING, BASE_NONE, NULL, 0x0,
4870 { &hf_mac_lte_oob_send_sr,
4871 { "Scheduling Request sent",
4872 "mac-lte.sr-req", FT_NONE, BASE_NONE, NULL, 0x0,
4876 { &hf_mac_lte_number_of_srs,
4878 "mac-lte.sr-req.count", FT_UINT32, BASE_DEC, 0, 0x0,
4879 "Number of UEs doing SR in this frame", HFILL
4882 { &hf_mac_lte_oob_sr_failure,
4883 { "Scheduling Request failure",
4884 "mac-lte.sr-failure", FT_NONE, BASE_NONE, NULL, 0x0,
4889 /*******************************************/
4890 /* MAC shared channel header fields */
4891 { &hf_mac_lte_ulsch,
4893 "mac-lte.ulsch", FT_STRING, BASE_NONE, NULL, 0x0,
4897 { &hf_mac_lte_ulsch_header,
4899 "mac-lte.ulsch.header", FT_STRING, BASE_NONE, NULL, 0x0,
4903 { &hf_mac_lte_dlsch_header,
4905 "mac-lte.dlsch.header", FT_STRING, BASE_NONE, NULL, 0x0,
4909 { &hf_mac_lte_dlsch,
4911 "mac-lte.dlsch", FT_STRING, BASE_NONE, NULL, 0x0,
4915 { &hf_mac_lte_sch_subheader,
4917 "mac-lte.sch.subheader", FT_STRING, BASE_NONE, NULL, 0x0,
4923 "mac-lte.mch", FT_STRING, BASE_NONE, NULL, 0x0,
4927 { &hf_mac_lte_mch_header,
4929 "mac-lte.mch.header", FT_STRING, BASE_NONE, NULL, 0x0,
4933 { &hf_mac_lte_mch_subheader,
4935 "mac-lte.mch.subheader", FT_STRING, BASE_NONE, NULL, 0x0,
4939 { &hf_mac_lte_sch_reserved,
4940 { "SCH reserved bits",
4941 "mac-lte.sch.reserved", FT_UINT8, BASE_HEX, NULL, 0xc0,
4945 { &hf_mac_lte_sch_extended,
4947 "mac-lte.sch.extended", FT_UINT8, BASE_HEX, 0, 0x20,
4948 "Extension - i.e. further headers after this one", HFILL
4951 { &hf_mac_lte_dlsch_lcid,
4953 "mac-lte.dlsch.lcid", FT_UINT8, BASE_HEX, VALS(dlsch_lcid_vals), 0x1f,
4954 "DL-SCH Logical Channel Identifier", HFILL
4957 { &hf_mac_lte_ulsch_lcid,
4959 "mac-lte.ulsch.lcid", FT_UINT8, BASE_HEX, VALS(ulsch_lcid_vals), 0x1f,
4960 "UL-SCH Logical Channel Identifier", HFILL
4963 { &hf_mac_lte_sch_format,
4965 "mac-lte.sch.format", FT_UINT8, BASE_HEX, VALS(format_vals), 0x80,
4969 { &hf_mac_lte_sch_length,
4971 "mac-lte.sch.length", FT_UINT16, BASE_DEC, 0, 0x0,
4972 "Length of MAC SDU or MAC control element", HFILL
4975 { &hf_mac_lte_mch_reserved,
4976 { "MCH reserved bits",
4977 "mac-lte.mch.reserved", FT_UINT8, BASE_HEX, NULL, 0xc0,
4981 { &hf_mac_lte_mch_extended,
4983 "mac-lte.mch.extended", FT_UINT8, BASE_HEX, 0, 0x20,
4984 "Extension - i.e. further headers after this one", HFILL
4987 { &hf_mac_lte_mch_lcid,
4989 "mac-lte.mch.lcid", FT_UINT8, BASE_HEX, VALS(mch_lcid_vals), 0x1f,
4990 "MCH Logical Channel Identifier", HFILL
4993 { &hf_mac_lte_mch_format,
4995 "mac-lte.mch.format", FT_UINT8, BASE_HEX, VALS(format_vals), 0x80,
4999 { &hf_mac_lte_mch_length,
5001 "mac-lte.mch.length", FT_UINT16, BASE_DEC, 0, 0x0,
5002 "Length of MAC SDU or MAC control element", HFILL
5005 { &hf_mac_lte_sch_header_only,
5006 { "MAC PDU Header only",
5007 "mac-lte.sch.header-only", FT_UINT8, BASE_DEC, VALS(header_only_vals), 0x0,
5011 { &hf_mac_lte_mch_header_only,
5012 { "MAC PDU Header only",
5013 "mac-lte.mch.header-only", FT_UINT8, BASE_DEC, VALS(header_only_vals), 0x0,
5018 /********************************/
5020 { &hf_mac_lte_sch_sdu,
5022 "mac-lte.sch.sdu", FT_BYTES, BASE_NONE, 0, 0x0,
5023 "Shared channel SDU", HFILL
5026 { &hf_mac_lte_mch_sdu,
5028 "mac-lte.mch.sdu", FT_BYTES, BASE_NONE, 0, 0x0,
5029 "Multicast channel SDU", HFILL
5032 { &hf_mac_lte_bch_pdu,
5034 "mac-lte.bch.pdu", FT_BYTES, BASE_NONE, 0, 0x0,
5038 { &hf_mac_lte_pch_pdu,
5040 "mac-lte.pch.pdu", FT_BYTES, BASE_NONE, 0, 0x0,
5044 { &hf_mac_lte_predefined_pdu,
5045 { "Predefined data",
5046 "mac-lte.predefined-data", FT_BYTES, BASE_NONE, 0, 0x0,
5047 "Predefined test data", HFILL
5050 { &hf_mac_lte_raw_pdu,
5052 "mac-lte.raw-data", FT_BYTES, BASE_NONE, 0, 0x0,
5053 "Raw bytes of PDU (e.g. if CRC error)", HFILL
5056 { &hf_mac_lte_padding_data,
5058 "mac-lte.padding-data", FT_BYTES, BASE_NONE, 0, 0x0,
5062 { &hf_mac_lte_padding_length,
5064 "mac-lte.padding-length", FT_INT32, BASE_DEC, 0, 0x0,
5065 "Length of padding data not included at end of frame", HFILL
5071 /*********************************/
5075 "mac-lte.rar", FT_NONE, BASE_NONE, NULL, 0x0,
5079 { &hf_mac_lte_rar_headers,
5081 "mac-lte.rar.headers", FT_STRING, BASE_NONE, NULL, 0x0,
5085 { &hf_mac_lte_rar_header,
5087 "mac-lte.rar.header", FT_STRING, BASE_NONE, NULL, 0x0,
5091 { &hf_mac_lte_rar_extension,
5093 "mac-lte.rar.e", FT_UINT8, BASE_HEX, 0, 0x80,
5094 "Extension - i.e. further RAR headers after this one", HFILL
5097 { &hf_mac_lte_rar_t,
5099 "mac-lte.rar.t", FT_UINT8, BASE_HEX, VALS(rar_type_vals), 0x40,
5100 "Type field indicating whether the payload is RAPID or BI", HFILL
5103 { &hf_mac_lte_rar_bi,
5105 "mac-lte.rar.bi", FT_UINT8, BASE_HEX, VALS(rar_bi_vals), 0x0f,
5106 "Backoff Indicator (ms)", HFILL
5109 { &hf_mac_lte_rar_rapid,
5111 "mac-lte.rar.rapid", FT_UINT8, BASE_HEX_DEC, 0, 0x3f,
5112 "Random Access Preamble IDentifier", HFILL
5115 { &hf_mac_lte_rar_reserved,
5117 "mac-lte.rar.reserved", FT_UINT8, BASE_HEX, 0, 0x30,
5118 "Reserved bits in RAR header - should be 0", HFILL
5122 { &hf_mac_lte_rar_body,
5124 "mac-lte.rar.body", FT_STRING, BASE_NONE, NULL, 0x0,
5128 { &hf_mac_lte_rar_reserved2,
5130 "mac-lte.rar.reserved2", FT_UINT8, BASE_HEX, 0, 0x80,
5131 "Reserved bit in RAR body - should be 0", HFILL
5134 { &hf_mac_lte_rar_ta,
5136 "mac-lte.rar.ta", FT_UINT16, BASE_DEC, 0, 0x7ff0,
5137 "Required adjustment to uplink transmission timing", HFILL
5140 { &hf_mac_lte_rar_ul_grant,
5142 "mac-lte.rar.ul-grant", FT_UINT24, BASE_DEC, 0, 0x0fffff,
5143 "Size of UL Grant", HFILL
5146 { &hf_mac_lte_rar_ul_grant_hopping,
5148 "mac-lte.rar.ul-grant.hopping", FT_UINT8, BASE_DEC, 0, 0x08,
5152 { &hf_mac_lte_rar_ul_grant_fsrba,
5153 { "Fixed sized resource block assignment",
5154 "mac-lte.rar.ul-grant.fsrba", FT_UINT16, BASE_DEC, 0, 0x07fe,
5158 { &hf_mac_lte_rar_ul_grant_tmcs,
5159 { "Truncated Modulation and coding scheme",
5160 "mac-lte.rar.ul-grant.tmcs", FT_UINT16, BASE_DEC, 0, 0x01e0,
5164 { &hf_mac_lte_rar_ul_grant_tcsp,
5165 { "TPC command for scheduled PUSCH",
5166 "mac-lte.rar.ul-grant.tcsp", FT_UINT8, BASE_DEC, 0, 0x01c,
5170 { &hf_mac_lte_rar_ul_grant_ul_delay,
5172 "mac-lte.rar.ul-grant.ul-delay", FT_UINT8, BASE_DEC, 0, 0x02,
5176 { &hf_mac_lte_rar_ul_grant_cqi_request,
5178 "mac-lte.rar.ul-grant.cqi-request", FT_UINT8, BASE_DEC, 0, 0x01,
5182 { &hf_mac_lte_rar_temporary_crnti,
5183 { "Temporary C-RNTI",
5184 "mac-lte.rar.temporary-crnti", FT_UINT16, BASE_DEC, 0, 0x0,
5189 /**********************/
5190 /* Control PDU fields */
5191 { &hf_mac_lte_control_bsr,
5193 "mac-lte.control.bsr", FT_STRING, BASE_NONE, 0, 0x0,
5194 "Buffer Status Report", HFILL
5197 { &hf_mac_lte_control_bsr_lcg_id,
5198 { "Logical Channel Group ID",
5199 "mac-lte.control.bsr.lcg-id", FT_UINT8, BASE_DEC, 0, 0xc0,
5203 { &hf_mac_lte_control_short_bsr_buffer_size,
5205 "mac-lte.control.bsr.buffer-size", FT_UINT8, BASE_DEC|BASE_EXT_STRING, &buffer_size_vals_ext, 0x3f,
5206 "Buffer Size available in all channels in group", HFILL
5209 { &hf_mac_lte_control_long_bsr_buffer_size_0,
5211 "mac-lte.control.bsr.buffer-size-0", FT_UINT8, BASE_DEC|BASE_EXT_STRING, &buffer_size_vals_ext, 0xfc,
5212 "Buffer Size available in logical channel group 0", HFILL
5215 { &hf_mac_lte_control_long_bsr_buffer_size_1,
5217 "mac-lte.control.bsr.buffer-size-1", FT_UINT16, BASE_DEC|BASE_EXT_STRING, &buffer_size_vals_ext, 0x03f0,
5218 "Buffer Size available in logical channel group 1", HFILL
5221 { &hf_mac_lte_control_long_bsr_buffer_size_2,
5223 "mac-lte.control.bsr.buffer-size-2", FT_UINT16, BASE_DEC|BASE_EXT_STRING, &buffer_size_vals_ext, 0x0fc0,
5224 "Buffer Size available in logical channel group 2", HFILL
5227 { &hf_mac_lte_control_long_bsr_buffer_size_3,
5229 "mac-lte.control.bsr.buffer-size-3", FT_UINT8, BASE_DEC|BASE_EXT_STRING, &buffer_size_vals_ext, 0x3f,
5230 "Buffer Size available in logical channel group 3", HFILL
5233 { &hf_mac_lte_control_short_ext_bsr_buffer_size,
5235 "mac-lte.control.bsr.buffer-size", FT_UINT8, BASE_DEC|BASE_EXT_STRING, &ext_buffer_size_vals_ext, 0x3f,
5236 "Buffer Size available in all channels in group", HFILL
5239 { &hf_mac_lte_control_long_ext_bsr_buffer_size_0,
5241 "mac-lte.control.bsr.buffer-size-0", FT_UINT8, BASE_DEC|BASE_EXT_STRING, &ext_buffer_size_vals_ext, 0xfc,
5242 "Buffer Size available in logical channel group 0", HFILL
5245 { &hf_mac_lte_control_long_ext_bsr_buffer_size_1,
5247 "mac-lte.control.bsr.buffer-size-1", FT_UINT16, BASE_DEC|BASE_EXT_STRING, &ext_buffer_size_vals_ext, 0x03f0,
5248 "Buffer Size available in logical channel group 1", HFILL
5251 { &hf_mac_lte_control_long_ext_bsr_buffer_size_2,
5253 "mac-lte.control.bsr.buffer-size-2", FT_UINT16, BASE_DEC|BASE_EXT_STRING, &ext_buffer_size_vals_ext, 0x0fc0,
5254 "Buffer Size available in logical channel group 2", HFILL
5257 { &hf_mac_lte_control_long_ext_bsr_buffer_size_3,
5259 "mac-lte.control.bsr.buffer-size-3", FT_UINT8, BASE_DEC|BASE_EXT_STRING, &ext_buffer_size_vals_ext, 0x3f,
5260 "Buffer Size available in logical channel group 3", HFILL
5263 { &hf_mac_lte_control_crnti,
5265 "mac-lte.control.crnti", FT_UINT16, BASE_DEC, 0, 0x0,
5266 "C-RNTI for the UE", HFILL
5269 { &hf_mac_lte_control_timing_advance,
5271 "mac-lte.control.timing-advance", FT_UINT8, BASE_DEC, 0, 0x3f,
5272 "Timing Advance (0-1282 - see 36.213, 4.2.3)", HFILL
5275 { &hf_mac_lte_control_timing_advance_reserved,
5277 "mac-lte.control.timing-advance.reserved", FT_UINT8, BASE_HEX, 0, 0xc0,
5278 "Reserved bits", HFILL
5281 { &hf_mac_lte_control_ue_contention_resolution,
5282 { "UE Contention Resolution",
5283 "mac-lte.control.ue-contention-resolution", FT_STRING, BASE_NONE, 0, 0x0,
5287 { &hf_mac_lte_control_ue_contention_resolution_identity,
5288 { "UE Contention Resolution Identity",
5289 "mac-lte.control.ue-contention-resolution.identity", FT_BYTES, BASE_NONE, 0, 0x0,
5293 { &hf_mac_lte_control_ue_contention_resolution_msg3,
5295 "mac-lte.control.ue-contention-resolution.msg3", FT_FRAMENUM, BASE_NONE, 0, 0x0,
5299 { &hf_mac_lte_control_ue_contention_resolution_msg3_matched,
5300 { "UE Contention Resolution Matches Msg3",
5301 "mac-lte.control.ue-contention-resolution.matches-msg3", FT_BOOLEAN, BASE_NONE, 0, 0x0,
5305 { &hf_mac_lte_control_ue_contention_resolution_time_since_msg3,
5306 { "Time since Msg3",
5307 "mac-lte.control.ue-contention-resolution.time-since-msg3", FT_UINT32, BASE_DEC, 0, 0x0,
5308 "Time in ms since corresponding Msg3", HFILL
5312 { &hf_mac_lte_control_power_headroom,
5314 "mac-lte.control.power-headroom", FT_STRING, BASE_NONE, 0, 0x0,
5318 { &hf_mac_lte_control_power_headroom_reserved,
5320 "mac-lte.control.power-headroom.reserved", FT_UINT8, BASE_DEC, 0, 0xc0,
5321 "Reserved bits, should be 0", HFILL
5324 { &hf_mac_lte_control_power_headroom_level,
5325 { "Power Headroom Level",
5326 "mac-lte.control.power-headroom.level", FT_UINT8, BASE_DEC|BASE_EXT_STRING,
5327 &power_headroom_vals_ext, 0x3f, "Power Headroom Level in dB", HFILL
5331 { &hf_mac_lte_control_ext_power_headroom,
5332 { "Extended Power Headroom",
5333 "mac-lte.control.ext-power-headroom", FT_STRING, BASE_NONE,
5337 { &hf_mac_lte_control_ext_power_headroom_c7,
5338 { "SCell Index 7 Power Headroom",
5339 "mac-lte.control.ext-power-headroom.c7", FT_BOOLEAN, 8,
5340 TFS(&mac_lte_scell_ph_vals), 0x80, NULL, HFILL
5343 { &hf_mac_lte_control_ext_power_headroom_c6,
5344 { "SCell Index 6 Power Headroom",
5345 "mac-lte.control.ext-power-headroom.c6", FT_BOOLEAN, 8,
5346 TFS(&mac_lte_scell_ph_vals), 0x40, NULL, HFILL
5349 { &hf_mac_lte_control_ext_power_headroom_c5,
5350 { "SCell Index 5 Power Headroom",
5351 "mac-lte.control.ext-power-headroom.c5", FT_BOOLEAN, 8,
5352 TFS(&mac_lte_scell_ph_vals), 0x20, NULL, HFILL
5355 { &hf_mac_lte_control_ext_power_headroom_c4,
5356 { "SCell Index 4 Power Headroom",
5357 "mac-lte.control.ext-power-headroom.c4", FT_BOOLEAN, 8,
5358 TFS(&mac_lte_scell_ph_vals), 0x10, NULL, HFILL
5361 { &hf_mac_lte_control_ext_power_headroom_c3,
5362 { "SCell Index 3 Power Headroom",
5363 "mac-lte.control.ext-power-headroom.c3", FT_BOOLEAN, 8,
5364 TFS(&mac_lte_scell_ph_vals), 0x08, NULL, HFILL
5367 { &hf_mac_lte_control_ext_power_headroom_c2,
5368 { "SCell Index 2 Power Headroom",
5369 "mac-lte.control.ext-power-headroom.c2", FT_BOOLEAN, 8,
5370 TFS(&mac_lte_scell_ph_vals), 0x04, NULL, HFILL
5373 { &hf_mac_lte_control_ext_power_headroom_c1,
5374 { "SCell Index 1 Power Headroom",
5375 "mac-lte.control.ext-power-headroom.c1", FT_BOOLEAN, 8,
5376 TFS(&mac_lte_scell_ph_vals), 0x02, NULL, HFILL
5379 { &hf_mac_lte_control_ext_power_headroom_reserved,
5381 "mac-lte.control.ext-power-headroom.reserved", FT_UINT8, BASE_DEC,
5382 0, 0x01, "Reserved bit, should be 0", HFILL
5385 { &hf_mac_lte_control_ext_power_headroom_power_backoff,
5387 "mac-lte.control.ext-power-headroom.power-backoff", FT_BOOLEAN, 8,
5388 TFS(&mac_lte_power_backoff_vals), 0x80, NULL, HFILL
5391 { &hf_mac_lte_control_ext_power_headroom_value,
5392 { "Power Headroom Value",
5393 "mac-lte.control.ext-power-headroom.power-headroom-value", FT_BOOLEAN, 8,
5394 TFS(&mac_lte_ph_value_vals), 0x40, NULL, HFILL
5397 { &hf_mac_lte_control_ext_power_headroom_level,
5398 { "Power Headroom Level",
5399 "mac-lte.control.ext-power-headroom.level", FT_UINT8, BASE_DEC|BASE_EXT_STRING,
5400 &power_headroom_vals_ext, 0x3f, "Power Headroom Level in dB", HFILL
5403 { &hf_mac_lte_control_ext_power_headroom_reserved2,
5405 "mac-lte.control.ext-power-headroom.reserved2", FT_UINT8, BASE_DEC,
5406 0, 0xc0, "Reserved bits, should be 0", HFILL
5409 { &hf_mac_lte_control_ext_power_headroom_pcmaxc,
5410 { "Configured UE Transmit Power",
5411 "mac-lte.control.ext-power-headroom.pcmaxc", FT_UINT8, BASE_DEC|BASE_EXT_STRING,
5412 &pcmaxc_vals_ext, 0x3f, "Pcmax,c in dBm", HFILL
5416 { &hf_mac_lte_control_activation_deactivation,
5417 { "Activation/Deactivation",
5418 "mac-lte.control.activation-deactivation", FT_STRING, BASE_NONE,
5422 { &hf_mac_lte_control_activation_deactivation_c7,
5423 { "SCell Index 7 Status",
5424 "mac-lte.control.activation-deactivation.c7", FT_BOOLEAN, 8,
5425 TFS(&mac_lte_scell_status_vals), 0x80, NULL, HFILL
5428 { &hf_mac_lte_control_activation_deactivation_c6,
5429 { "SCell Index 6 Status",
5430 "mac-lte.control.activation-deactivation.c6", FT_BOOLEAN, 8,
5431 TFS(&mac_lte_scell_status_vals), 0x40, NULL, HFILL
5434 { &hf_mac_lte_control_activation_deactivation_c5,
5435 { "SCell Index 5 Status",
5436 "mac-lte.control.activation-deactivation.c5", FT_BOOLEAN, 8,
5437 TFS(&mac_lte_scell_status_vals), 0x20, NULL, HFILL
5440 { &hf_mac_lte_control_activation_deactivation_c4,
5441 { "SCell Index 4 Status",
5442 "mac-lte.control.activation-deactivation.c4", FT_BOOLEAN, 8,
5443 TFS(&mac_lte_scell_status_vals), 0x10, NULL, HFILL
5446 { &hf_mac_lte_control_activation_deactivation_c3,
5447 { "SCell Index 3 Status",
5448 "mac-lte.control.activation-deactivation.c3", FT_BOOLEAN, 8,
5449 TFS(&mac_lte_scell_status_vals), 0x08, NULL, HFILL
5452 { &hf_mac_lte_control_activation_deactivation_c2,
5453 { "SCell Index 2 Status",
5454 "mac-lte.control.activation-deactivation.c2", FT_BOOLEAN, 8,
5455 TFS(&mac_lte_scell_status_vals), 0x04, NULL, HFILL
5458 { &hf_mac_lte_control_activation_deactivation_c1,
5459 { "SCell Index 1 Status",
5460 "mac-lte.control.activation-deactivation.c1", FT_BOOLEAN, 8,
5461 TFS(&mac_lte_scell_status_vals), 0x02, NULL, HFILL
5464 { &hf_mac_lte_control_activation_deactivation_reserved,
5466 "mac-lte.control.activation-deactivation.reserved", FT_UINT8, BASE_DEC,
5467 0, 0x01, "Reserved bit, should be 0", HFILL
5471 { &hf_mac_lte_control_mch_scheduling_info,
5472 { "MCH Scheduling Information",
5473 "mac-lte.control.mch_scheduling_info", FT_STRING, BASE_NONE, 0, 0x0,
5477 { &hf_mac_lte_control_mch_scheduling_info_lcid,
5479 "mac-lte.control.mch_scheduling_info.lcid", FT_UINT8, BASE_HEX, VALS(mch_lcid_vals), 0xf8,
5480 "Logical Channel ID of the MTCH", HFILL
5483 { &hf_mac_lte_control_mch_scheduling_info_stop_mtch,
5485 "mac-lte.control.mch_scheduling_info.stop_mtch", FT_UINT16, BASE_DEC, 0, 0x07ff,
5486 "Ordinal number of the subframe where the corresponding MTCH stops", HFILL
5490 /* Generated fields */
5491 { &hf_mac_lte_dl_harq_resend_original_frame,
5492 { "Frame with previous tx",
5493 "mac-lte.dlsch.retx.original-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
5497 { &hf_mac_lte_dl_harq_resend_time_since_previous_frame,
5498 { "Time since previous tx (ms)",
5499 "mac-lte.dlsch.retx.time-since-previous", FT_UINT16, BASE_DEC, 0, 0x0,
5503 { &hf_mac_lte_dl_harq_resend_next_frame,
5504 { "Frame with next tx",
5505 "mac-lte.dlsch.retx.next-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
5509 { &hf_mac_lte_dl_harq_resend_time_until_next_frame,
5510 { "Time until next tx (ms)",
5511 "mac-lte.dlsch.retx.time-until-next", FT_UINT16, BASE_DEC, 0, 0x0,
5516 { &hf_mac_lte_ul_harq_resend_original_frame,
5517 { "Frame with previous tx",
5518 "mac-lte.ulsch.retx.original-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
5522 { &hf_mac_lte_ul_harq_resend_time_since_previous_frame,
5523 { "Time since previous tx (ms)",
5524 "mac-lte.ulsch.retx.time-since-previous", FT_UINT16, BASE_DEC, 0, 0x0,
5528 { &hf_mac_lte_ul_harq_resend_next_frame,
5529 { "Frame with next tx",
5530 "mac-lte.ulsch.retx.next-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
5534 { &hf_mac_lte_ul_harq_resend_time_until_next_frame,
5535 { "Time until next tx (ms)",
5536 "mac-lte.ulsch.retx.time-until-next", FT_UINT16, BASE_DEC, 0, 0x0,
5541 { &hf_mac_lte_grant_answering_sr,
5542 { "First Grant Following SR from",
5543 "mac-lte.ulsch.grant-answering-sr", FT_FRAMENUM, BASE_NONE, 0, 0x0,
5547 { &hf_mac_lte_failure_answering_sr,
5548 { "SR which failed",
5549 "mac-lte.ulsch.failure-answering-sr", FT_FRAMENUM, BASE_NONE, 0, 0x0,
5553 { &hf_mac_lte_sr_leading_to_failure,
5555 "mac-lte.ulsch.failure-answering-sr-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
5559 { &hf_mac_lte_sr_leading_to_grant,
5560 { "This SR results in a grant here",
5561 "mac-lte.ulsch.grant-answering-sr-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
5565 { &hf_mac_lte_sr_invalid_event,
5567 "mac-lte.ulsch.sr-invalid-event", FT_NONE, BASE_NONE, 0, 0x0,
5571 { &hf_mac_lte_sr_time_since_request,
5572 { "Time since SR (ms)",
5573 "mac-lte.ulsch.time-since-sr", FT_UINT32, BASE_DEC, 0, 0x0,
5577 { &hf_mac_lte_sr_time_until_answer,
5578 { "Time until answer (ms)",
5579 "mac-lte.ulsch.time-until-sr-answer", FT_UINT32, BASE_DEC, 0, 0x0,
5586 static gint *ett[] =
5589 &ett_mac_lte_context,
5590 &ett_mac_lte_phy_context,
5591 &ett_mac_lte_rar_headers,
5592 &ett_mac_lte_rar_header,
5593 &ett_mac_lte_rar_body,
5594 &ett_mac_lte_rar_ul_grant,
5595 &ett_mac_lte_ulsch_header,
5596 &ett_mac_lte_dlsch_header,
5597 &ett_mac_lte_mch_header,
5598 &ett_mac_lte_sch_subheader,
5599 &ett_mac_lte_mch_subheader,
5603 &ett_mac_lte_activation_deactivation,
5604 &ett_mac_lte_contention_resolution,
5605 &ett_mac_lte_power_headroom,
5606 &ett_mac_lte_extended_power_headroom,
5607 &ett_mac_lte_extended_power_headroom_cell,
5608 &ett_mac_lte_mch_scheduling_info,
5612 static enum_val_t show_info_col_vals[] = {
5613 {"show-phy", "PHY Info", ShowPHYLayer},
5614 {"show-mac", "MAC Info", ShowMACLayer},
5615 {"show-rlc", "RLC Info", ShowRLCLayer},
5619 static enum_val_t lcid_drb_source_vals[] = {
5620 {"from-static-stable", "From static table", FromStaticTable},
5621 {"from-configuration-protocol", "From configuration protocol", FromConfigurationProtocol},
5626 module_t *mac_lte_module;
5628 static uat_field_t lcid_drb_mapping_flds[] = {
5629 UAT_FLD_VS(lcid_drb_mappings, lcid, "lcid", drb_lcid_vals, "The MAC LCID"),
5630 UAT_FLD_DEC(lcid_drb_mappings, drbid,"drb id (1-32)", "Identifier of logical data channel"),
5631 UAT_FLD_VS(lcid_drb_mappings, channel_type, "RLC Channel Type", rlc_channel_type_vals, "The MAC LCID"),
5635 /* Register protocol. */
5636 proto_mac_lte = proto_register_protocol("MAC-LTE", "MAC-LTE", "mac-lte");
5637 proto_register_field_array(proto_mac_lte, hf, array_length(hf));
5638 proto_register_subtree_array(ett, array_length(ett));
5640 /* Allow other dissectors to find this one by name. */
5641 register_dissector("mac-lte", dissect_mac_lte, proto_mac_lte);
5643 /* Register the tap name */
5644 mac_lte_tap = register_tap("mac-lte");
5647 mac_lte_module = prefs_register_protocol(proto_mac_lte, NULL);
5649 /* Obsolete preferences */
5650 prefs_register_obsolete_preference(mac_lte_module, "single_rar");
5651 prefs_register_obsolete_preference(mac_lte_module, "check_reserved_bits");
5652 prefs_register_obsolete_preference(mac_lte_module, "decode_rar_ul_grant");
5653 prefs_register_obsolete_preference(mac_lte_module, "show_rlc_info_column");
5654 prefs_register_obsolete_preference(mac_lte_module, "attempt_to_detect_dl_harq_resend");
5655 prefs_register_obsolete_preference(mac_lte_module, "attempt_to_track_ul_harq_resend");
5657 prefs_register_uint_preference(mac_lte_module, "retx_count_warn",
5658 "Number of Re-Transmits before expert warning triggered",
5659 "Number of Re-Transmits before expert warning triggered",
5660 10, &global_mac_lte_retx_counter_trigger);
5662 prefs_register_bool_preference(mac_lte_module, "attempt_rrc_decode",
5663 "Attempt to decode BCH, PCH and CCCH data using LTE RRC dissector",
5664 "Attempt to decode BCH, PCH and CCCH data using LTE RRC dissector",
5665 &global_mac_lte_attempt_rrc_decode);
5667 prefs_register_bool_preference(mac_lte_module, "attempt_to_dissect_crc_failures",
5668 "Dissect frames that have failed CRC check",
5669 "Attempt to dissect frames that have failed CRC check",
5670 &global_mac_lte_dissect_crc_failures);
5672 prefs_register_bool_preference(mac_lte_module, "heuristic_mac_lte_over_udp",
5673 "Try Heuristic LTE-MAC over UDP framing",
5674 "When enabled, use heuristic dissector to find MAC-LTE frames sent with "
5676 &global_mac_lte_heur);
5678 prefs_register_bool_preference(mac_lte_module, "attempt_to_dissect_srb_sdus",
5679 "Attempt to dissect LCID 1&2 as srb1&2",
5680 "Will call LTE RLC dissector with standard settings as per RRC spec",
5681 &global_mac_lte_attempt_srb_decode);
5683 prefs_register_enum_preference(mac_lte_module, "lcid_to_drb_mapping_source",
5684 "Source of LCID -> drb channel settings",
5685 "Set whether LCID -> drb Table is taken from static table (below) or from "
5686 "info learned from control protocol (e.g. RRC)",
5687 &global_mac_lte_lcid_drb_source, lcid_drb_source_vals, FALSE);
5689 lcid_drb_mappings_uat = uat_new("Static LCID -> drb Table",
5690 sizeof(lcid_drb_mapping_t),
5693 (void*) &lcid_drb_mappings,
5694 &num_lcid_drb_mappings,
5696 "", /* TODO: is this ref to help manual? */
5697 lcid_drb_mapping_copy_cb,
5701 lcid_drb_mapping_flds );
5703 prefs_register_uat_preference(mac_lte_module,
5705 "LCID -> DRB Mappings Table",
5706 "A table that maps from configurable lcids -> RLC logical channels",
5707 lcid_drb_mappings_uat);
5709 prefs_register_uint_preference(mac_lte_module, "bsr_warn_threshold",
5710 "BSR size when warning should be issued (0 - 63)",
5711 "If any BSR report is >= this number, an expert warning will be added",
5712 10, &global_mac_lte_bsr_warn_threshold);
5714 prefs_register_bool_preference(mac_lte_module, "track_sr",
5715 "Track status of SRs within UEs",
5716 "Track status of SRs, providing links between requests, failure indications and grants",
5717 &global_mac_lte_track_sr);
5719 prefs_register_enum_preference(mac_lte_module, "layer_to_show",
5720 "Which layer info to show in Info column",
5721 "Can show PHY, MAC or RLC layer info in Info column",
5722 &global_mac_lte_layer_to_show, show_info_col_vals, FALSE);
5724 register_init_routine(&mac_lte_init_protocol);
5728 /* Set LCID -> RLC channel mappings from signalling protocol (i.e. RRC or similar).
5729 TODO: not using UEID yet - assume all UEs configured identically... */
5730 void set_mac_lte_channel_mapping(guint16 ueid _U_, guint8 lcid,
5731 guint8 srbid, guint8 drbid,
5732 guint8 rlcMode, guint8 um_sn_length,
5735 /* Don't bother setting srb details - we just assume AM */
5740 /* Ignore if LCID is out of range */
5741 if ((lcid < 3) || (lcid > 10)) {
5745 /* Set array entry */
5746 dynamic_lcid_drb_mapping[lcid].valid = TRUE;
5747 dynamic_lcid_drb_mapping[lcid].drbid = drbid;
5748 dynamic_lcid_drb_mapping[lcid].ul_priority = ul_priority;
5752 dynamic_lcid_drb_mapping[lcid].channel_type = rlcAM;
5755 if (um_sn_length == 5) {
5756 dynamic_lcid_drb_mapping[lcid].channel_type = rlcUM5;
5759 dynamic_lcid_drb_mapping[lcid].channel_type = rlcUM10;
5768 /* Return the configured UL priority for the channel */
5769 static guint8 get_mac_lte_channel_priority(guint16 ueid _U_, guint8 lcid,
5772 /* Priority only affects UL */
5773 if (direction == DIRECTION_DOWNLINK) {
5777 /* Won't report value if channel not configured */
5778 if (!dynamic_lcid_drb_mapping[lcid].valid) {
5782 return dynamic_lcid_drb_mapping[lcid].ul_priority;
5786 /* Function to be called from outside this module (e.g. in a plugin) to get per-packet data */
5787 mac_lte_info *get_mac_lte_proto_data(packet_info *pinfo)
5789 return p_get_proto_data(pinfo->fd, proto_mac_lte);
5792 /* Function to be called from outside this module (e.g. in a plugin) to set per-packet data */
5793 void set_mac_lte_proto_data(packet_info *pinfo, mac_lte_info *p_mac_lte_info)
5795 p_add_proto_data(pinfo->fd, proto_mac_lte, p_mac_lte_info);
5798 void proto_reg_handoff_mac_lte(void)
5800 static dissector_handle_t mac_lte_handle;
5801 if (!mac_lte_handle) {
5802 mac_lte_handle = find_dissector("mac-lte");
5804 /* Add as a heuristic UDP dissector */
5805 heur_dissector_add("udp", dissect_mac_lte_heur, proto_mac_lte);