170f39daddf1fc85c8a2306a2f2b088619e35de9
[obnox/wireshark/wip.git] / epan / dissectors / packet-mac-lte.c
1 /* Routines for LTE MAC disassembly
2  *
3  * Martin Mathieson
4  *
5  * $Id$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 # include "config.h"
24 #endif
25
26 #include <string.h>
27
28 #include <epan/packet.h>
29 #include <epan/expert.h>
30 #include <epan/prefs.h>
31 #include <epan/tap.h>
32 #include <epan/uat.h>
33
34 #include "packet-mac-lte.h"
35 #include "packet-rlc-lte.h"
36
37
38 /* Described in:
39  * 3GPP TS 36.321 Evolved Universal Terrestrial Radio Access (E-UTRA)
40  *                Medium Access Control (MAC) protocol specification (Release 8)
41  */
42
43
44 /* TODO:
45    - TDD mode?
46    - add a preference so that padding can be verified against an expected pattern?
47 */
48
49 /* Initialize the protocol and registered fields. */
50 int proto_mac_lte = -1;
51
52 static int mac_lte_tap = -1;
53
54 /* Decoding context */
55 static int hf_mac_lte_context = -1;
56 static int hf_mac_lte_context_radio_type = -1;
57 static int hf_mac_lte_context_direction = -1;
58 static int hf_mac_lte_context_rnti = -1;
59 static int hf_mac_lte_context_rnti_type = -1;
60 static int hf_mac_lte_context_ueid = -1;
61 static int hf_mac_lte_context_subframe_number = -1;
62 static int hf_mac_lte_context_grant_subframe_number = -1;
63 static int hf_mac_lte_context_predefined_frame = -1;
64 static int hf_mac_lte_context_length = -1;
65 static int hf_mac_lte_context_ul_grant_size = -1;
66 static int hf_mac_lte_context_bch_transport_channel = -1;
67 static int hf_mac_lte_context_retx_count = -1;
68 static int hf_mac_lte_context_crc_status = -1;
69 static int hf_mac_lte_context_rapid = -1;
70 static int hf_mac_lte_context_rach_attempt_number = -1;
71
72 /* Extra PHY context */
73 static int hf_mac_lte_context_phy_ul = -1;
74 static int hf_mac_lte_context_phy_ul_modulation_type = -1;
75 static int hf_mac_lte_context_phy_ul_tbs_index = -1;
76 static int hf_mac_lte_context_phy_ul_resource_block_length = -1;
77 static int hf_mac_lte_context_phy_ul_resource_block_start = -1;
78
79 static int hf_mac_lte_context_phy_dl = -1;
80 static int hf_mac_lte_context_phy_dl_dci_format = -1;
81 static int hf_mac_lte_context_phy_dl_resource_allocation_type = -1;
82 static int hf_mac_lte_context_phy_dl_aggregation_level = -1;
83 static int hf_mac_lte_context_phy_dl_mcs_index = -1;
84 static int hf_mac_lte_context_phy_dl_redundancy_version_index = -1;
85 static int hf_mac_lte_context_phy_dl_retx = -1;
86 static int hf_mac_lte_context_phy_dl_resource_block_length = -1;
87 static int hf_mac_lte_context_phy_dl_crc_status = -1;
88
89
90 /* Out-of-band events */
91 static int hf_mac_lte_oob_send_preamble = -1;
92 static int hf_mac_lte_oob_send_sr = -1;
93 static int hf_mac_lte_oob_sr_failure = -1;
94
95 /* MAC SCH header fields */
96 static int hf_mac_lte_ulsch = -1;
97 static int hf_mac_lte_ulsch_header = -1;
98 static int hf_mac_lte_dlsch = -1;
99 static int hf_mac_lte_dlsch_header = -1;
100 static int hf_mac_lte_sch_subheader = -1;
101
102 static int hf_mac_lte_sch_reserved = -1;
103 static int hf_mac_lte_dlsch_lcid = -1;
104 static int hf_mac_lte_ulsch_lcid = -1;
105 static int hf_mac_lte_sch_extended = -1;
106 static int hf_mac_lte_sch_format = -1;
107 static int hf_mac_lte_sch_length = -1;
108
109 static int hf_mac_lte_sch_header_only = -1;
110
111 /* Data */
112 static int hf_mac_lte_sch_sdu = -1;
113 static int hf_mac_lte_bch_pdu = -1;
114 static int hf_mac_lte_pch_pdu = -1;
115 static int hf_mac_lte_predefined_pdu = -1;
116 static int hf_mac_lte_raw_pdu = -1;
117 static int hf_mac_lte_padding_data = -1;
118 static int hf_mac_lte_padding_length = -1;
119
120
121 /* RAR fields */
122 static int hf_mac_lte_rar = -1;
123 static int hf_mac_lte_rar_headers = -1;
124 static int hf_mac_lte_rar_header = -1;
125 static int hf_mac_lte_rar_extension = -1;
126 static int hf_mac_lte_rar_t = -1;
127 static int hf_mac_lte_rar_bi = -1;
128 static int hf_mac_lte_rar_rapid = -1;
129 static int hf_mac_lte_rar_reserved = -1;
130 static int hf_mac_lte_rar_body = -1;
131 static int hf_mac_lte_rar_reserved2 = -1;
132 static int hf_mac_lte_rar_ta = -1;
133 static int hf_mac_lte_rar_ul_grant = -1;
134 static int hf_mac_lte_rar_ul_grant_hopping = -1;
135 static int hf_mac_lte_rar_ul_grant_fsrba = -1;
136 static int hf_mac_lte_rar_ul_grant_tmcs = -1;
137 static int hf_mac_lte_rar_ul_grant_tcsp = -1;
138 static int hf_mac_lte_rar_ul_grant_ul_delay = -1;
139 static int hf_mac_lte_rar_ul_grant_cqi_request = -1;
140 static int hf_mac_lte_rar_temporary_crnti = -1;
141
142 /* Common channel control values */
143 static int hf_mac_lte_control_bsr = -1;
144 static int hf_mac_lte_control_bsr_lcg_id = -1;
145 static int hf_mac_lte_control_short_bsr_buffer_size = -1;
146 static int hf_mac_lte_control_long_bsr_buffer_size_0 = -1;
147 static int hf_mac_lte_control_long_bsr_buffer_size_1 = -1;
148 static int hf_mac_lte_control_long_bsr_buffer_size_2 = -1;
149 static int hf_mac_lte_control_long_bsr_buffer_size_3 = -1;
150 static int hf_mac_lte_control_crnti = -1;
151 static int hf_mac_lte_control_timing_advance = -1;
152 static int hf_mac_lte_control_timing_advance_reserved = -1;
153 static int hf_mac_lte_control_ue_contention_resolution = -1;
154 static int hf_mac_lte_control_ue_contention_resolution_identity = -1;
155 static int hf_mac_lte_control_ue_contention_resolution_msg3 = -1;
156 static int hf_mac_lte_control_ue_contention_resolution_msg3_matched = -1;
157 static int hf_mac_lte_control_ue_contention_resolution_time_since_msg3 = -1;
158 static int hf_mac_lte_control_power_headroom = -1;
159 static int hf_mac_lte_control_power_headroom_reserved = -1;
160 static int hf_mac_lte_control_power_headroom_level = -1;
161 static int hf_mac_lte_control_padding = -1;
162
163 static int hf_mac_lte_suspected_dl_retx_original_frame = -1;
164
165 static int hf_mac_lte_ul_harq_resend_original_frame = -1;
166
167 static int hf_mac_lte_grant_answering_sr = -1;
168 static int hf_mac_lte_failure_answering_sr = -1;
169 static int hf_mac_lte_sr_leading_to_failure = -1;
170 static int hf_mac_lte_sr_leading_to_grant = -1;
171 static int hf_mac_lte_sr_invalid_event = -1;
172 static int hf_mac_lte_sr_time_since_request = -1;
173 static int hf_mac_lte_sr_time_until_answer = -1;
174
175
176 /* Subtrees. */
177 static int ett_mac_lte = -1;
178 static int ett_mac_lte_context = -1;
179 static int ett_mac_lte_phy_context = -1;
180 static int ett_mac_lte_ulsch_header = -1;
181 static int ett_mac_lte_dlsch_header = -1;
182 static int ett_mac_lte_sch_subheader = -1;
183 static int ett_mac_lte_rar_headers = -1;
184 static int ett_mac_lte_rar_header = -1;
185 static int ett_mac_lte_rar_body = -1;
186 static int ett_mac_lte_rar_ul_grant = -1;
187 static int ett_mac_lte_bsr = -1;
188 static int ett_mac_lte_bch = -1;
189 static int ett_mac_lte_pch = -1;
190 static int ett_mac_lte_contention_resolution = -1;
191 static int ett_mac_lte_power_headroom = -1;
192 static int ett_mac_lte_oob = -1;
193
194
195 /* Constants and value strings */
196
197 static const value_string radio_type_vals[] =
198 {
199     { FDD_RADIO,      "FDD"},
200     { TDD_RADIO,      "TDD"},
201     { 0, NULL }
202 };
203
204
205 static const value_string direction_vals[] =
206 {
207     { DIRECTION_UPLINK,      "Uplink"},
208     { DIRECTION_DOWNLINK,    "Downlink"},
209     { 0, NULL }
210 };
211
212
213 static const value_string rnti_type_vals[] =
214 {
215     { NO_RNTI,     "NO-RNTI"},
216     { P_RNTI,      "P-RNTI"},
217     { RA_RNTI,     "RA-RNTI"},
218     { C_RNTI,      "C-RNTI"},
219     { SI_RNTI,     "SI-RNTI"},
220     { SPS_RNTI,    "SPS-RNTI"},
221     { 0, NULL }
222 };
223
224 static const value_string bch_transport_channel_vals[] =
225 {
226     { SI_RNTI,      "DL-SCH"},
227     { NO_RNTI,      "BCH"},
228     { 0, NULL }
229 };
230
231 static const value_string crc_status_vals[] =
232 {
233     { 0,  "Failed"},
234     { 1,  "OK"},
235     { 0, NULL }
236 };
237
238
239 static const value_string dci_format_vals[] =
240 {
241     { 0, "0"},
242     { 1, "1"},
243     { 2, "1A"},
244     { 3, "1B"},
245     { 4, "1C"},
246     { 5, "1D"},
247     { 6, "2"},
248     { 7, "2A"},
249     { 8, "3/3A"},
250     { 0, NULL }
251 };
252
253 static const value_string aggregation_level_vals[] =
254 {
255     { 0, "1"},
256     { 1, "2"},
257     { 2, "4"},
258     { 3, "8"},
259     { 0, NULL }
260 };
261
262 static const value_string modulation_type_vals[] =
263 {
264     { 2, "QPSK"},
265     { 4, "QAM16"},
266     { 6, "QAM64"},
267     { 0, NULL }
268 };
269
270
271 #define UE_CONTENTION_RESOLUTION_IDENTITY_LCID 0x1c
272 #define TIMING_ADVANCE_LCID                    0x1d
273 #define DRX_COMMAND_LCID                       0x1e
274 #define PADDING_LCID                           0x1f
275
276 static const value_string dlsch_lcid_vals[] =
277 {
278     { 0,                                        "CCCH"},
279     { 1,                                        "1"},
280     { 2,                                        "2"},
281     { 3,                                        "3"},
282     { 4,                                        "4"},
283     { 5,                                        "5"},
284     { 6,                                        "6"},
285     { 7,                                        "7"},
286     { 8,                                        "8"},
287     { 9,                                        "9"},
288     { 10,                                       "10"},
289     { UE_CONTENTION_RESOLUTION_IDENTITY_LCID,   "UE Contention Resolution Identity"},
290     { TIMING_ADVANCE_LCID                   ,   "Timing Advance"},
291     { DRX_COMMAND_LCID                      ,   "DRX Command"},
292     { PADDING_LCID                          ,   "Padding" },
293     { 0, NULL }
294 };
295
296 #define POWER_HEADROOM_REPORT_LCID    0x1a
297 #define CRNTI_LCID                    0x1b
298 #define TRUNCATED_BSR_LCID            0x1c
299 #define SHORT_BSR_LCID                0x1d
300 #define LONG_BSR_LCID                 0x1e
301
302 static const value_string ulsch_lcid_vals[] =
303 {
304     { 0,                            "CCCH"},
305     { 1,                            "1"},
306     { 2,                            "2"},
307     { 3,                            "3"},
308     { 4,                            "4"},
309     { 5,                            "5"},
310     { 6,                            "6"},
311     { 7,                            "7"},
312     { 8,                            "8"},
313     { 9,                            "9"},
314     { 10,                           "10"},
315     { POWER_HEADROOM_REPORT_LCID,   "Power Headroom Report"},
316     { CRNTI_LCID,                   "C-RNTI"},
317     { TRUNCATED_BSR_LCID,           "Truncated BSR"},
318     { SHORT_BSR_LCID,               "Short BSR"},
319     { LONG_BSR_LCID,                "Long BSR"},
320     { PADDING_LCID,                 "Padding" },
321     { 0, NULL }
322 };
323
324
325 static const value_string format_vals[] =
326 {
327     { 0,      "Data length is < 128 bytes"},
328     { 1,      "Data length is >= 128 bytes"},
329     { 0, NULL }
330 };
331
332
333 static const value_string rar_type_vals[] =
334 {
335     { 0,      "Backoff Indicator present"},
336     { 1,      "RAPID present"},
337     { 0, NULL }
338 };
339
340
341 static const value_string rar_bi_vals[] =
342 {
343     { 0,      "0"},
344     { 1,      "10"},
345     { 2,      "20"},
346     { 3,      "30"},
347     { 4,      "40"},
348     { 5,      "60"},
349     { 6,      "80"},
350     { 7,      "120"},
351     { 8,      "160"},
352     { 9,      "240"},
353     { 10,     "320"},
354     { 11,     "480"},
355     { 12,     "960"},
356     { 0, NULL }
357 };
358
359
360 static const value_string buffer_size_vals[] =
361 {
362     { 0,      "BS = 0"},
363     { 1,      "0   < BS <= 10"},
364     { 2,      "10  < BS <= 12"},
365     { 3,      "12  < BS <= 14"},
366     { 4,      "14  < BS <= 17"},
367     { 5,      "17  < BS <= 19"},
368     { 6,      "19  < BS <= 22"},
369     { 7,      "22  < BS <= 26"},
370     { 8,      "26  < BS <= 31"},
371     { 9,      "31  < BS <= 36"},
372     { 10,     "36  < BS <= 42"},
373     { 11,     "42  < BS <= 49"},
374     { 12,     "49  < BS <= 57"},
375     { 13,     "47  < BS <= 67"},
376     { 14,     "67  < BS <= 78"},
377     { 15,     "78  < BS <= 91"},
378     { 16,     "91  < BS <= 107"},
379     { 17,     "107 < BS <= 125"},
380     { 18,     "125 < BS <= 146"},
381     { 19,     "146 < BS <= 171"},
382     { 20,     "171 < BS <= 200"},
383     { 21,     "200 < BS <= 234"},
384     { 22,     "234 < BS <= 274"},
385     { 23,     "274 < BS <= 321"},
386     { 24,     "321 < BS <= 376"},
387     { 25,     "376 < BS <= 440"},
388     { 26,     "440 < BS <= 515"},
389     { 27,     "515 < BS <= 603"},
390     { 28,     "603 < BS <= 706"},
391     { 29,     "706 < BS <= 826"},
392     { 30,     "826 < BS <= 967"},
393     { 31,     "967  < BS <= 1132"},
394     { 32,     "1132 < BS <= 1326"},
395     { 33,     "1326 < BS <= 1552"},
396     { 34,     "1552 < BS <= 1817"},
397     { 35,     "1817 < BS <= 2127"},
398     { 36,     "2127 < BS <= 2490"},
399     { 37,     "2490 < BS <= 2915"},
400     { 38,     "2915 < BS <= 3413"},
401     { 39,     "3413 < BS <= 3995"},
402     { 40,     "3995 < BS <= 4677"},
403     { 41,     "4677 < BS <= 5476"},
404     { 42,     "5476 < BS <= 6411"},
405     { 43,     "6411 < BS <= 7505"},
406     { 44,     "7505 < BS <= 8787"},
407     { 45,     "8787 < BS <= 10276"},
408     { 46,     "10287 < BS <= 12043"},
409     { 47,     "12043 < BS <= 14099"},
410     { 48,     "14099 < BS <= 16507"},
411     { 49,     "16507 < BS <= 19325"},
412     { 50,     "19325 < BS <= 22624"},
413     { 51,     "22624 < BS <= 26487"},
414     { 52,     "26487 < BS <= 31009"},
415     { 53,     "31009 < BS <= 36304"},
416     { 54,     "36304 < BS <= 42502"},
417     { 55,     "42502 < BS <= 49759"},
418     { 56,     "49759 < BS <= 58255"},
419     { 57,     "58255 < BS <= 68201"},
420     { 58,     "68201 < BS <= 79846"},
421     { 59,     "79846 < BS <= 93479"},
422     { 60,     "93479 < BS <= 109439"},
423     { 61,     "109439 < BS <= 128125"},
424     { 62,     "128125 < BS <= 150000"},
425     { 63,     "BS > 150000"},
426     { 0, NULL }
427 };
428
429 static const value_string power_headroom_size_vals[] =
430 {
431     { 0,      "-23 <= PH < -22"},
432     { 1,      "-22 <= PH < -21"},
433     { 2,      "-21 <= PH < -20"},
434     { 3,      "-20 <= PH < -19"},
435     { 4,      "-19 <= PH < -18"},
436     { 5,      "-18 <= PH < -17"},
437     { 6,      "-17 <= PH < -16"},
438     { 7,      "-16 <= PH < -15"},
439     { 8,      "-15 <= PH < -14"},
440     { 9,      "-14 <= PH < -13"},
441     { 10,     "-13 <= PH < -12"},
442     { 11,     "-12 <= PH < -11"},
443     { 12,     "-11 <= PH < -10"},
444     { 13,     "-10 <= PH < -9"},
445     { 14,     "-9 <= PH < -8"},
446     { 15,     "-8 <= PH < -7"},
447     { 16,     "-7 <= PH < -6"},
448     { 17,     "-6 <= PH < -5"},
449     { 18,     "-5 <= PH < -4"},
450     { 19,     "-4 <= PH < -3"},
451     { 20,     "-3 <= PH < -2"},
452     { 21,     "-2 <= PH < -1"},
453     { 22,     "-1 <= PH < 0"},
454     { 23,     "0 <= PH < 1"},
455     { 24,     "1 <= PH < 2"},
456     { 25,     "2 <= PH < 3"},
457     { 26,     "3 <= PH < 4"},
458     { 27,     "4 <= PH < 5"},
459     { 28,     "5 <= PH < 6"},
460     { 29,     "6 <= PH < 7"},
461     { 30,     "7 <= PH < 8"},
462     { 31,     "8 <= PH < 9"},
463     { 32,     "9 <= PH < 10"},
464     { 33,     "10 <= PH < 11"},
465     { 34,     "11 <= PH < 12"},
466     { 35,     "12 <= PH < 13"},
467     { 36,     "13 <= PH < 14"},
468     { 37,     "14 <= PH < 15"},
469     { 38,     "15 <= PH < 16"},
470     { 39,     "16 <= PH < 17"},
471     { 40,     "17 <= PH < 18"},
472     { 41,     "18 <= PH < 19"},
473     { 42,     "19 <= PH < 20"},
474     { 43,     "20 <= PH < 21"},
475     { 44,     "21 <= PH < 22"},
476     { 45,     "22 <= PH < 23"},
477     { 46,     "23 <= PH < 24"},
478     { 47,     "24 <= PH < 25"},
479     { 48,     "25 <= PH < 26"},
480     { 49,     "26 <= PH < 27"},
481     { 50,     "27 <= PH < 28"},
482     { 51,     "28 <= PH < 29"},
483     { 52,     "29 <= PH < 30"},
484     { 53,     "30 <= PH < 31"},
485     { 54,     "31 <= PH < 32"},
486     { 55,     "32 <= PH < 33"},
487     { 56,     "33 <= PH < 34"},
488     { 57,     "34 <= PH < 35"},
489     { 58,     "34 <= PH < 36"},
490     { 59,     "36 <= PH < 37"},
491     { 60,     "37 <= PH < 38"},
492     { 61,     "38 <= PH < 39"},
493     { 62,     "39 <= PH < 40"},
494     { 63,     "PH >= 40"},
495     { 0, NULL }
496 };
497
498 static const value_string header_only_vals[] =
499 {
500     { 0,      "MAC PDU Headers and body present"},
501     { 1,      "MAC PDU Headers only"},
502     { 0, NULL }
503 };
504
505 static const value_string predefined_frame_vals[] =
506 {
507     { 0,      "Real MAC PDU present - will dissect"},
508     { 1,      "Predefined frame present - will not dissect"},
509     { 0, NULL }
510 };
511
512
513 /**************************************************************************/
514 /* Preferences state                                                      */
515 /**************************************************************************/
516
517 /* If this PDU has been NACK'd (by HARQ) more than a certain number of times,
518    we trigger an expert warning. */
519 static gint global_mac_lte_retx_counter_trigger = 3;
520
521 /* By default try to decode transparent data (BCH, PCH and CCCH) data using LTE RRC dissector */
522 static gboolean global_mac_lte_attempt_rrc_decode = TRUE;
523
524 /* Whether should attempt to dissect frames failing CRC check */
525 static gboolean global_mac_lte_dissect_crc_failures = FALSE;
526
527 /* Whether should attempt to decode lcid 1&2 SDUs as srb1/2 (i.e. AM RLC) */
528 static gboolean global_mac_lte_attempt_srb_decode = TRUE;
529
530 /* Whether should attempt to track UL HARQ resends */
531 static gboolean global_mac_lte_attempt_ul_harq_resend_track = TRUE;
532
533 /* Threshold for warning in expert info about high BSR values */
534 static gint global_mac_lte_bsr_warn_threshold = 50; /* default is 19325 -> 22624 */
535
536 /* Whether or not to track SRs and related frames */
537 static gboolean global_mac_lte_track_sr = TRUE;
538
539 /* Which layer info to show in the info column */
540 enum layer_to_show {
541     ShowPHYLayer, ShowMACLayer, ShowRLCLayer
542 };
543
544 static gint     global_mac_lte_layer_to_show = (gint)ShowRLCLayer;
545 static guint8   s_number_of_rlc_pdus_shown = 0;
546
547
548 /***********************************************************************/
549 /* How to dissect lcid 3-10 (presume drb logical channels)             */
550
551 static const value_string drb_lcid_vals[] = {
552     { 3,  "LCID 3"},
553     { 4,  "LCID 4"},
554     { 5,  "LCID 5"},
555     { 6,  "LCID 6"},
556     { 7,  "LCID 7"},
557     { 8,  "LCID 8"},
558     { 9,  "LCID 9"},
559     { 10, "LCID 10"},
560     { 0, NULL }
561 };
562
563 typedef enum rlc_channel_type_t {
564     rlcRaw,
565     rlcTM,
566     rlcUM5,
567     rlcUM10,
568     rlcAM
569 } rlc_channel_type_t;
570
571 static const value_string rlc_channel_type_vals[] = {
572     { rlcTM,    "TM"},
573     { rlcUM5 ,  "UM, SN Len=5"},
574     { rlcUM10,  "UM, SN Len=10"},
575     { rlcAM  ,  "AM"},
576     { 0, NULL }
577 };
578
579
580 /* Mapping type */
581 typedef struct drb_mapping_t {
582     guint16 lcid;
583     gint drbid;
584     rlc_channel_type_t channel_type;
585 } lcid_drb_mapping_t;
586
587 /* Mapping entity */
588 static lcid_drb_mapping_t *lcid_drb_mappings = NULL;
589 static guint num_lcid_drb_mappings = 0;
590
591 UAT_VS_DEF(lcid_drb_mappings, lcid, lcid_drb_mapping_t, 3, "LCID 3")
592 UAT_DEC_CB_DEF(lcid_drb_mappings, drbid, lcid_drb_mapping_t)
593 UAT_VS_DEF(lcid_drb_mappings, channel_type, lcid_drb_mapping_t, 2, "AM")
594
595 /* UAT object */
596 static uat_t* lcid_drb_mappings_uat;
597
598 extern int proto_rlc_lte;
599
600 /***************************************************************/
601
602
603
604 /***************************************************************/
605 /* Keeping track of Msg3 bodies so they can be compared with   */
606 /* Contention Resolution bodies.                               */
607
608 typedef struct Msg3Data {
609     guint8   data[6];
610     nstime_t msg3Time;
611     guint32  framenum;
612 } Msg3Data;
613
614
615 /* This table stores (RNTI -> Msg3Data*).  Will be populated when
616    Msg3 frames are first read.  */
617 static GHashTable *mac_lte_msg3_hash = NULL;
618
619 /* Hash table functions for mac_lte_msg3_hash.  Hash is just the (RNTI) key */
620 static gint mac_lte_rnti_hash_equal(gconstpointer v, gconstpointer v2)
621 {
622     return (v == v2);
623 }
624
625 static guint mac_lte_rnti_hash_func(gconstpointer v)
626 {
627     return GPOINTER_TO_UINT(v);
628 }
629
630
631
632 typedef enum ContentionResolutionStatus {
633     NoMsg3,
634     Msg3Match,
635     Msg3NoMatch
636 } ContentionResolutionStatus;
637
638 typedef struct ContentionResolutionResult {
639     ContentionResolutionStatus status;
640     guint                      msg3FrameNum;
641     guint                      msSinceMsg3;
642 } ContentionResolutionResult;
643
644
645 /* This table stores (CRFrameNum -> CRResult).  It is assigned during the first
646    pass and used thereafter */
647 static GHashTable *mac_lte_cr_result_hash = NULL;
648
649 /* Hash table functions for mac_lte_cr_result_hash.  Hash is just the (framenum) key */
650 static gint mac_lte_framenum_hash_equal(gconstpointer v, gconstpointer v2)
651 {
652     return (v == v2);
653 }
654
655 static guint mac_lte_framenum_hash_func(gconstpointer v)
656 {
657     return GPOINTER_TO_UINT(v);
658 }
659
660 /**************************************************************************/
661
662
663
664 /****************************************************************/
665 /* Keeping track of last DL frames per C-RNTI so can guess when */
666 /* there has been a HARQ retransmission                         */
667
668 /* Could be bigger, but more than enough to flag suspected resends */
669 #define MAX_EXPECTED_PDU_LENGTH 2048
670
671 typedef struct LastFrameData {
672     gboolean inUse;
673     guint32  framenum;
674     guint    subframeNumber;
675     nstime_t received_time;
676     gint     length;
677     guint8   data[MAX_EXPECTED_PDU_LENGTH];
678 } LastFrameData;
679
680 typedef struct LastFrameDataAllSubframes {
681     LastFrameData subframe[10];
682 } LastFrameDataAllSubframes;
683
684
685 /* This table stores (RNTI -> LastFrameDataAllSubframes*).  Will be populated when
686    DL frames are first read.  */
687 static GHashTable *mac_lte_dl_harq_hash = NULL;
688
689 typedef struct DLHARQResult {
690     guint       previousFrameNum;
691 } DLHARQResult;
692
693
694 /* This table stores (FrameNumber -> DLHARQResult).  It is assigned during the first
695    pass and used thereafter */
696 static GHashTable *mac_lte_dl_harq_result_hash = NULL;
697
698 /**************************************************************************/
699
700
701 /*****************************************************************/
702 /* Keeping track of last UL frames per C-RNTI so can verify when */
703 /* told that a frame is a retx                                   */
704
705 /* This table stores (RNTI -> LastFrameDataAllSubframes*).  Will be populated when
706    UL frames are first read.  */
707 static GHashTable *mac_lte_ul_harq_hash = NULL;
708
709 typedef struct ULHARQResult {
710     guint       previousFrameNum;
711 } ULHARQResult;
712
713
714 /* This table stores (CRFrameNum -> ULHARQResult).  It is assigned during the first
715    pass and used thereafter */
716 static GHashTable *mac_lte_ul_harq_result_hash = NULL;
717
718 /**************************************************************************/
719
720
721 /**************************************************************************/
722 /* Tracking of Scheduling Requests (SRs).                                 */
723 /* Keep track of:                                                         */
724 /* - last grant before SR                                                 */
725 /* - SR failures following request                                        */
726 /* - grant following SR                                                   */
727
728 typedef enum SREvent {
729     SR_Grant,
730     SR_Request,
731     SR_Failure
732 } SREvent;
733
734 static const value_string sr_event_vals[] =
735 {
736     { SR_Grant,        "Grant"},
737     { SR_Request,      "SR Request"},
738     { SR_Failure,      "SR Failure"},
739     { 0,               NULL}
740 };
741
742
743 typedef enum SRStatus {
744     None,
745     SR_Outstanding,
746     SR_Failed
747 } SRStatus;
748
749 static const value_string sr_status_vals[] =
750 {
751     { None,                "Receiving grants"},
752     { SR_Outstanding,      "SR Request outstanding"},
753     { SR_Failed,           "SR has Failed"},
754     { 0,                   NULL}
755 };
756
757
758 typedef struct SRState {
759     SRStatus status;
760     guint32  lastSRFramenum;
761     guint32  lastGrantFramenum;
762     nstime_t requestTime;
763 } SRState;
764
765
766 /* This table keeps track of the SR state for each UE.
767    (RNTI -> SRState) */
768 static GHashTable *mac_lte_ue_sr_state = NULL;
769
770
771 typedef enum SRResultType {
772     GrantAnsweringSR,
773     FailureAnsweringSR,
774     SRLeadingToGrant,
775     SRLeadingToFailure,
776     InvalidSREvent
777 } SRResultType;
778
779
780 typedef struct SRResult {
781     SRResultType type;
782     guint32      frameNum;
783     guint32      timeDifference;
784
785     /* These 2 are only used with InvalidSREvent */
786     SRStatus     status;
787     SREvent      event;
788 } SRResult;
789
790 /* Entries in this table are created during the first pass
791    It maps (SRFrameNum -> SRResult) */
792 static GHashTable *mac_lte_sr_request_hash = NULL;
793
794
795 /**************************************************************************/
796
797
798
799 /* Forward declarations */
800 void proto_reg_handoff_mac_lte(void);
801 void dissect_mac_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
802
803
804 /* Heuristic dissection */
805 static gboolean global_mac_lte_heur = FALSE;
806
807 /* Heuristic dissector looks for supported framing protocol (see wiki page)  */
808 static gboolean dissect_mac_lte_heur(tvbuff_t *tvb, packet_info *pinfo,
809                                      proto_tree *tree)
810 {
811     gint                 offset = 0;
812     struct mac_lte_info  *p_mac_lte_info;
813     tvbuff_t             *mac_tvb;
814     guint8               tag = 0;
815     gboolean             infoAlreadySet = FALSE;
816
817     /* This is a heuristic dissector, which means we get all the UDP
818      * traffic not sent to a known dissector and not claimed by
819      * a heuristic dissector called before us!
820      */
821
822     if (!global_mac_lte_heur) {
823         return FALSE;
824     }
825
826     /* If redissecting, use previous info struct (if available) */
827     p_mac_lte_info = p_get_proto_data(pinfo->fd, proto_mac_lte);
828     if (p_mac_lte_info == NULL) {
829         /* Allocate new info struct for this frame */
830         p_mac_lte_info = se_alloc0(sizeof(struct mac_lte_info));
831         infoAlreadySet = FALSE;
832     }
833     else {
834         infoAlreadySet = TRUE;
835     }
836
837     /* Do this again on re-dissection to re-discover offset of actual PDU */
838     
839     /* Needs to be at least as long as:
840        - the signature string
841        - fixed header bytes
842        - tag for data
843        - at least one byte of MAC PDU payload */
844     if ((size_t)tvb_length_remaining(tvb, offset) < (strlen(MAC_LTE_START_STRING)+3+2)) {
845         return FALSE;
846     }
847
848     /* OK, compare with signature string */
849     if (tvb_strneql(tvb, offset, MAC_LTE_START_STRING, (gint)strlen(MAC_LTE_START_STRING)) != 0) {
850         return FALSE;
851     }
852     offset += (gint)strlen(MAC_LTE_START_STRING);
853
854     /* Read fixed fields */
855     p_mac_lte_info->radioType = tvb_get_guint8(tvb, offset++);
856     p_mac_lte_info->direction = tvb_get_guint8(tvb, offset++);
857
858     /* TODO: add this info to framing protocol */
859     if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
860         p_mac_lte_info->detailed_phy_info.ul_info.present = FALSE;
861     }
862     else {
863         p_mac_lte_info->detailed_phy_info.dl_info.present = FALSE;
864     }
865         
866     p_mac_lte_info->rntiType = tvb_get_guint8(tvb, offset++);
867
868     /* Read optional fields */
869     while (tag != MAC_LTE_PAYLOAD_TAG) {
870         /* Process next tag */
871         tag = tvb_get_guint8(tvb, offset++);
872         switch (tag) {
873             case MAC_LTE_RNTI_TAG:
874                 p_mac_lte_info->rnti = tvb_get_ntohs(tvb, offset);
875                 offset += 2;
876                 break;
877             case MAC_LTE_UEID_TAG:
878                 p_mac_lte_info->ueid = tvb_get_ntohs(tvb, offset);
879                 offset += 2;
880                 break;
881             case MAC_LTE_SUBFRAME_TAG:
882                 p_mac_lte_info->subframeNumber = tvb_get_ntohs(tvb, offset);
883                 offset += 2;
884                 break;
885             case MAC_LTE_PREDFINED_DATA_TAG:
886                 p_mac_lte_info->isPredefinedData = tvb_get_guint8(tvb, offset);
887                 offset++;
888                 break;
889             case MAC_LTE_RETX_TAG:
890                 p_mac_lte_info->reTxCount = tvb_get_guint8(tvb, offset);
891                 offset++;
892                 break;
893             case MAC_LTE_CRC_STATUS_TAG:
894                 p_mac_lte_info->crcStatusValid = TRUE;
895                 p_mac_lte_info->detailed_phy_info.dl_info.crc_status = tvb_get_guint8(tvb, offset);
896                 offset++;
897                 break;
898
899             case MAC_LTE_PAYLOAD_TAG:
900                 /* Have reached data, so set payload length and get out of loop */
901                 p_mac_lte_info->length= tvb_length_remaining(tvb, offset);
902                 continue;
903
904             default:
905                 /* It must be a recognised tag */
906                 return FALSE;
907         }
908     }
909
910     if (!infoAlreadySet) {
911         /* Store info in packet */
912         p_add_proto_data(pinfo->fd, proto_mac_lte, p_mac_lte_info);
913     }
914
915     /**************************************/
916     /* OK, now dissect as MAC LTE         */
917
918     /* Create tvb that starts at actual MAC PDU */
919     mac_tvb = tvb_new_subset(tvb, offset, -1, tvb_reported_length(tvb)-offset);
920     dissect_mac_lte(mac_tvb, pinfo, tree);
921     return TRUE;
922 }
923
924
925 /* Write the given formatted text to:
926    - the info column (if pinfo != NULL)
927    - 1 or 2 other labels (optional)
928 */
929 static void write_pdu_label_and_info(proto_item *ti1, proto_item *ti2,
930                                      packet_info *pinfo, const char *format, ...)
931 {
932     #define MAX_INFO_BUFFER 256
933     static char info_buffer[MAX_INFO_BUFFER];
934
935     va_list ap;
936
937     va_start(ap, format);
938     g_vsnprintf(info_buffer, MAX_INFO_BUFFER, format, ap);
939     va_end(ap);
940
941     /* Add to indicated places */
942     if (pinfo != NULL) {
943         col_append_str(pinfo->cinfo, COL_INFO, info_buffer);
944     }
945     if (ti1 != NULL) {
946         proto_item_append_text(ti1, "%s", info_buffer);
947     }
948     if (ti2 != NULL) {
949         proto_item_append_text(ti2, "%s", info_buffer);
950     }
951 }
952
953 /* Show extra PHY parameters (if present) */
954 static void show_extra_phy_parameters(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree,
955                                       struct mac_lte_info *p_mac_lte_info)
956 {
957     proto_item *phy_ti;
958     proto_tree *phy_tree;
959     proto_item *ti;
960
961     if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
962         if (p_mac_lte_info->detailed_phy_info.ul_info.present) {
963
964             /* Create root */
965             phy_ti = proto_tree_add_string_format(tree, hf_mac_lte_context_phy_ul,
966                                                   tvb, 0, 0, "", "UL PHY Context");
967             phy_tree = proto_item_add_subtree(phy_ti, ett_mac_lte_phy_context);
968             PROTO_ITEM_SET_GENERATED(phy_ti);
969
970             /* Add items */
971             ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_modulation_type,
972                                      tvb, 0, 0,
973                                      p_mac_lte_info->detailed_phy_info.ul_info.modulation_type);
974             PROTO_ITEM_SET_GENERATED(ti);
975  
976             ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_tbs_index,
977                                      tvb, 0, 0,
978                                      p_mac_lte_info->detailed_phy_info.ul_info.tbs_index);
979             PROTO_ITEM_SET_GENERATED(ti);
980
981             ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_resource_block_length,
982                                      tvb, 0, 0,
983                                      p_mac_lte_info->detailed_phy_info.ul_info.resource_block_length);
984             PROTO_ITEM_SET_GENERATED(ti);
985
986             ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_ul_resource_block_start,
987                                      tvb, 0, 0,
988                                      p_mac_lte_info->detailed_phy_info.ul_info.resource_block_start);
989             PROTO_ITEM_SET_GENERATED(ti);
990
991             proto_item_append_text(phy_ti, " (");
992
993             write_pdu_label_and_info(phy_ti, NULL,
994                                      (global_mac_lte_layer_to_show == ShowPHYLayer) ? pinfo : NULL,
995                                      "%s Tbs_Index=%u RB_len=%u RB_start=%u",
996                                      val_to_str_const(p_mac_lte_info->detailed_phy_info.ul_info.modulation_type,
997                                                       modulation_type_vals, "Unknown"),
998                                      p_mac_lte_info->detailed_phy_info.ul_info.tbs_index,
999                                      p_mac_lte_info->detailed_phy_info.ul_info.resource_block_length,
1000                                      p_mac_lte_info->detailed_phy_info.ul_info.resource_block_start);
1001
1002             proto_item_append_text(phy_ti, ")");
1003
1004             /* Don't want columns to be replaced now */
1005             if (global_mac_lte_layer_to_show == ShowPHYLayer) {
1006                 col_set_writable(pinfo->cinfo, FALSE);
1007             }
1008         }
1009     }
1010     else {
1011         if (p_mac_lte_info->detailed_phy_info.dl_info.present) {
1012
1013             /* Create root */
1014             phy_ti = proto_tree_add_string_format(tree, hf_mac_lte_context_phy_dl,
1015                                                   tvb, 0, 0, "", "DL PHY Context");
1016             phy_tree = proto_item_add_subtree(phy_ti, ett_mac_lte_phy_context);
1017             PROTO_ITEM_SET_GENERATED(phy_ti);
1018
1019             /* Add items */
1020             ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_dci_format,
1021                                      tvb, 0, 0,
1022                                      p_mac_lte_info->detailed_phy_info.dl_info.dci_format);
1023             PROTO_ITEM_SET_GENERATED(ti);
1024
1025             ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_resource_allocation_type,
1026                                      tvb, 0, 0,
1027                                      p_mac_lte_info->detailed_phy_info.dl_info.resource_allocation_type);
1028             PROTO_ITEM_SET_GENERATED(ti);
1029
1030             ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_aggregation_level,
1031                                      tvb, 0, 0,
1032                                      p_mac_lte_info->detailed_phy_info.dl_info.aggregation_level);
1033             PROTO_ITEM_SET_GENERATED(ti);
1034
1035             ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_mcs_index,
1036                                      tvb, 0, 0,
1037                                      p_mac_lte_info->detailed_phy_info.dl_info.mcs_index);
1038             PROTO_ITEM_SET_GENERATED(ti);
1039
1040             ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_redundancy_version_index,
1041                                      tvb, 0, 0,
1042                                      p_mac_lte_info->detailed_phy_info.dl_info.redundancy_version_index);
1043             PROTO_ITEM_SET_GENERATED(ti);
1044
1045             ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_resource_block_length,
1046                                      tvb, 0, 0,
1047                                      p_mac_lte_info->detailed_phy_info.dl_info.resource_block_length);
1048             PROTO_ITEM_SET_GENERATED(ti);
1049
1050             ti = proto_tree_add_uint(phy_tree, hf_mac_lte_context_phy_dl_crc_status,
1051                                      tvb, 0, 0,
1052                                      p_mac_lte_info->detailed_phy_info.dl_info.crc_status);
1053             PROTO_ITEM_SET_GENERATED(ti);
1054
1055             proto_item_append_text(phy_ti, " (");
1056
1057             write_pdu_label_and_info(phy_ti, NULL,
1058                                      (global_mac_lte_layer_to_show == ShowPHYLayer) ? pinfo : NULL,
1059                                      "DCI_Format=%s Res_Alloc=%u Aggr_Level=%s MCS=%u RV=%u "
1060                                      "Res_Block_len=%u CRC_status=%s",
1061                                      val_to_str_const(p_mac_lte_info->detailed_phy_info.dl_info.dci_format,
1062                                                       dci_format_vals, "Unknown"),
1063                                      p_mac_lte_info->detailed_phy_info.dl_info.resource_allocation_type,
1064                                      val_to_str_const(p_mac_lte_info->detailed_phy_info.dl_info.aggregation_level,
1065                                                       aggregation_level_vals, "Unknown"),
1066                                      p_mac_lte_info->detailed_phy_info.dl_info.mcs_index,
1067                                      p_mac_lte_info->detailed_phy_info.dl_info.redundancy_version_index,
1068                                      p_mac_lte_info->detailed_phy_info.dl_info.resource_block_length,
1069                                      val_to_str_const(p_mac_lte_info->detailed_phy_info.dl_info.crc_status,
1070                                                       crc_status_vals, "Unknown"));
1071             proto_item_append_text(phy_ti, ")");
1072
1073             /* Don't want columns to be replaced now */
1074             if (global_mac_lte_layer_to_show == ShowPHYLayer) {
1075                 col_set_writable(pinfo->cinfo, FALSE);
1076             }
1077         }
1078     }   
1079 }
1080
1081
1082 /* Dissect a single Random Access Reponse body */
1083 static gint dissect_rar_entry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1084                               proto_item *pdu_ti,
1085                               gint offset, guint8 rapid)
1086 {
1087     guint8 reserved;
1088     guint start_body_offset = offset;
1089     proto_item *ti;
1090     proto_item *rar_body_ti;
1091     proto_tree *rar_body_tree;
1092     proto_tree *ul_grant_tree;
1093     proto_item *ul_grant_ti;
1094     guint16 timing_advance;
1095     guint32 ul_grant;
1096     guint16 temp_crnti;
1097
1098     /* Create tree for this Body */
1099     rar_body_ti = proto_tree_add_item(tree,
1100                                       hf_mac_lte_rar_body,
1101                                       tvb, offset, 0, FALSE);
1102     rar_body_tree = proto_item_add_subtree(rar_body_ti, ett_mac_lte_rar_body);
1103
1104     /* Dissect an RAR entry */
1105
1106     /* Check reserved bit */
1107     reserved = (tvb_get_guint8(tvb, offset) & 0x80) >> 7;
1108     ti = proto_tree_add_item(rar_body_tree, hf_mac_lte_rar_reserved2, tvb, offset, 1, FALSE);
1109     if (reserved != 0) {
1110             expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
1111                       "RAR body Reserved bit not zero (found 0x%x)", reserved);
1112     }
1113
1114     /* Timing Advance */
1115     timing_advance = (tvb_get_ntohs(tvb, offset) & 0x7ff0) >> 4;
1116     ti = proto_tree_add_item(rar_body_tree, hf_mac_lte_rar_ta, tvb, offset, 2, FALSE);
1117     if (timing_advance != 0) {
1118         expert_add_info_format(pinfo, ti, PI_SEQUENCE, (timing_advance <= 31) ? PI_NOTE : PI_WARN,
1119                                "RAR Timing advance not zero (%u)", timing_advance);
1120     }
1121     offset++;
1122
1123     /* UL Grant */
1124     ul_grant = (tvb_get_ntohl(tvb, offset) & 0x0fffff00) >> 8;
1125     ul_grant_ti = proto_tree_add_item(rar_body_tree, hf_mac_lte_rar_ul_grant, tvb, offset, 3, FALSE);
1126
1127     /* Break these 20 bits down as described in 36.213, section 6.2 */
1128     /* Create subtree for UL grant break-down */
1129     ul_grant_tree = proto_item_add_subtree(ul_grant_ti, ett_mac_lte_rar_ul_grant);
1130
1131     /* Hopping flag (1 bit) */
1132     proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_hopping,
1133                         tvb, offset, 1, FALSE);
1134
1135     /* Fixed sized resource block assignment (10 bits) */
1136     proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_fsrba,
1137                         tvb, offset, 2, FALSE);
1138
1139     /* Truncated Modulation and coding scheme (4 bits) */
1140     proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_tmcs,
1141                         tvb, offset+1, 2, FALSE);
1142
1143     /* TPC command for scheduled PUSCH (3 bits) */
1144     proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_tcsp,
1145                         tvb, offset+2, 1, FALSE);
1146
1147     /* UL delay (1 bit) */
1148     proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_ul_delay,
1149                         tvb, offset+2, 1, FALSE);
1150
1151     /* CQI request (1 bit) */
1152     proto_tree_add_item(ul_grant_tree, hf_mac_lte_rar_ul_grant_cqi_request,
1153                         tvb, offset+2, 1, FALSE);
1154
1155     offset += 3;
1156
1157     /* Temporary C-RNTI */
1158     temp_crnti = tvb_get_ntohs(tvb, offset);
1159     proto_tree_add_item(rar_body_tree, hf_mac_lte_rar_temporary_crnti, tvb, offset, 2, FALSE);
1160     offset += 2;
1161
1162     write_pdu_label_and_info(pdu_ti, rar_body_ti, pinfo,
1163                              "(RAPID=%u: TA=%u, UL-Grant=%u, Temp C-RNTI=%u) ",
1164                              rapid, timing_advance, ul_grant, temp_crnti);
1165
1166     proto_item_set_len(rar_body_ti, offset-start_body_offset);
1167
1168     return offset;
1169 }
1170
1171
1172 /* Dissect Random Access Reponse (RAR) PDU */
1173 static void dissect_rar(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *pdu_ti,
1174                         gint offset, mac_lte_info *p_mac_lte_info, mac_lte_tap_info *tap_info)
1175 {
1176     gint     number_of_rars = 0;   /* No of RAR bodies expected following headers */
1177     guint8   rapids[64];
1178     gboolean backoff_indicator_seen = FALSE;
1179     guint8   backoff_indicator = 0;
1180     guint8   extension;
1181     gint     n;
1182     proto_tree *rar_headers_tree;
1183     proto_item *ti;
1184     proto_item *rar_headers_ti;
1185     int        start_headers_offset = offset;
1186
1187     write_pdu_label_and_info(pdu_ti, NULL, pinfo,
1188                              "RAR (RA-RNTI=%u, SF=%u) ",
1189                              p_mac_lte_info->rnti, p_mac_lte_info->subframeNumber);
1190
1191     /* Create hidden 'virtual root' so can filter on mac-lte.rar */
1192     ti = proto_tree_add_item(tree, hf_mac_lte_rar, tvb, offset, -1, FALSE);
1193     PROTO_ITEM_SET_HIDDEN(ti);
1194
1195     /* Create headers tree */
1196     rar_headers_ti = proto_tree_add_item(tree,
1197                                          hf_mac_lte_rar_headers,
1198                                          tvb, offset, 0, FALSE);
1199     rar_headers_tree = proto_item_add_subtree(rar_headers_ti, ett_mac_lte_rar_headers);
1200
1201
1202     /***************************/
1203     /* Read the header entries */
1204     do {
1205         int start_header_offset = offset;
1206         proto_tree *rar_header_tree;
1207         proto_item *rar_header_ti;
1208         guint8 type_value;
1209         guint8 first_byte = tvb_get_guint8(tvb, offset);
1210
1211         /* Create tree for this header */
1212         rar_header_ti = proto_tree_add_item(rar_headers_tree,
1213                                             hf_mac_lte_rar_header,
1214                                             tvb, offset, 0, FALSE);
1215         rar_header_tree = proto_item_add_subtree(rar_header_ti, ett_mac_lte_rar_header);
1216
1217         /* Extension */
1218         extension = (first_byte & 0x80) >> 7;
1219         proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_extension, tvb, offset, 1, FALSE);
1220
1221         /* Type */
1222         type_value = (first_byte & 0x40) >> 6;
1223         proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_t, tvb, offset, 1, FALSE);
1224
1225         if (type_value == 0) {
1226             /* Backoff Indicator (BI) case */
1227
1228             guint8 reserved;
1229             proto_item *tii;
1230             proto_item *bi_ti;
1231
1232             /* 2 Reserved bits */
1233             reserved = (tvb_get_guint8(tvb, offset) & 0x30) >> 4;
1234             tii = proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_reserved, tvb, offset, 1, FALSE);
1235             if (reserved != 0) {
1236                 expert_add_info_format(pinfo, tii, PI_MALFORMED, PI_ERROR,
1237                                        "RAR header Reserved bits not zero (found 0x%x)", reserved);
1238             }
1239
1240             /* Backoff Indicator */
1241             backoff_indicator = tvb_get_guint8(tvb, offset) & 0x0f;
1242             bi_ti = proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_bi, tvb, offset, 1, FALSE);
1243
1244             /* As of March 2009 spec, it must be first, and may only appear once */
1245             if (backoff_indicator_seen) {
1246                 expert_add_info_format(pinfo, bi_ti, PI_MALFORMED, PI_ERROR,
1247                                        "MAC RAR PDU has > 1 Backoff Indicator subheader present");
1248             }
1249             backoff_indicator_seen = TRUE;
1250
1251             write_pdu_label_and_info(pdu_ti, rar_header_ti, pinfo,
1252                                      "(Backoff Indicator=%sms)",
1253                                      val_to_str_const(backoff_indicator, rar_bi_vals, "Illegal-value "));
1254
1255             /* If present, it must be the first subheader */
1256             if (number_of_rars > 0) {
1257                 expert_add_info_format(pinfo, bi_ti, PI_MALFORMED, PI_WARN,
1258                                        "Backoff Indicator must appear as first subheader");
1259             }
1260
1261         }
1262         else {
1263             /* RAPID case */
1264             /* TODO: complain if the same RAPID appears twice in same frame? */
1265             rapids[number_of_rars] = tvb_get_guint8(tvb, offset) & 0x3f;
1266             proto_tree_add_item(rar_header_tree, hf_mac_lte_rar_rapid, tvb, offset, 1, FALSE);
1267
1268             proto_item_append_text(rar_header_ti, "(RAPID=%u)", rapids[number_of_rars]);
1269
1270             number_of_rars++;
1271         }
1272
1273         offset++;
1274
1275         /* Finalise length of header tree selection */
1276         proto_item_set_len(rar_header_ti, offset - start_header_offset);
1277
1278     } while (extension);
1279
1280     /* Append summary to headers root */
1281     proto_item_append_text(rar_headers_ti, " (%u RARs", number_of_rars);
1282     if (backoff_indicator_seen) {
1283         proto_item_append_text(rar_headers_ti, ", BI=%sms)",
1284                                val_to_str_const(backoff_indicator, rar_bi_vals, "Illegal-value "));
1285     }
1286     else {
1287         proto_item_append_text(rar_headers_ti, ")");
1288     }
1289
1290     /* Set length for headers root */
1291     proto_item_set_len(rar_headers_ti, offset-start_headers_offset);
1292
1293
1294     /***************************/
1295     /* Read any indicated RARs */
1296     for (n=0; n < number_of_rars; n++) {
1297         offset = dissect_rar_entry(tvb, pinfo, tree, pdu_ti, offset, rapids[n]);
1298     }
1299
1300     /* Update TAP info */
1301     tap_info->number_of_rars += number_of_rars;
1302
1303     /* Warn if we don't seem to have reached the end of the frame yet */
1304     if (tvb_length_remaining(tvb, offset) != 0) {
1305            expert_add_info_format(pinfo, pdu_ti, PI_MALFORMED, PI_ERROR,
1306                                   "%u bytes remaining after RAR PDU dissected",
1307                                   tvb_length_remaining(tvb, offset));
1308     }
1309 }
1310
1311
1312 /* Dissect BCH PDU */
1313 static void dissect_bch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1314                         proto_item *pdu_ti,
1315                         int offset, mac_lte_info *p_mac_lte_info)
1316 {
1317     proto_item *ti;
1318
1319     write_pdu_label_and_info(pdu_ti, NULL, pinfo,
1320                              "BCH PDU (%u bytes, on %s transport)  ",
1321                              tvb_length_remaining(tvb, offset),
1322                              val_to_str_const(p_mac_lte_info->rntiType,
1323                                               bch_transport_channel_vals,
1324                                               "Unknown"));
1325
1326     /* Show which transport layer it came in on (inferred from RNTI type) */
1327     ti = proto_tree_add_uint(tree, hf_mac_lte_context_bch_transport_channel,
1328                              tvb, offset, 0, p_mac_lte_info->rntiType);
1329     PROTO_ITEM_SET_GENERATED(ti);
1330
1331     /****************************************/
1332     /* Whole frame is BCH data              */
1333
1334     /* Raw data */
1335     ti = proto_tree_add_item(tree, hf_mac_lte_bch_pdu,
1336                              tvb, offset, -1, FALSE);
1337
1338     if (global_mac_lte_attempt_rrc_decode) {
1339         /* Attempt to decode payload using LTE RRC dissector */
1340         tvbuff_t *rrc_tvb = tvb_new_subset(tvb, offset, -1, tvb_length_remaining(tvb, offset));
1341
1342         /* Get appropriate dissector handle */
1343         dissector_handle_t protocol_handle = 0;
1344         if (p_mac_lte_info->rntiType == SI_RNTI) {
1345             protocol_handle = find_dissector("lte-rrc.bcch.dl.sch");
1346         }
1347         else {
1348             protocol_handle = find_dissector("lte-rrc.bcch.bch");
1349         }
1350
1351         /* Hide raw view of bytes */
1352         PROTO_ITEM_SET_HIDDEN(ti);
1353
1354         /* Call it (catch exceptions so that stats will be updated) */
1355         /* TODO: couldn't avoid warnings for 'ti' by using volatile
1356                  (with gcc 3.4.6)                                   */
1357 /*        TRY {                                                         */
1358             call_dissector_only(protocol_handle, rrc_tvb, pinfo, tree);
1359 /*        }                                                             */
1360 /*        CATCH_ALL {                                                   */
1361 /*        }                                                             */
1362 /*        ENDTRY                                                        */
1363     }
1364
1365     /* Check that this *is* downlink! */
1366     if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
1367         expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
1368                                "BCH data should not be received in Uplink!");
1369     }
1370 }
1371
1372
1373 /* Dissect PCH PDU */
1374 static void dissect_pch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1375                         proto_item *pdu_ti, int offset, guint8 direction)
1376 {
1377     proto_item *ti;
1378
1379     write_pdu_label_and_info(pdu_ti, NULL, pinfo,
1380                              "PCH PDU (%u bytes)  ",
1381                              tvb_length_remaining(tvb, offset));
1382
1383     /****************************************/
1384     /* Whole frame is PCH data              */
1385
1386     /* Always show as raw data */
1387     ti = proto_tree_add_item(tree, hf_mac_lte_pch_pdu,
1388                              tvb, offset, -1, FALSE);
1389
1390     if (global_mac_lte_attempt_rrc_decode) {
1391
1392         /* Attempt to decode payload using LTE RRC dissector */
1393         tvbuff_t *rrc_tvb = tvb_new_subset(tvb, offset, -1, tvb_length_remaining(tvb, offset));
1394
1395         /* Get appropriate dissector handle */
1396         dissector_handle_t protocol_handle = find_dissector("lte-rrc.pcch");
1397
1398         /* Hide raw view of bytes */
1399         PROTO_ITEM_SET_HIDDEN(ti);
1400
1401         /* Call it (catch exceptions so that stats will be updated) */
1402         TRY {
1403             call_dissector_only(protocol_handle, rrc_tvb, pinfo, tree);
1404         }
1405         CATCH_ALL {
1406         }
1407         ENDTRY
1408     }
1409
1410     /* Check that this *is* downlink! */
1411     if (direction == DIRECTION_UPLINK) {
1412         expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
1413                                "PCH data should not be received in Uplink!");
1414     }
1415 }
1416
1417
1418 /* Does this header entry correspond to a fixed-sized control element? */
1419 static int is_fixed_sized_control_element(guint8 lcid, guint8 direction)
1420 {
1421     if (direction == DIRECTION_UPLINK) {
1422         /* Uplink */
1423         switch (lcid) {
1424             case POWER_HEADROOM_REPORT_LCID:
1425             case CRNTI_LCID:
1426             case TRUNCATED_BSR_LCID:
1427             case SHORT_BSR_LCID:
1428             case LONG_BSR_LCID:
1429                 return TRUE;
1430
1431             default:
1432                 return FALSE;
1433         }
1434     }
1435     else {
1436         /* Assume Downlink */
1437         switch (lcid) {
1438             case UE_CONTENTION_RESOLUTION_IDENTITY_LCID:
1439             case TIMING_ADVANCE_LCID:
1440             case DRX_COMMAND_LCID:
1441                 return TRUE;
1442
1443             default:
1444                 return FALSE;
1445         }
1446     }
1447 }
1448
1449
1450 /* Is this a BSR report header? */
1451 static int is_bsr_lcid(guint8 lcid)
1452 {
1453     return ((lcid == TRUNCATED_BSR_LCID) ||
1454             (lcid == SHORT_BSR_LCID) ||
1455             (lcid == LONG_BSR_LCID));
1456 }
1457
1458
1459 /* Helper function to call RLC dissector for SDUs (where channel params are known) */
1460 static void call_rlc_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1461                                proto_item *pdu_ti,
1462                                int offset, guint16 data_length,
1463                                guint8 mode, guint8 direction, guint16 ueid,
1464                                guint16 channelType, guint16 channelId,
1465                                guint8 UMSequenceNumberLength)
1466 {
1467     tvbuff_t *srb_tvb = tvb_new_subset(tvb, offset, data_length, data_length);
1468     struct rlc_lte_info *p_rlc_lte_info;
1469
1470     /* Get RLC dissector handle */
1471     volatile dissector_handle_t protocol_handle = find_dissector("rlc-lte");
1472
1473     /* Resuse or create RLC info */
1474     p_rlc_lte_info = p_get_proto_data(pinfo->fd, proto_rlc_lte);
1475     if (p_rlc_lte_info == NULL) {
1476         p_rlc_lte_info = se_alloc0(sizeof(struct rlc_lte_info));
1477     }
1478
1479     /* Fill in struct details for srb channels */
1480     p_rlc_lte_info->rlcMode = mode;
1481     p_rlc_lte_info->direction = direction;
1482     p_rlc_lte_info->priority = 0; /* ?? */
1483     p_rlc_lte_info->ueid = ueid;
1484     p_rlc_lte_info->channelType = channelType;
1485     p_rlc_lte_info->channelId = channelId;
1486     p_rlc_lte_info->pduLength = data_length;
1487     p_rlc_lte_info->UMSequenceNumberLength = UMSequenceNumberLength;
1488
1489     /* Store info in packet */
1490     p_add_proto_data(pinfo->fd, proto_rlc_lte, p_rlc_lte_info);
1491
1492     if (global_mac_lte_layer_to_show != ShowRLCLayer) {
1493         /* Don't want these columns replaced */
1494         col_set_writable(pinfo->cinfo, FALSE);
1495     }
1496     else {
1497         /* Clear info column before first RLC PDU */
1498         if (s_number_of_rlc_pdus_shown == 0) {
1499             col_clear(pinfo->cinfo, COL_INFO);
1500         }
1501         else {
1502             /* Add a separator and protect column contents here */
1503             write_pdu_label_and_info(pdu_ti, NULL, pinfo, "   ||   ");
1504             col_set_fence(pinfo->cinfo, COL_INFO);
1505         }
1506     }
1507     s_number_of_rlc_pdus_shown++;
1508
1509     /* Call it (catch exceptions so that stats will be updated) */
1510     TRY {
1511         call_dissector_only(protocol_handle, srb_tvb, pinfo, tree);
1512     }
1513     CATCH_ALL {
1514     }
1515     ENDTRY
1516
1517     col_set_writable(pinfo->cinfo, TRUE);
1518 }
1519
1520
1521 /* Track DL frames, and look for likely cases of likely HARQ retx. Return TRUE if found */
1522 static int DetectIfDLHARQResend(packet_info *pinfo, tvbuff_t *tvb, volatile int offset,
1523                                 proto_tree *tree, mac_lte_info *p_mac_lte_info)
1524 {
1525     DLHARQResult *result = NULL;
1526     proto_item *result_ti;
1527
1528     /* TDD may not work... */
1529
1530     if (!pinfo->fd->flags.visited) {
1531         /* First time, so set result and update DL harq table */
1532         LastFrameData *lastData = NULL;
1533         LastFrameData *thisData = NULL;
1534
1535         /* Look up entry for this UE/RNTI */
1536         LastFrameDataAllSubframes *ueData =
1537             g_hash_table_lookup(mac_lte_dl_harq_hash, GUINT_TO_POINTER((guint)p_mac_lte_info->rnti));
1538         if (ueData != NULL) {
1539
1540             /* Looking for a frame sent 8 or 9 subframes previously.
1541                TODO: have seen retx >=10 SFs later... */
1542             gboolean found_match = FALSE;
1543             gint     SFs_ago;
1544
1545             for (SFs_ago=8; (SFs_ago <= 9) && !found_match; SFs_ago++) {
1546                 /* Check 8 SFs ago */
1547                 lastData = &(ueData->subframe[(p_mac_lte_info->subframeNumber+(10-SFs_ago)) % 10]);
1548                 if (lastData->inUse) {
1549                     /* Compare time, sf, data to see if this looks like a retx */
1550                     if ((tvb_length_remaining(tvb, offset) == lastData->length) &&
1551                         (memcmp(lastData->data,
1552                                 tvb_get_ptr(tvb, offset, lastData->length),
1553                                 MIN(lastData->length, MAX_EXPECTED_PDU_LENGTH)) == 0)) {
1554
1555                         /* Work out gap between frames */
1556                         gint seconds_between_packets = (gint)
1557                               (pinfo->fd->abs_ts.secs - lastData->received_time.secs);
1558                         gint nseconds_between_packets =
1559                               pinfo->fd->abs_ts.nsecs - lastData->received_time.nsecs;
1560
1561                         /* Round difference to nearest millisecond */
1562                         gint total_gap = (seconds_between_packets*1000) +
1563                                          ((nseconds_between_packets+500000) / 1000000);
1564
1565                         /* Should be equal to number of subframes - allow some leeway */
1566                         if ((total_gap >= (SFs_ago-1)) && (total_gap <= (SFs_ago+1))) {
1567                             found_match = TRUE;
1568
1569                             /* Resend detected!!! Store result */
1570                             result = se_alloc(sizeof(DLHARQResult));
1571                             result->previousFrameNum = lastData->framenum;
1572                             g_hash_table_insert(mac_lte_dl_harq_result_hash, GUINT_TO_POINTER(pinfo->fd->num), result);
1573                         }
1574                     }
1575                 }
1576             }
1577
1578             /* Even if we didn't find a previous frame, if we know its a retx, setup result */
1579             if ((result == NULL) && (p_mac_lte_info->dl_retx == dl_retx_yes)) {
1580                 result = se_alloc(sizeof(DLHARQResult));
1581                 result->previousFrameNum = 0;
1582                 g_hash_table_insert(mac_lte_dl_harq_result_hash, GUINT_TO_POINTER(pinfo->fd->num), result);
1583             }
1584
1585         }
1586         else {
1587             /* Allocate entry in table for this UE/RNTI */
1588             ueData = se_alloc0(sizeof(LastFrameDataAllSubframes));
1589             g_hash_table_insert(mac_lte_dl_harq_hash, GUINT_TO_POINTER((guint)p_mac_lte_info->rnti), ueData);
1590         }
1591
1592         /* Store this frame's details in table */
1593         thisData = &(ueData->subframe[p_mac_lte_info->subframeNumber]);
1594         thisData->inUse = TRUE;
1595         thisData->length = tvb_length_remaining(tvb, offset);
1596         memcpy(thisData->data,
1597                tvb_get_ptr(tvb, offset, MIN(thisData->length, MAX_EXPECTED_PDU_LENGTH)),
1598                MIN(thisData->length, MAX_EXPECTED_PDU_LENGTH));
1599         thisData->subframeNumber = p_mac_lte_info->subframeNumber;
1600         thisData->framenum = pinfo->fd->num;
1601         thisData->received_time = pinfo->fd->abs_ts;
1602     }
1603     else {
1604         /* Not first time, so just set whats already stored in result */
1605         result = g_hash_table_lookup(mac_lte_dl_harq_result_hash, GUINT_TO_POINTER(pinfo->fd->num));
1606     }
1607
1608
1609     /************************************************************/
1610     /* Show result, with link back to original frame (if known) */
1611     result_ti = proto_tree_add_boolean(tree, hf_mac_lte_context_phy_dl_retx,
1612                                        tvb, 0, 0, (result != NULL));
1613     if (result != NULL) {
1614         proto_item *original_ti;
1615         expert_add_info_format(pinfo, result_ti, PI_SEQUENCE, PI_WARN,
1616                                "%sDL HARQ resend (UE=%u)",
1617                                (p_mac_lte_info->dl_retx == dl_retx_unknown) ? "Suspected " : "",
1618                                p_mac_lte_info->ueid);
1619         if (result->previousFrameNum != 0) {
1620             original_ti = proto_tree_add_uint(tree, hf_mac_lte_suspected_dl_retx_original_frame,
1621                                              tvb, 0, 0, result->previousFrameNum);
1622             PROTO_ITEM_SET_GENERATED(original_ti);
1623         }
1624     }
1625     else {
1626         /* Don't show negatives */
1627         PROTO_ITEM_SET_HIDDEN(result_ti);
1628     }
1629     PROTO_ITEM_SET_GENERATED(result_ti);
1630
1631     /* Return TRUE if resend was detected */
1632     return (result != NULL);
1633 }
1634
1635
1636 /* Return TRUE if the given packet is thought to be a retx */
1637 int is_mac_lte_frame_retx(packet_info *pinfo, guint8 direction)
1638 {
1639     if (direction == DIRECTION_UPLINK) {
1640         /* For UL, retx count is stored in per-packet struct */
1641         struct mac_lte_info *p_mac_lte_info = p_get_proto_data(pinfo->fd, proto_mac_lte);
1642         return ((p_mac_lte_info != NULL) && (p_mac_lte_info->reTxCount > 0));
1643     }
1644     else {
1645         /* For DL, must consult result table */
1646         return (g_hash_table_lookup(mac_lte_dl_harq_result_hash, GUINT_TO_POINTER(pinfo->fd->num)) != NULL);
1647     }
1648 }
1649
1650
1651 /* Track UL frames, so that when a retx is indicated, we can search for
1652    the original tx.  We will either find it, and provide a link back to it,
1653    or flag that we couldn't find as an expert error */
1654 static void TrackReportedULHARQResend(packet_info *pinfo, tvbuff_t *tvb, volatile int offset,
1655                                       proto_tree *tree, mac_lte_info *p_mac_lte_info,
1656                                       proto_item *retx_ti)
1657 {
1658     ULHARQResult *result = NULL;
1659
1660     /* FDD only for now! */
1661     if (p_mac_lte_info->radioType != FDD_RADIO) {
1662         return;
1663     }
1664
1665     if (!pinfo->fd->flags.visited) {
1666         /* First time, so set result and update UL harq table */
1667         LastFrameData *lastData = NULL;
1668         LastFrameData *thisData = NULL;
1669
1670         /* Look up entry for this UE/RNTI */
1671         LastFrameDataAllSubframes *ueData =
1672             g_hash_table_lookup(mac_lte_ul_harq_hash, GUINT_TO_POINTER((guint)p_mac_lte_info->rnti));
1673         if (ueData != NULL) {
1674
1675             if (p_mac_lte_info->reTxCount >= 1) {
1676                 /* Looking for a frame sent 8 subframes previously */
1677                 lastData = &(ueData->subframe[(p_mac_lte_info->subframeNumber+2) % 10]);
1678                 if (lastData->inUse) {
1679                     /* Compare time, sf, data to see if this looks like a retx */
1680                     if ((tvb_length_remaining(tvb, offset) == lastData->length) &&
1681                         (memcmp(lastData->data,
1682                                 tvb_get_ptr(tvb, offset, lastData->length),
1683                                 MIN(lastData->length, MAX_EXPECTED_PDU_LENGTH)) == 0)) {
1684
1685                         /* Work out gap between frames */
1686                         gint seconds_between_packets = (gint)
1687                               (pinfo->fd->abs_ts.secs - lastData->received_time.secs);
1688                         gint nseconds_between_packets =
1689                               pinfo->fd->abs_ts.nsecs - lastData->received_time.nsecs;
1690
1691                         /* Round to nearest ms */
1692                         gint total_gap = (seconds_between_packets*1000) +
1693                                          ((nseconds_between_packets+500000) / 1000000);
1694
1695                         /* Should be 8 ms apart - allow some leeway */
1696                         if ((total_gap >= 7) && (total_gap <= 9)) {
1697                             /* Original detected!!! Store result */
1698                             result = se_alloc(sizeof(ULHARQResult));
1699                             result->previousFrameNum = lastData->framenum;
1700                             g_hash_table_insert(mac_lte_ul_harq_result_hash, GUINT_TO_POINTER(pinfo->fd->num), result);
1701                         }
1702                     }
1703                 }
1704             }
1705         }
1706         else {
1707             /* Allocate entry in table for this UE/RNTI */
1708             ueData = se_alloc0(sizeof(LastFrameDataAllSubframes));
1709             g_hash_table_insert(mac_lte_ul_harq_hash, GUINT_TO_POINTER((guint)p_mac_lte_info->rnti), ueData);
1710         }
1711
1712         /* Store this frame's details in table */
1713         thisData = &(ueData->subframe[p_mac_lte_info->subframeNumber]);
1714         thisData->inUse = TRUE;
1715         thisData->length = tvb_length_remaining(tvb, offset);
1716         memcpy(thisData->data,
1717                tvb_get_ptr(tvb, offset, MIN(thisData->length, MAX_EXPECTED_PDU_LENGTH)),
1718                MIN(thisData->length, MAX_EXPECTED_PDU_LENGTH));
1719         thisData->subframeNumber = p_mac_lte_info->subframeNumber;
1720         thisData->framenum = pinfo->fd->num;
1721         thisData->received_time = pinfo->fd->abs_ts;
1722     }
1723     else {
1724         /* Not first time, so just set whats already stored in result */
1725         result = g_hash_table_lookup(mac_lte_ul_harq_result_hash, GUINT_TO_POINTER(pinfo->fd->num));
1726     }
1727
1728     if (retx_ti != NULL) {
1729         if (result != NULL) {
1730             proto_item *original_ti;
1731
1732             original_ti = proto_tree_add_uint(tree, hf_mac_lte_ul_harq_resend_original_frame,
1733                                               tvb, 0, 0, result->previousFrameNum);
1734             PROTO_ITEM_SET_GENERATED(original_ti);
1735         }
1736         else {
1737             expert_add_info_format(pinfo, retx_ti, PI_SEQUENCE, PI_ERROR,
1738                                    "Original Tx of UL frame not found (UE %u) !!", p_mac_lte_info->ueid);
1739         }
1740     }
1741 }
1742
1743
1744 /* Look up SRResult associated with a given frame. Will create one if necessary
1745    if can_create is set */
1746 static SRResult *GetSRResult(guint32 frameNum, gboolean can_create)
1747 {
1748     SRResult *result;
1749     result = g_hash_table_lookup(mac_lte_sr_request_hash, GUINT_TO_POINTER(frameNum));
1750
1751     if ((result == NULL) && can_create) {
1752         result = se_alloc0(sizeof(SRResult));
1753         g_hash_table_insert(mac_lte_sr_request_hash, GUINT_TO_POINTER((guint)frameNum), result);
1754     }
1755     return result;
1756 }
1757
1758
1759 /* Keep track of SR requests, failures and related grants, in order to show them
1760    as generated fields in these frames */
1761 static void TrackSRInfo(SREvent event, packet_info *pinfo, proto_tree *tree _U_,
1762                         tvbuff_t *tvb _U_, guint16 rnti, proto_item *event_ti)
1763 {
1764     SRResult *result = NULL;
1765     SRResult *resultForSRFrame = NULL;
1766     proto_item *ti;
1767
1768     /* Create state for this RNTI if necessary */
1769     SRState *state = g_hash_table_lookup(mac_lte_ue_sr_state, GUINT_TO_POINTER((guint)rnti));
1770     if (state == NULL) {
1771         /* Allocate status for this RNTI */
1772         state = se_alloc(sizeof(SRState));
1773         state->status = None;
1774         g_hash_table_insert(mac_lte_ue_sr_state, GUINT_TO_POINTER((guint)rnti), state);
1775     }
1776
1777     /* First time through - update state with new info */
1778     if (!pinfo->fd->flags.visited) {
1779         guint32 timeSinceRequest;
1780
1781         /* Store time of request */
1782         if (event == SR_Request) {
1783             state->requestTime = pinfo->fd->abs_ts;
1784         }
1785
1786         switch (state->status) {
1787             case None:
1788                 switch (event) {
1789                     case SR_Grant:
1790                         /* Got another grant - fine */
1791
1792                         /* update state */
1793                         state->lastGrantFramenum = pinfo->fd->num;
1794                         break;
1795
1796                     case SR_Request:
1797                         /* Sent an SR - fine */
1798
1799                         /* Update state */
1800                         state->status = SR_Outstanding;
1801                         state->lastSRFramenum = pinfo->fd->num;
1802                         break;
1803
1804                     case SR_Failure:
1805                         /* This is an error, since we hadn't send an SR... */
1806                         result = GetSRResult(pinfo->fd->num, TRUE);
1807                         result->type = InvalidSREvent;
1808                         result->status = None;
1809                         result->event = SR_Failure;
1810                         break;
1811                 }
1812                 break;
1813
1814             case SR_Outstanding:
1815                 timeSinceRequest = (guint32)(((pinfo->fd->abs_ts.secs - state->requestTime.secs) * 1000) +
1816                                              ((pinfo->fd->abs_ts.nsecs - state->requestTime.nsecs) / 1000000));
1817
1818                 switch (event) {
1819                     case SR_Grant:
1820                         /* Got grant we were waiting for, so state goes to None */
1821
1822                         /* Update state */
1823                         state->status = None;
1824
1825                         /* Set result info */
1826                         result = GetSRResult(pinfo->fd->num, TRUE);
1827                         result->type = GrantAnsweringSR;
1828                         result->frameNum = state->lastSRFramenum;
1829                         result->timeDifference = timeSinceRequest;
1830
1831                         /* Also set forward link for SR */
1832                         resultForSRFrame = GetSRResult(state->lastSRFramenum, TRUE);
1833                         resultForSRFrame->type = SRLeadingToGrant;
1834                         resultForSRFrame->frameNum = pinfo->fd->num;
1835                         resultForSRFrame->timeDifference = timeSinceRequest;
1836                         break;
1837
1838                     case SR_Request:
1839                         /* Another request when already have one pending */
1840                         result = GetSRResult(pinfo->fd->num, TRUE);
1841                         result->type = InvalidSREvent;
1842                         result->status = SR_Outstanding;
1843                         result->event = SR_Grant;
1844                         break;
1845
1846                     case SR_Failure:
1847                         /* We sent an SR but it failed */
1848
1849                         /* Update state */
1850                         state->status = SR_Failed;
1851
1852                         /* Set result info for failure frame */
1853                         result = GetSRResult(pinfo->fd->num, TRUE);
1854                         result->type = FailureAnsweringSR;
1855                         result->frameNum = state->lastSRFramenum;
1856                         result->timeDifference = timeSinceRequest;
1857
1858                         /* Also set forward link for SR */
1859                         resultForSRFrame = GetSRResult(state->lastSRFramenum, TRUE);
1860                         resultForSRFrame->type = SRLeadingToFailure;
1861                         resultForSRFrame->frameNum = pinfo->fd->num;
1862                         resultForSRFrame->timeDifference = timeSinceRequest;
1863                         break;
1864                 }
1865                 break;
1866
1867             case SR_Failed:
1868                 switch (event) {
1869                     case SR_Grant:
1870                         /* Got a grant, presumably after a subsequent RACH - fine */
1871
1872                         /* Update state */
1873                         state->status = None;
1874                         break;
1875
1876                     case SR_Request:
1877                         /* Tried another SR after a failure, and presumbly no
1878                            successful subsequent RACH */
1879                         result = GetSRResult(pinfo->fd->num, TRUE);
1880                         result->type = InvalidSREvent;
1881                         result->status = SR_Failed;
1882                         result->event = SR_Request;
1883                         break;
1884
1885                     case SR_Failure:
1886                         /* 2 failures in a row.... */
1887                         result = GetSRResult(pinfo->fd->num, TRUE);
1888                         result->type = InvalidSREvent;
1889                         result->status = SR_Failed;
1890                         result->event = SR_Failure;
1891                         break;
1892                 }
1893                 break;
1894         }
1895     }
1896
1897     /* Get stored result for this frame */
1898     result = GetSRResult(pinfo->fd->num, FALSE);
1899     if (result == NULL) {
1900         /* For an SR frame, there should always be either a PDCCH grant or indication
1901            that the SR has failed */
1902         if (event == SR_Request) {
1903             expert_add_info_format(pinfo, event_ti, PI_SEQUENCE, PI_ERROR,
1904                                   "SR results in neither a grant or a failure indication");
1905         }
1906         return;
1907     }
1908
1909
1910     /* Show result info */
1911     switch (result->type) {
1912         case GrantAnsweringSR:
1913             ti = proto_tree_add_uint(tree, hf_mac_lte_grant_answering_sr,
1914                                      tvb, 0, 0, result->frameNum);
1915             PROTO_ITEM_SET_GENERATED(ti);
1916             ti = proto_tree_add_uint(tree, hf_mac_lte_sr_time_since_request,
1917                                      tvb, 0, 0, result->timeDifference);
1918             PROTO_ITEM_SET_GENERATED(ti);
1919             break;
1920
1921         case FailureAnsweringSR:
1922             ti = proto_tree_add_uint(tree, hf_mac_lte_failure_answering_sr,
1923                                      tvb, 0, 0, result->frameNum);
1924             PROTO_ITEM_SET_GENERATED(ti);
1925             ti = proto_tree_add_uint(tree, hf_mac_lte_sr_time_since_request,
1926                                      tvb, 0, 0, result->timeDifference);
1927             PROTO_ITEM_SET_GENERATED(ti);
1928             break;
1929
1930         case SRLeadingToGrant:
1931             ti = proto_tree_add_uint(tree, hf_mac_lte_sr_leading_to_grant,
1932                                      tvb, 0, 0, result->frameNum);
1933             PROTO_ITEM_SET_GENERATED(ti);
1934             ti = proto_tree_add_uint(tree, hf_mac_lte_sr_time_until_answer,
1935                                      tvb, 0, 0, result->timeDifference);
1936             PROTO_ITEM_SET_GENERATED(ti);
1937
1938             break;
1939
1940         case SRLeadingToFailure:
1941             ti = proto_tree_add_uint(tree, hf_mac_lte_sr_leading_to_failure,
1942                                      tvb, 0, 0, result->frameNum);
1943             PROTO_ITEM_SET_GENERATED(ti);
1944             ti = proto_tree_add_uint(tree, hf_mac_lte_sr_time_until_answer,
1945                                      tvb, 0, 0, result->timeDifference);
1946             PROTO_ITEM_SET_GENERATED(ti);
1947             break;
1948
1949         case InvalidSREvent:
1950             ti = proto_tree_add_none_format(tree, hf_mac_lte_sr_invalid_event,
1951                                             tvb, 0, 0, "Invalid SR event - state=(%s), event=(%s)",
1952                                             val_to_str_const(result->status, sr_status_vals, "Unknown"),
1953                                             val_to_str_const(result->event,  sr_event_vals,  "Unknown"));
1954             PROTO_ITEM_SET_GENERATED(ti);
1955             expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_ERROR,
1956                                    "Invalid SR event - state=(%s), event=(%s)",
1957                                    val_to_str_const(result->status, sr_status_vals, "Unknown"),
1958                                    val_to_str_const(result->event,  sr_event_vals,  "Unknown"));
1959
1960             break;
1961     }
1962 }
1963
1964
1965
1966
1967
1968 #define MAX_HEADERS_IN_PDU 1024
1969
1970 /* UL-SCH and DL-SCH formats have much in common, so handle them in a common
1971    function */
1972 static void dissect_ulsch_or_dlsch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1973                                    proto_item *pdu_ti,
1974                                    volatile int offset, guint8 direction,
1975                                    mac_lte_info *p_mac_lte_info, mac_lte_tap_info *tap_info,
1976                                    proto_item *retx_ti,
1977                                    proto_tree *context_tree)
1978 {
1979     guint8          extension;
1980     volatile guint8 n;
1981     proto_item      *truncated_ti;
1982     proto_item      *padding_length_ti;
1983     proto_item      *hidden_root_ti;
1984
1985     /* Keep track of LCIDs and lengths as we dissect the header */
1986     volatile guint8 number_of_headers = 0;
1987     guint8  lcids[MAX_HEADERS_IN_PDU];
1988     gint16  pdu_lengths[MAX_HEADERS_IN_PDU];
1989
1990     proto_item *pdu_header_ti;
1991     proto_tree *pdu_header_tree;
1992
1993     gboolean   have_seen_data_header = FALSE;
1994     gboolean   have_seen_bsr = FALSE;
1995     gboolean   expecting_body_data = FALSE;
1996     volatile   guint32    is_truncated = FALSE;
1997
1998     write_pdu_label_and_info(pdu_ti, NULL, pinfo,
1999                              "%s: (SF=%u) UEId=%u ",
2000                              (direction == DIRECTION_UPLINK) ? "UL-SCH" : "DL-SCH",
2001                              p_mac_lte_info->subframeNumber,
2002                              p_mac_lte_info->ueid);
2003
2004     tap_info->raw_length = p_mac_lte_info->length;
2005
2006     /* For downlink frames, can try to work out if this looks like a HARQ resend */
2007     if (direction == DIRECTION_DOWNLINK) {
2008         /* Result will be added to context tree */
2009         int detected = DetectIfDLHARQResend(pinfo, tvb, offset, context_tree, p_mac_lte_info);
2010         if (p_mac_lte_info->dl_retx == dl_retx_unknown) {
2011             tap_info->isPHYRetx = detected;
2012         }
2013         else {
2014             tap_info->isPHYRetx = p_mac_lte_info->dl_retx;
2015         }
2016     }
2017
2018
2019     /* For uplink frames, if this is logged as a resend, look for original tx */
2020     if ((direction == DIRECTION_UPLINK) && global_mac_lte_attempt_ul_harq_resend_track) {
2021         TrackReportedULHARQResend(pinfo, tvb, offset, tree, p_mac_lte_info, retx_ti);
2022     }
2023
2024     /* For uplink grants, update SR status */
2025     if ((direction == DIRECTION_UPLINK) && global_mac_lte_track_sr) {
2026         TrackSRInfo(SR_Grant, pinfo, tree, tvb, p_mac_lte_info->rnti, NULL);
2027     }
2028
2029     /* Add hidden item to filter on */
2030     hidden_root_ti = proto_tree_add_string_format(tree,
2031                                                  (direction == DIRECTION_UPLINK) ?
2032                                                     hf_mac_lte_ulsch :
2033                                                     hf_mac_lte_dlsch,
2034                                                  tvb, offset, 0,
2035                                                  "",
2036                                                  "Hidden header");
2037     PROTO_ITEM_SET_HIDDEN(hidden_root_ti);
2038
2039     /* Add PDU block header subtree */
2040     pdu_header_ti = proto_tree_add_string_format(tree,
2041                                                  (direction == DIRECTION_UPLINK) ?
2042                                                     hf_mac_lte_ulsch_header :
2043                                                     hf_mac_lte_dlsch_header,
2044                                                  tvb, offset, 0,
2045                                                  "",
2046                                                  "MAC PDU Header");
2047     pdu_header_tree = proto_item_add_subtree(pdu_header_ti,
2048                                              (direction == DIRECTION_UPLINK) ?
2049                                                     ett_mac_lte_ulsch_header :
2050                                                     ett_mac_lte_dlsch_header);
2051
2052
2053     /************************************************************************/
2054     /* Dissect each sub-header.                                             */
2055     do {
2056         guint8 reserved;
2057         guint64 length = 0;
2058         proto_item *pdu_subheader_ti;
2059         proto_tree *pdu_subheader_tree;
2060         proto_item *lcid_ti;
2061         proto_item *ti;
2062         gint       offset_start_subheader = offset;
2063         guint8 first_byte = tvb_get_guint8(tvb, offset);
2064
2065         /* Add PDU block header subtree */
2066         pdu_subheader_ti = proto_tree_add_string_format(pdu_header_tree,
2067                                                         hf_mac_lte_sch_subheader,
2068                                                         tvb, offset, 0,
2069                                                         "",
2070                                                         "Sub-header");
2071         pdu_subheader_tree = proto_item_add_subtree(pdu_subheader_ti,
2072                                                     ett_mac_lte_sch_subheader);
2073
2074         /* Check 1st 2 reserved bits */
2075         reserved = (first_byte & 0xc0) >> 6;
2076         ti = proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_sch_reserved,
2077                                  tvb, offset, 1, FALSE);
2078         if (reserved != 0) {
2079             expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
2080                                    "%cL-SCH header Reserved bits not zero",
2081                                    (p_mac_lte_info->direction == DIRECTION_UPLINK) ? 'U' : 'D');
2082         }
2083
2084         /* Extended bit */
2085         extension = (first_byte & 0x20) >> 5;
2086         proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_sch_extended,
2087                             tvb, offset, 1, FALSE);
2088
2089         /* LCID.  Has different meaning depending upon direction. */
2090         lcids[number_of_headers] = first_byte & 0x1f;
2091         if (direction == DIRECTION_UPLINK) {
2092             lcid_ti = proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_ulsch_lcid,
2093                                           tvb, offset, 1, FALSE);
2094             write_pdu_label_and_info(pdu_ti, NULL, pinfo,
2095                                      "(%s",
2096                                      val_to_str_const(lcids[number_of_headers],
2097                                                       ulsch_lcid_vals, "(Unknown LCID)"));
2098         }
2099         else {
2100             lcid_ti = proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_dlsch_lcid,
2101                                           tvb, offset, 1, FALSE);
2102             write_pdu_label_and_info(pdu_ti, NULL, pinfo,
2103                                      "(%s",
2104                                      val_to_str_const(lcids[number_of_headers],
2105                                                       dlsch_lcid_vals, "(Unknown LCID)"));
2106         }
2107         offset++;
2108
2109         /* Remember if we've seen a data subheader */
2110         if (lcids[number_of_headers] <= 10) {
2111             have_seen_data_header = TRUE;
2112             expecting_body_data = TRUE;
2113         }
2114
2115         /* Show an expert item if a contol subheader (except Padding) appears
2116            *after* a data PDU */
2117         if (have_seen_data_header &&
2118             (lcids[number_of_headers] > 10) && (lcids[number_of_headers] != PADDING_LCID)) {
2119             expert_add_info_format(pinfo, lcid_ti, PI_MALFORMED, PI_ERROR,
2120                                    "%cL-SCH Control subheaders should not appear after data subheaders",
2121                                    (p_mac_lte_info->direction == DIRECTION_UPLINK) ? 'U' : 'D');
2122         }
2123
2124         /* Show an expert item if we're seeing more then one BSR in a frame */
2125         if ((direction == DIRECTION_UPLINK) && is_bsr_lcid(lcids[number_of_headers])) {
2126             if (have_seen_bsr) {
2127                 expert_add_info_format(pinfo, lcid_ti, PI_MALFORMED, PI_ERROR,
2128                                       "There shouldn't be > 1 BSR in a frame");
2129             }
2130             have_seen_bsr = TRUE;
2131         }
2132
2133
2134         /********************************************************************/
2135         /* Length field follows if not the last header or for a fixed-sized
2136            control element */
2137         if (!extension) {
2138             if (is_fixed_sized_control_element(lcids[number_of_headers], direction)) {
2139                 pdu_lengths[number_of_headers] = 0;
2140             }
2141             else {
2142                 pdu_lengths[number_of_headers] = -1;
2143             }
2144         }
2145         else {
2146             if (!is_fixed_sized_control_element(lcids[number_of_headers], direction) &&
2147                 (lcids[number_of_headers] != PADDING_LCID)) {
2148
2149                 guint8  format;
2150
2151                 /* F(ormat) bit tells us how long the length field is */
2152                 format = (tvb_get_guint8(tvb, offset) & 0x80) >> 7;
2153                 proto_tree_add_item(pdu_subheader_tree, hf_mac_lte_sch_format,
2154                                     tvb, offset, 1, FALSE);
2155
2156                 /* Now read length field itself */
2157                 if (format) {
2158                     /* >= 128 - use 15 bits */
2159                     proto_tree_add_bits_ret_val(pdu_subheader_tree, hf_mac_lte_sch_length,
2160                                                 tvb, offset*8 + 1, 15, &length, FALSE);
2161
2162                     offset += 2;
2163                 }
2164                 else {
2165                     /* Less than 128 - only 7 bits */
2166                     proto_tree_add_bits_ret_val(pdu_subheader_tree, hf_mac_lte_sch_length,
2167                                                 tvb, offset*8 + 1, 7, &length, FALSE);
2168                     offset++;
2169                 }
2170                 pdu_lengths[number_of_headers] = (gint16)length;
2171             }
2172             else {
2173                 pdu_lengths[number_of_headers] = 0;
2174             }
2175         }
2176
2177
2178         /* Close off description in info column */
2179         switch (pdu_lengths[number_of_headers]) {
2180             case 0:
2181                 write_pdu_label_and_info(pdu_ti, NULL, pinfo, ") ");
2182                 break;
2183             case -1:
2184                 write_pdu_label_and_info(pdu_ti, NULL, pinfo, ":remainder) ");
2185                 break;
2186             default:
2187                 write_pdu_label_and_info(pdu_ti, NULL, pinfo, ":%u bytes) ",
2188                                          pdu_lengths[number_of_headers]);
2189                 break;
2190         }
2191
2192         /* Append summary to subheader root */
2193         proto_item_append_text(pdu_subheader_ti, " (lcid=%s",
2194                                val_to_str_const(lcids[number_of_headers],
2195                                                 (direction == DIRECTION_UPLINK) ?
2196                                                     ulsch_lcid_vals :
2197                                                         dlsch_lcid_vals,
2198                                                 "Unknown"));
2199
2200         switch (pdu_lengths[number_of_headers]) {
2201             case -1:
2202                 proto_item_append_text(pdu_subheader_ti, ", length is remainder)");
2203                 break;
2204             case 0:
2205                 proto_item_append_text(pdu_subheader_ti, ")");
2206                 break;
2207             default:
2208                 proto_item_append_text(pdu_subheader_ti, ", length=%u)",
2209                                        pdu_lengths[number_of_headers]);
2210                 break;
2211         }
2212
2213
2214         /* Flag unknown lcid values in expert info */
2215         if (match_strval(lcids[number_of_headers],
2216                          (direction == DIRECTION_UPLINK) ? ulsch_lcid_vals : dlsch_lcid_vals) == NULL) {
2217             expert_add_info_format(pinfo, pdu_subheader_ti, PI_MALFORMED, PI_ERROR,
2218                                    "%cL-SCH: Unexpected LCID received (%u)",
2219                                    (p_mac_lte_info->direction == DIRECTION_UPLINK) ? 'U' : 'D',
2220                                    lcids[number_of_headers]);
2221         }
2222
2223         /* Set length of this subheader */
2224         proto_item_set_len(pdu_subheader_ti, offset- offset_start_subheader);
2225
2226         number_of_headers++;
2227     } while (extension);
2228
2229     /* Append summary to overall PDU header root */
2230     proto_item_append_text(pdu_header_ti, " (%u subheaders)",
2231                            number_of_headers);
2232
2233     /* And set its length to offset */
2234     proto_item_set_len(pdu_header_ti, offset);
2235
2236
2237
2238
2239     /************************************************************************/
2240     /* Dissect SDUs / control elements / padding.                           */
2241     /************************************************************************/
2242
2243     /* Dissect control element bodies first */
2244
2245     for (n=0; n < number_of_headers; n++) {
2246         /* Get out of loop once see any data SDU subheaders */
2247         if (lcids[n] <= 10) {
2248             break;
2249         }
2250
2251         /* Process what should be a valid control PDU type */
2252         if (direction == DIRECTION_DOWNLINK) {
2253
2254             /****************************/
2255             /* DL-SCH Control PDUs      */
2256             switch (lcids[n]) {
2257                 case UE_CONTENTION_RESOLUTION_IDENTITY_LCID:
2258                     {
2259                         proto_item *cr_ti;
2260                         proto_tree *cr_tree;
2261                         proto_item *ti;
2262                         ContentionResolutionResult *crResult;
2263
2264                         /* Create CR root */
2265                         cr_ti = proto_tree_add_string_format(tree,
2266                                                              hf_mac_lte_control_ue_contention_resolution,
2267                                                              tvb, offset, 6,
2268                                                              "",
2269                                                              "Contention Resolution");
2270                         cr_tree = proto_item_add_subtree(cr_ti, ett_mac_lte_contention_resolution);
2271
2272
2273                         proto_tree_add_item(cr_tree, hf_mac_lte_control_ue_contention_resolution_identity,
2274                                             tvb, offset, 6, FALSE);
2275
2276                         /* Get pointer to result struct for this frame */
2277                         crResult =  g_hash_table_lookup(mac_lte_cr_result_hash, GUINT_TO_POINTER(pinfo->fd->num));
2278                         if (crResult == NULL) {
2279
2280                             /* Need to set result by looking for and comparing with Msg3 */
2281                             Msg3Data *msg3Data;
2282                             guint msg3Key = p_mac_lte_info->rnti;
2283
2284                             /* Allocate result and add it to the table */
2285                             crResult = se_alloc(sizeof(ContentionResolutionResult));
2286                             g_hash_table_insert(mac_lte_cr_result_hash, GUINT_TO_POINTER(pinfo->fd->num), crResult);
2287
2288                             /* Look for Msg3 */
2289                             msg3Data = g_hash_table_lookup(mac_lte_msg3_hash, GUINT_TO_POINTER(msg3Key));
2290
2291                             /* Compare CCCH bytes */
2292                             if (msg3Data != NULL) {
2293                                 crResult->msSinceMsg3 = (guint32)(((pinfo->fd->abs_ts.secs - msg3Data->msg3Time.secs) * 1000) +
2294                                                                   ((pinfo->fd->abs_ts.nsecs - msg3Data->msg3Time.nsecs) / 1000000));
2295                                 crResult->msg3FrameNum = msg3Data->framenum;
2296
2297                                 /* Compare the 6 bytes */
2298                                 if (memcmp(&msg3Data->data, tvb_get_ptr(tvb, offset, 6), 6) == 0) {
2299                                     crResult->status = Msg3Match;
2300                                 }
2301                                 else {
2302                                     crResult->status = Msg3NoMatch;
2303                                 }
2304                             }
2305                             else {
2306                                 crResult->status = NoMsg3;
2307                             }
2308                         }
2309
2310                         /* Now show CR result in tree */
2311                         switch (crResult->status) {
2312                             case NoMsg3:
2313                                 proto_item_append_text(cr_ti, " (no corresponding Msg3 found!)");
2314                                 break;
2315
2316                             case Msg3Match:
2317                                 ti = proto_tree_add_uint(cr_tree, hf_mac_lte_control_ue_contention_resolution_msg3,
2318                                                          tvb, 0, 0, crResult->msg3FrameNum);
2319                                 PROTO_ITEM_SET_GENERATED(ti);
2320                                 ti = proto_tree_add_uint(cr_tree, hf_mac_lte_control_ue_contention_resolution_time_since_msg3,
2321                                                          tvb, 0, 0, crResult->msSinceMsg3);
2322                                 PROTO_ITEM_SET_GENERATED(ti);
2323
2324                                 ti = proto_tree_add_boolean(cr_tree, hf_mac_lte_control_ue_contention_resolution_msg3_matched,
2325                                                             tvb, 0, 0, TRUE);
2326                                 PROTO_ITEM_SET_GENERATED(ti);
2327                                 proto_item_append_text(cr_ti, " (matches Msg3 from frame %u, %ums ago)",
2328                                                        crResult->msg3FrameNum, crResult->msSinceMsg3);
2329                                 break;
2330
2331                             case Msg3NoMatch:
2332                                 ti = proto_tree_add_uint(cr_tree, hf_mac_lte_control_ue_contention_resolution_msg3,
2333                                                          tvb, 0, 0, crResult->msg3FrameNum);
2334                                 PROTO_ITEM_SET_GENERATED(ti);
2335                                 ti = proto_tree_add_uint(cr_tree, hf_mac_lte_control_ue_contention_resolution_time_since_msg3,
2336                                                          tvb, 0, 0, crResult->msSinceMsg3);
2337                                 PROTO_ITEM_SET_GENERATED(ti);
2338
2339                                 ti = proto_tree_add_boolean(cr_tree, hf_mac_lte_control_ue_contention_resolution_msg3_matched,
2340                                                              tvb, 0, 0, FALSE);
2341                                 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
2342                                                        "CR body in Msg4 doesn't match Msg3 CCCH in frame %u",
2343                                                        crResult->msg3FrameNum);
2344                                 PROTO_ITEM_SET_GENERATED(ti);
2345                                 proto_item_append_text(cr_ti, " (doesn't match Msg3 from frame %u, %u ago)",
2346                                                        crResult->msg3FrameNum, crResult->msSinceMsg3);
2347                                 break;
2348                         };
2349
2350                         offset += 6;
2351                     }
2352                     break;
2353                 case TIMING_ADVANCE_LCID:
2354                     {
2355                         proto_item *ta_ti;
2356                         proto_item *reserved_ti;
2357                         guint8      reserved;
2358                         guint8      ta_value;
2359
2360                         /* Check 2 reserved bits */
2361                         reserved = (tvb_get_guint8(tvb, offset) & 0xc0) >> 6;
2362                         reserved_ti = proto_tree_add_item(tree, hf_mac_lte_control_timing_advance_reserved, tvb, offset, 1, FALSE);
2363                         if (reserved != 0) {
2364                             expert_add_info_format(pinfo, reserved_ti, PI_MALFORMED, PI_ERROR,
2365                                                    "Timing Advance Reserved bits not zero (found 0x%x)", reserved);
2366                         }
2367
2368                         /* TA value */
2369                         ta_value = tvb_get_guint8(tvb, offset) & 0x3f;
2370                         ta_ti = proto_tree_add_item(tree, hf_mac_lte_control_timing_advance,
2371                                                     tvb, offset, 1, FALSE);
2372
2373                         if (ta_value == 31) {
2374                             expert_add_info_format(pinfo, ta_ti, PI_SEQUENCE,
2375                                                    PI_NOTE,
2376                                                    "Timing Advance control element received (no correction needed)");
2377                         }
2378                         else {
2379                             expert_add_info_format(pinfo, ta_ti, PI_SEQUENCE,
2380                                                    PI_WARN,
2381                                                    "Timing Advance control element received (%u) %s correction needed",
2382                                                    ta_value,
2383                                                    (ta_value < 31) ? "-ve" : "+ve");
2384                         }
2385                         offset++;
2386                     }
2387                     break;
2388                 case DRX_COMMAND_LCID:
2389                     /* No payload */
2390                     break;
2391                 case PADDING_LCID:
2392                     /* No payload (in this position) */
2393                     tap_info->padding_bytes++;
2394                     break;
2395
2396                 default:
2397                     break;
2398             }
2399         }
2400         else {
2401
2402             /**********************************/
2403             /* UL-SCH Control PDUs            */
2404             switch (lcids[n]) {
2405                 case POWER_HEADROOM_REPORT_LCID:
2406                     {
2407                         proto_item *phr_ti;
2408                         proto_tree *phr_tree;
2409                         proto_item *ti;
2410                         guint8 reserved;
2411                         guint8 level;
2412
2413                         /* Create PHR root */
2414                         phr_ti = proto_tree_add_string_format(tree,
2415                                                               hf_mac_lte_control_power_headroom,
2416                                                               tvb, offset, 1,
2417                                                               "",
2418                                                               "Power Headroom");
2419                         phr_tree = proto_item_add_subtree(phr_ti, ett_mac_lte_power_headroom);
2420
2421                         /* Check 2 Reserved bits */
2422                         reserved = (tvb_get_guint8(tvb, offset) & 0xc0) >> 6;
2423                         ti = proto_tree_add_item(phr_tree, hf_mac_lte_control_power_headroom_reserved,
2424                                                  tvb, offset, 1, FALSE);
2425                         if (reserved != 0) {
2426                             expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
2427                                                    "Power Headroom Reserved bits not zero (found 0x%x)", reserved);
2428                         }
2429
2430                         /* Level */
2431                         level = tvb_get_guint8(tvb, offset) & 0x3f;
2432                         proto_tree_add_item(phr_tree, hf_mac_lte_control_power_headroom_level,
2433                                             tvb, offset, 1, FALSE);
2434
2435                         /* Show value in root label */
2436                         proto_item_append_text(phr_ti, " (%s)",
2437                                                val_to_str_const(level, power_headroom_size_vals, "Unknown"));
2438                         offset++;
2439                     }
2440
2441
2442                     break;
2443                 case CRNTI_LCID:
2444                     proto_tree_add_item(tree, hf_mac_lte_control_crnti,
2445                                         tvb, offset, 2, FALSE);
2446                     offset += 2;
2447                     break;
2448                 case TRUNCATED_BSR_LCID:
2449                 case SHORT_BSR_LCID:
2450                     {
2451                         proto_tree *bsr_tree;
2452                         proto_item *bsr_ti;
2453                         proto_item *buffer_size_ti;
2454                         guint8 lcgid;
2455                         guint8 buffer_size;
2456
2457                         bsr_ti = proto_tree_add_string_format(tree,
2458                                                               hf_mac_lte_control_bsr,
2459                                                               tvb, offset, 1,
2460                                                               "",
2461                                                               "Short BSR");
2462                         bsr_tree = proto_item_add_subtree(bsr_ti, ett_mac_lte_bsr);
2463
2464                         /* LCG ID */
2465                         lcgid = (tvb_get_guint8(tvb, offset) & 0xc0) >> 6;
2466                         proto_tree_add_item(bsr_tree, hf_mac_lte_control_bsr_lcg_id,
2467                                                     tvb, offset, 1, FALSE);
2468                         /* Buffer Size */
2469                         buffer_size = tvb_get_guint8(tvb, offset) & 0x3f;
2470                         buffer_size_ti = proto_tree_add_item(bsr_tree, hf_mac_lte_control_short_bsr_buffer_size,
2471                                                              tvb, offset, 1, FALSE);
2472                         offset++;
2473                         if (buffer_size >= global_mac_lte_bsr_warn_threshold) {
2474                             expert_add_info_format(pinfo, buffer_size_ti, PI_SEQUENCE, PI_WARN,
2475                                                    "UE %u - BSR for LCG %u exceeds threshold: %u (%s)",
2476                                                    p_mac_lte_info->ueid,
2477                                                    lcgid,
2478                                                    buffer_size, val_to_str_const(buffer_size, buffer_size_vals, "Unknown"));
2479                         }
2480
2481
2482                         proto_item_append_text(bsr_ti, " (lcgid=%u  %s)",
2483                                                lcgid,
2484                                                val_to_str_const(buffer_size, buffer_size_vals, "Unknown"));
2485                     }
2486                     break;
2487                 case LONG_BSR_LCID:
2488                     {
2489                         proto_tree *bsr_tree;
2490                         proto_item *bsr_ti;
2491                         proto_item *buffer_size_ti;
2492                         guint8     buffer_size[4];
2493                         bsr_ti = proto_tree_add_string_format(tree,
2494                                                               hf_mac_lte_control_bsr,
2495                                                               tvb, offset, 3,
2496                                                               "",
2497                                                               "Long BSR");
2498                         bsr_tree = proto_item_add_subtree(bsr_ti, ett_mac_lte_bsr);
2499
2500                         /* LCID Group 0 */
2501                         buffer_size_ti = proto_tree_add_item(bsr_tree, hf_mac_lte_control_long_bsr_buffer_size_0,
2502                                                              tvb, offset, 1, FALSE);
2503                         buffer_size[0] = (tvb_get_guint8(tvb, offset) & 0xfc) >> 2;
2504                         if (buffer_size[0] >= global_mac_lte_bsr_warn_threshold) {
2505                             expert_add_info_format(pinfo, buffer_size_ti, PI_SEQUENCE, PI_WARN,
2506                                                    "UE %u - BSR for LCG 0 exceeds threshold: %u (%s)",
2507                                                    p_mac_lte_info->ueid,
2508                                                    buffer_size[0], val_to_str_const(buffer_size[0], buffer_size_vals, "Unknown"));
2509                         }
2510
2511                         /* LCID Group 1 */
2512                         buffer_size_ti = proto_tree_add_item(bsr_tree, hf_mac_lte_control_long_bsr_buffer_size_1,
2513                                                              tvb, offset, 2, FALSE);
2514                         buffer_size[1] = ((tvb_get_guint8(tvb, offset) & 0x03) << 4) | ((tvb_get_guint8(tvb, offset+1) & 0xf0) >> 4);
2515                         offset++;
2516                         if (buffer_size[1] >= global_mac_lte_bsr_warn_threshold) {
2517                             expert_add_info_format(pinfo, buffer_size_ti, PI_SEQUENCE, PI_WARN,
2518                                                    "UE %u - BSR for LCG 1 exceeds threshold: %u (%s)",
2519                                                    p_mac_lte_info->ueid,
2520                                                    buffer_size[1], val_to_str_const(buffer_size[1], buffer_size_vals, "Unknown"));
2521                         }
2522
2523                         /* LCID Group 2 */
2524                         buffer_size_ti = proto_tree_add_item(bsr_tree, hf_mac_lte_control_long_bsr_buffer_size_2,
2525                                                              tvb, offset, 2, FALSE);
2526
2527                         buffer_size[2] = ((tvb_get_guint8(tvb, offset) & 0x0f) << 2) | ((tvb_get_guint8(tvb, offset+1) & 0xc0) >> 6);
2528                         offset++;
2529                         if (buffer_size[2] >= global_mac_lte_bsr_warn_threshold) {
2530                             expert_add_info_format(pinfo, buffer_size_ti, PI_SEQUENCE, PI_WARN,
2531                                                    "UE %u - BSR for LCG 2 exceeds threshold: %u (%s)",
2532                                                    p_mac_lte_info->ueid,
2533                                                    buffer_size[2], val_to_str_const(buffer_size[2], buffer_size_vals, "Unknown"));
2534                         }
2535
2536                         /* LCID Group 3 */
2537                         buffer_size_ti = proto_tree_add_item(bsr_tree, hf_mac_lte_control_long_bsr_buffer_size_3,
2538                                                              tvb, offset, 1, FALSE);
2539                         buffer_size[3] = tvb_get_guint8(tvb, offset) & 0x3f;
2540                         offset++;
2541                         if (buffer_size[3] >= global_mac_lte_bsr_warn_threshold) {
2542                             expert_add_info_format(pinfo, buffer_size_ti, PI_SEQUENCE, PI_WARN,
2543                                                    "UE %u - BSR for LCG 3 exceeds threshold: %u (%s)",
2544                                                    p_mac_lte_info->ueid,
2545                                                    buffer_size[3], val_to_str_const(buffer_size[3], buffer_size_vals, "Unknown"));
2546                         }
2547
2548                         /* Append summary to parent */
2549                         proto_item_append_text(bsr_ti, "   0:(%s)  1:(%s)  2:(%s)  3:(%s)",
2550                                                val_to_str_const(buffer_size[0], buffer_size_vals, "Unknown"),
2551                                                val_to_str_const(buffer_size[1], buffer_size_vals, "Unknown"),
2552                                                val_to_str_const(buffer_size[2], buffer_size_vals, "Unknown"),
2553                                                val_to_str_const(buffer_size[3], buffer_size_vals, "Unknown"));
2554                     }
2555                     break;
2556                 case PADDING_LCID:
2557                     /* No payload, in this position */
2558                     tap_info->padding_bytes++;
2559                     break;
2560
2561                 default:
2562                     break;
2563             }
2564         }
2565     }
2566
2567
2568     /* There might not be any data, if only headers (plus control data) were logged */
2569     is_truncated = ((tvb_length_remaining(tvb, offset) == 0) && expecting_body_data);
2570     truncated_ti = proto_tree_add_uint(tree, hf_mac_lte_sch_header_only, tvb, 0, 0,
2571                                        is_truncated);
2572     if (is_truncated) {
2573         PROTO_ITEM_SET_GENERATED(truncated_ti);
2574         expert_add_info_format(pinfo, truncated_ti, PI_SEQUENCE, PI_NOTE,
2575                                "MAC PDU SDUs have been omitted");
2576         return;
2577     }
2578     else {
2579         PROTO_ITEM_SET_HIDDEN(truncated_ti);
2580     }
2581
2582
2583     /* Now process remaining bodies, which should all be data */
2584     for (; n < number_of_headers; n++) {
2585
2586         /* Data SDUs treated identically for Uplink or downlink channels */
2587         proto_item *sdu_ti;
2588         const guint8 *pdu_data;
2589         volatile guint16 data_length;
2590         int i;
2591         char buff[64];
2592
2593         /* Break out if meet padding */
2594         if (lcids[n] == PADDING_LCID) {
2595             break;
2596         }
2597
2598         /* Work out length */
2599         data_length = (pdu_lengths[n] == -1) ?
2600                             tvb_length_remaining(tvb, offset) :
2601                             pdu_lengths[n];
2602
2603         /* Dissect SDU as raw bytes */
2604         sdu_ti = proto_tree_add_bytes_format(tree, hf_mac_lte_sch_sdu, tvb, offset, pdu_lengths[n],
2605                                              tvb_get_ptr(tvb, offset, pdu_lengths[n]),
2606                                              "SDU (%s, length=%u bytes): ",
2607                                              val_to_str_const(lcids[n],
2608                                                               (direction == DIRECTION_UPLINK) ?
2609                                                                   ulsch_lcid_vals :
2610                                                                   dlsch_lcid_vals,
2611                                                              "Unknown"),
2612                                              data_length);
2613         /* Show bytes too.  There must be a nicer way of doing this! */
2614         pdu_data = tvb_get_ptr(tvb, offset, pdu_lengths[n]);
2615         for (i=0; i < data_length; i++) {
2616             g_snprintf(buff+(i*2), 3, "%02x",  pdu_data[i]);
2617             if (i >= 30) {
2618                 g_snprintf(buff+(i*2), 4, "...");
2619                 break;
2620             }
2621         }
2622         proto_item_append_text(sdu_ti, "%s", buff);
2623
2624
2625         /* Look for Msg3 data so that it may be compared with later
2626            Contention Resolution body */
2627         if ((lcids[n] == 0) && (direction == DIRECTION_UPLINK) && (data_length == 6)) {
2628             if (!pinfo->fd->flags.visited) {
2629                 guint key = p_mac_lte_info->rnti;
2630                 Msg3Data *data = g_hash_table_lookup(mac_lte_msg3_hash, GUINT_TO_POINTER(key));
2631
2632                 /* Look for previous entry for this UE */
2633                 if (data == NULL) {
2634                     /* Allocate space for data and add to table */
2635                     data = se_alloc(sizeof(Msg3Data));
2636                     g_hash_table_insert(mac_lte_msg3_hash, GUINT_TO_POINTER(key), data);
2637                 }
2638
2639                 /* Fill in data details */
2640                 data->framenum = pinfo->fd->num;
2641                 memcpy(&data->data, tvb_get_ptr(tvb, offset, data_length), data_length);
2642                 data->msg3Time = pinfo->fd->abs_ts;
2643             }
2644         }
2645
2646         /* CCCH frames can be dissected directly by LTE RRC... */
2647         if ((lcids[n] == 0) && global_mac_lte_attempt_rrc_decode) {
2648             tvbuff_t *rrc_tvb = tvb_new_subset(tvb, offset, data_length, data_length);
2649
2650             /* Get appropriate dissector handle */
2651             volatile dissector_handle_t protocol_handle = 0;
2652             if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
2653                 protocol_handle = find_dissector("lte_rrc.ul_ccch");
2654             }
2655             else {
2656                 protocol_handle = find_dissector("lte_rrc.dl_ccch");
2657             }
2658
2659             /* Hide raw view of bytes */
2660             PROTO_ITEM_SET_HIDDEN(sdu_ti);
2661
2662             /* Call it (catch exceptions so that stats will be updated) */
2663             TRY {
2664                 call_dissector_only(protocol_handle, rrc_tvb, pinfo, tree);
2665             }
2666             CATCH_ALL {
2667             }
2668             ENDTRY
2669         }
2670
2671         /* LCID 1 and 2 can be assumed to be srb1&2, so can dissect as RLC AM */
2672         if ((lcids[n] == 1) || (lcids[n] == 2)) {
2673             if (global_mac_lte_attempt_srb_decode) {
2674                 /* Call RLC dissector */
2675                 call_rlc_dissector(tvb, pinfo, tree, pdu_ti, offset, data_length,
2676                                    RLC_AM_MODE, direction, p_mac_lte_info->ueid,
2677                                    CHANNEL_TYPE_SRB, lcids[n], 0);
2678
2679                 /* Hide raw view of bytes */
2680                 PROTO_ITEM_SET_HIDDEN(sdu_ti);
2681             }
2682         }
2683
2684         else if ((lcids[n] >= 2) && (lcids[n] <= 10)) {
2685
2686             /* Look for mapping for this LCID to drb channel set by UAT table */
2687             rlc_channel_type_t rlc_channel_type = rlcRaw;
2688             guint8 UM_seqnum_length = 0;
2689             gint drb_id = 0;
2690
2691             guint m;
2692             for (m=0; m < num_lcid_drb_mappings; m++) {
2693                 if (lcids[n] == lcid_drb_mappings[m].lcid) {
2694
2695                     rlc_channel_type = lcid_drb_mappings[m].channel_type;
2696
2697                     /* Set UM_seqnum_length */
2698                     switch (lcid_drb_mappings[m].channel_type) {
2699                         case rlcUM5:
2700                             UM_seqnum_length = 5;
2701                             break;
2702                         case rlcUM10:
2703                             UM_seqnum_length = 10;
2704                             break;
2705                         default:
2706                             break;
2707                     }
2708
2709                     /* Set drb_id */
2710                     drb_id = lcid_drb_mappings[m].drbid;
2711                     break;
2712                 }
2713             }
2714
2715             /* Dissect according to channel type */
2716             switch (rlc_channel_type) {
2717                 case rlcUM5:
2718                     call_rlc_dissector(tvb, pinfo, tree, pdu_ti, offset, data_length,
2719                                        RLC_UM_MODE, direction, p_mac_lte_info->ueid,
2720                                        CHANNEL_TYPE_DRB, (guint16)drb_id, UM_seqnum_length);
2721                     break;
2722                 case rlcUM10:
2723                     call_rlc_dissector(tvb, pinfo, tree, pdu_ti, offset, data_length,
2724                                        RLC_UM_MODE, direction, p_mac_lte_info->ueid,
2725                                        CHANNEL_TYPE_DRB, (guint16)drb_id, UM_seqnum_length);
2726                     break;
2727                 case rlcAM:
2728                     call_rlc_dissector(tvb, pinfo, tree, pdu_ti, offset, data_length,
2729                                        RLC_AM_MODE, direction, p_mac_lte_info->ueid,
2730                                        CHANNEL_TYPE_DRB, (guint16)drb_id, 0);
2731                     break;
2732                 case rlcTM:
2733                     call_rlc_dissector(tvb, pinfo, tree, pdu_ti, offset, data_length,
2734                                        RLC_TM_MODE, direction, p_mac_lte_info->ueid,
2735                                        CHANNEL_TYPE_DRB, (guint16)drb_id, 0);
2736                     break;
2737                 case rlcRaw:
2738                     /* Nothing to do! */
2739                     break;
2740             }
2741
2742             if (rlc_channel_type != rlcRaw) {
2743                 /* Hide raw view of bytes */
2744                 PROTO_ITEM_SET_HIDDEN(sdu_ti);
2745             }
2746
2747         }
2748
2749         offset += data_length;
2750
2751         /* Update tap byte count for this channel */
2752         tap_info->bytes_for_lcid[lcids[n]] += data_length;
2753         tap_info->sdus_for_lcid[lcids[n]]++;
2754     }
2755
2756     /* Now padding, if present, extends to the end of the PDU */
2757     if (lcids[number_of_headers-1] == PADDING_LCID) {
2758         if (tvb_length_remaining(tvb, offset) > 0) {
2759             proto_tree_add_item(tree, hf_mac_lte_padding_data,
2760                                 tvb, offset, -1, FALSE);
2761         }
2762         padding_length_ti = proto_tree_add_int(tree, hf_mac_lte_padding_length,
2763                                                tvb, offset, 0,
2764                                                p_mac_lte_info->length - offset);
2765         PROTO_ITEM_SET_GENERATED(padding_length_ti);
2766
2767         /* Update padding bytes in stats */
2768         tap_info->padding_bytes += (p_mac_lte_info->length - offset);
2769
2770         /* Make sure the PDU isn't bigger than reported! */
2771         if (offset > p_mac_lte_info->length) {
2772             expert_add_info_format(pinfo, padding_length_ti, PI_MALFORMED, PI_ERROR,
2773                                    "MAC PDU is longer than reported length (reported=%u, actual=%u)",
2774                                    p_mac_lte_info->length, offset);
2775         }
2776     }
2777     else {
2778         /* There is no padding at the end of the frame */
2779         if (!is_truncated && (offset < p_mac_lte_info->length)) {
2780             /* There is a problem if we haven't used all of the PDU */
2781             expert_add_info_format(pinfo, pdu_ti, PI_MALFORMED, PI_ERROR,
2782                                    "PDU for UE %u is shorter than reported length (reported=%u, actual=%u)",
2783                                    p_mac_lte_info->ueid, p_mac_lte_info->length, offset);
2784         }
2785
2786         if (!is_truncated && (offset > p_mac_lte_info->length)) {
2787             /* There is a problem if the PDU is longer than rpeported */
2788             expert_add_info_format(pinfo, pdu_ti, PI_MALFORMED, PI_ERROR,
2789                                    "PDU for UE %u is longer than reported length (reported=%u, actual=%u)",
2790                                    p_mac_lte_info->ueid, p_mac_lte_info->length, offset);
2791         }
2792     }
2793 }
2794
2795
2796
2797 /*****************************/
2798 /* Main dissection function. */
2799 void dissect_mac_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2800 {
2801     proto_tree             *mac_lte_tree;
2802     proto_item             *pdu_ti;
2803     proto_tree             *context_tree;
2804     proto_item             *context_ti;
2805     proto_item             *retx_ti = NULL;
2806     proto_item             *ti;
2807     gint                   offset = 0;
2808     struct mac_lte_info    *p_mac_lte_info = NULL;
2809
2810     /* Zero out tap */
2811     static mac_lte_tap_info tap_info;
2812     memset(&tap_info, 0, sizeof(mac_lte_tap_info));
2813
2814     /* Set protocol name */
2815     col_set_str(pinfo->cinfo, COL_PROTOCOL, "MAC-LTE");
2816
2817     /* Create protocol tree. */
2818     pdu_ti = proto_tree_add_item(tree, proto_mac_lte, tvb, offset, -1, FALSE);
2819     proto_item_append_text(pdu_ti, " ");
2820     mac_lte_tree = proto_item_add_subtree(pdu_ti, ett_mac_lte);
2821
2822
2823     /* Look for packet info! */
2824     p_mac_lte_info = p_get_proto_data(pinfo->fd, proto_mac_lte);
2825
2826     /* Can't dissect anything without it... */
2827     if (p_mac_lte_info == NULL) {
2828         proto_item *tii =
2829             proto_tree_add_text(mac_lte_tree, tvb, offset, -1,
2830                                 "Can't dissect LTE MAC frame because no per-frame info was attached!");
2831         PROTO_ITEM_SET_GENERATED(tii);
2832         return;
2833     }
2834
2835     /* Clear info column */
2836     col_clear(pinfo->cinfo, COL_INFO);
2837
2838
2839     /*****************************************/
2840     /* Show context information              */
2841
2842     /* Create context root */
2843     context_ti = proto_tree_add_string_format(mac_lte_tree, hf_mac_lte_context,
2844                                               tvb, offset, 0, "", "Context");
2845     context_tree = proto_item_add_subtree(context_ti, ett_mac_lte_context);
2846     PROTO_ITEM_SET_GENERATED(context_ti);
2847
2848     ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_radio_type,
2849                              tvb, 0, 0, p_mac_lte_info->radioType);
2850     PROTO_ITEM_SET_GENERATED(ti);
2851
2852     ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_direction,
2853                              tvb, 0, 0, p_mac_lte_info->direction);
2854     PROTO_ITEM_SET_GENERATED(ti);
2855
2856     if (p_mac_lte_info->ueid != 0) {
2857         ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_ueid,
2858                                  tvb, 0, 0, p_mac_lte_info->ueid);
2859         PROTO_ITEM_SET_GENERATED(ti);
2860     }
2861
2862     /* There are several out-of-band MAC events that may be indicated in the context info. */
2863     /* Handle them here */
2864     if (p_mac_lte_info->length == 0) {
2865         proto_item *preamble_ti;
2866         proto_tree *preamble_tree;
2867
2868         switch (p_mac_lte_info->oob_event) {
2869             case ltemac_send_preamble:
2870                 preamble_ti = proto_tree_add_item(mac_lte_tree, hf_mac_lte_oob_send_preamble,
2871                                                   tvb, 0, 0, FALSE);
2872                 preamble_tree = proto_item_add_subtree(preamble_ti, ett_mac_lte_oob);
2873                 PROTO_ITEM_SET_GENERATED(ti);
2874
2875                 ti = proto_tree_add_uint(preamble_tree, hf_mac_lte_context_rapid,
2876                                          tvb, 0, 0, p_mac_lte_info->rapid);
2877                 PROTO_ITEM_SET_GENERATED(ti);
2878
2879                 ti = proto_tree_add_uint(preamble_tree, hf_mac_lte_context_rach_attempt_number,
2880                                          tvb, 0, 0, p_mac_lte_info->rach_attempt_number);
2881                 PROTO_ITEM_SET_GENERATED(ti);
2882
2883                 /* Info column */
2884                 write_pdu_label_and_info(pdu_ti, preamble_ti, pinfo,
2885                                          "RACH Preamble sent for UE %u (RAPID=%u, attempt=%u)",
2886                                          p_mac_lte_info->ueid, p_mac_lte_info->rapid, p_mac_lte_info->rach_attempt_number);
2887
2888                 /* Add expert info (a note, unless attempt > 1) */
2889                 expert_add_info_format(pinfo, ti, PI_SEQUENCE,
2890                                        (p_mac_lte_info->rach_attempt_number > 1) ? PI_WARN : PI_NOTE,
2891                                        "RACH Preamble sent for UE %u (RAPID=%u, attempt=%u)",
2892                                        p_mac_lte_info->ueid, p_mac_lte_info->rapid,
2893                                        p_mac_lte_info->rach_attempt_number);
2894                 break;
2895             case ltemac_send_sr:
2896                 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_rnti,
2897                                          tvb, 0, 0, p_mac_lte_info->rnti);
2898                 PROTO_ITEM_SET_GENERATED(ti);
2899
2900                 ti = proto_tree_add_item(mac_lte_tree, hf_mac_lte_oob_send_sr,
2901                                          tvb, 0, 0, FALSE);
2902                 PROTO_ITEM_SET_GENERATED(ti);
2903
2904                 /* Info column */
2905                 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
2906                                          "Scheduling Request sent for UE %u (C-RNTI=%u)",
2907                                          p_mac_lte_info->ueid, p_mac_lte_info->rnti);
2908
2909                 /* Add expert info (an note) */
2910                 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_NOTE,
2911                                        "Scheduling Request send for UE %u (RNTI %u)",
2912                                        p_mac_lte_info->ueid, p_mac_lte_info->rnti);
2913
2914                 /* Update SR status */
2915                 if (global_mac_lte_track_sr) {
2916                     TrackSRInfo(SR_Request, pinfo, mac_lte_tree, tvb, p_mac_lte_info->rnti, ti);
2917                 }
2918                 break;
2919             case ltemac_sr_failure:
2920                 ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_rnti,
2921                                          tvb, 0, 0, p_mac_lte_info->rnti);
2922                 PROTO_ITEM_SET_GENERATED(ti);
2923
2924                 ti = proto_tree_add_item(mac_lte_tree, hf_mac_lte_oob_sr_failure,
2925                                          tvb, 0, 0, FALSE);
2926                 PROTO_ITEM_SET_GENERATED(ti);
2927
2928                 /* Info column */
2929                 write_pdu_label_and_info(pdu_ti, NULL, pinfo,
2930                                          "Scheduling Request FAILED for UE %u (C-RNTI=%u)",
2931                                          p_mac_lte_info->ueid,
2932                                          p_mac_lte_info->rnti);
2933
2934                 /* Add expert info (an error) */
2935                 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_ERROR,
2936                                        "Scheduling Request failed for UE %u (RNTI %u)",
2937                                        p_mac_lte_info->ueid,
2938                                        p_mac_lte_info->rnti);
2939
2940                 /* Update SR status */
2941                 if (global_mac_lte_track_sr) {
2942                     TrackSRInfo(SR_Failure, pinfo, mac_lte_tree, tvb, p_mac_lte_info->rnti, ti);
2943                 }
2944
2945                 break;
2946         }
2947
2948         /* Our work here is done */
2949         return;
2950     }
2951
2952
2953     ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_subframe_number,
2954                              tvb, 0, 0, p_mac_lte_info->subframeNumber);
2955     PROTO_ITEM_SET_GENERATED(ti);
2956     if (p_mac_lte_info->subframeNumber > 9) {
2957         expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
2958                                "Subframe number was out of range - using max (9) instead");
2959         p_mac_lte_info->subframeNumber = 9;
2960     }
2961
2962     if (p_mac_lte_info->rntiType != NO_RNTI) {
2963         ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_rnti,
2964                                  tvb, 0, 0, p_mac_lte_info->rnti);
2965         PROTO_ITEM_SET_GENERATED(ti);
2966     }
2967
2968     ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_rnti_type,
2969                              tvb, 0, 0, p_mac_lte_info->rntiType);
2970     PROTO_ITEM_SET_GENERATED(ti);
2971
2972     ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_predefined_frame,
2973                              tvb, 0, 0, p_mac_lte_info->isPredefinedData);
2974     if (p_mac_lte_info->isPredefinedData) {
2975         PROTO_ITEM_SET_GENERATED(ti);
2976     }
2977     else {
2978         PROTO_ITEM_SET_HIDDEN(ti);
2979     }
2980
2981     ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_length,
2982                              tvb, 0, 0, p_mac_lte_info->length);
2983     PROTO_ITEM_SET_GENERATED(ti);
2984     /* Infer uplink grant size */
2985     if (p_mac_lte_info->direction == DIRECTION_UPLINK) {
2986         ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_ul_grant_size,
2987                                  tvb, 0, 0, p_mac_lte_info->length);
2988         PROTO_ITEM_SET_GENERATED(ti);
2989     }
2990
2991     /* Retx count goes in top-level tree to make it more visible */
2992     if (p_mac_lte_info->reTxCount) {
2993         retx_ti = proto_tree_add_uint(mac_lte_tree, hf_mac_lte_context_retx_count,
2994                                  tvb, 0, 0, p_mac_lte_info->reTxCount);
2995         PROTO_ITEM_SET_GENERATED(retx_ti);
2996
2997         if (p_mac_lte_info->reTxCount >= global_mac_lte_retx_counter_trigger) {
2998             expert_add_info_format(pinfo, retx_ti, PI_SEQUENCE, PI_ERROR,
2999                                    "UE %u: UL MAC frame ReTX no. %u",
3000                                    p_mac_lte_info->ueid, p_mac_lte_info->reTxCount);
3001         }
3002     }
3003
3004     if (p_mac_lte_info->crcStatusValid) {
3005         ti = proto_tree_add_uint(context_tree, hf_mac_lte_context_crc_status,
3006                                  tvb, 0, 0, p_mac_lte_info->detailed_phy_info.dl_info.crc_status);
3007         PROTO_ITEM_SET_GENERATED(ti);
3008         if (p_mac_lte_info->detailed_phy_info.dl_info.crc_status != TRUE) {
3009             expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
3010                                    "%s Frame has CRC error",
3011                                    (p_mac_lte_info->direction == DIRECTION_UPLINK) ? "UL" : "DL");
3012             write_pdu_label_and_info(pdu_ti, NULL, pinfo,
3013                                      "%s: <CRC FAILURE> UEId=%u %s=%u ",
3014                                      (p_mac_lte_info->direction == DIRECTION_UPLINK) ? "UL" : "DL",
3015                                      p_mac_lte_info->ueid,
3016                                      val_to_str_const(p_mac_lte_info->rntiType, rnti_type_vals,
3017                                                       "Unknown RNTI type"),
3018                                      p_mac_lte_info->rnti);
3019         }
3020     }
3021
3022     /* May also have extra Physical layer attributes set for this frame */
3023     show_extra_phy_parameters(pinfo, tvb, mac_lte_tree, p_mac_lte_info);
3024
3025     /* Set context-info parts of tap struct */
3026     tap_info.rnti = p_mac_lte_info->rnti;
3027     tap_info.ueid = p_mac_lte_info->ueid;
3028     tap_info.rntiType = p_mac_lte_info->rntiType;
3029     tap_info.isPredefinedData = p_mac_lte_info->isPredefinedData;
3030     tap_info.isPHYRetx = (p_mac_lte_info->reTxCount >= 1);
3031     tap_info.crcStatusValid = p_mac_lte_info->crcStatusValid;
3032     tap_info.crcStatus = p_mac_lte_info->detailed_phy_info.dl_info.crc_status;
3033     tap_info.direction = p_mac_lte_info->direction;
3034
3035     /* Also set total number of bytes (won't be used for UL/DL-SCH) */
3036     tap_info.single_number_of_bytes = tvb_length_remaining(tvb, offset);
3037
3038     /* If we know its predefined data, don't try to decode any further */
3039     if (p_mac_lte_info->isPredefinedData) {
3040         proto_tree_add_item(mac_lte_tree, hf_mac_lte_predefined_pdu, tvb, offset, -1, FALSE);
3041         write_pdu_label_and_info(pdu_ti, NULL, pinfo,
3042                                  "Predefined data (%u bytes)",
3043                                  tvb_length_remaining(tvb, offset));
3044
3045         /* Queue tap info */
3046         if (!pinfo->in_error_pkt) {
3047             tap_queue_packet(mac_lte_tap, pinfo, &tap_info);
3048         }
3049
3050         return;
3051     }
3052
3053     /* IF CRC status failed, just do decode as raw bytes */
3054     if (!global_mac_lte_dissect_crc_failures &&
3055         (p_mac_lte_info->crcStatusValid && !p_mac_lte_info->detailed_phy_info.dl_info.crc_status)) {
3056
3057         proto_tree_add_item(mac_lte_tree, hf_mac_lte_raw_pdu, tvb, offset, -1, FALSE);
3058         write_pdu_label_and_info(pdu_ti, NULL, pinfo, "Raw data (%u bytes)", tvb_length_remaining(tvb, offset));
3059
3060         /* Queue tap info.
3061            TODO: unfortunately DL retx detection won't get done if we return here... */
3062         if (!pinfo->in_error_pkt) {
3063             tap_queue_packet(mac_lte_tap, pinfo, &tap_info);
3064         }
3065
3066         return;
3067     }
3068
3069     /* Reset this counter */
3070     s_number_of_rlc_pdus_shown = 0;
3071
3072     /* Dissect the MAC PDU itself. Format depends upon RNTI type. */
3073     switch (p_mac_lte_info->rntiType) {
3074
3075         case P_RNTI:
3076             /* PCH PDU */
3077             dissect_pch(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info->direction);
3078             break;
3079
3080         case RA_RNTI:
3081             /* RAR PDU */
3082             dissect_rar(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info, &tap_info);
3083             break;
3084
3085         case C_RNTI:
3086         case SPS_RNTI:
3087             /* Can be UL-SCH or DL-SCH */
3088             dissect_ulsch_or_dlsch(tvb, pinfo, mac_lte_tree, pdu_ti, offset,
3089                                    p_mac_lte_info->direction, p_mac_lte_info, &tap_info,
3090                                    retx_ti, context_tree);
3091             break;
3092
3093         case SI_RNTI:
3094             /* BCH over DL-SCH */
3095             dissect_bch(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info);
3096             break;
3097
3098         case NO_RNTI:
3099             /* Must be BCH over BCH... */
3100             dissect_bch(tvb, pinfo, mac_lte_tree, pdu_ti, offset, p_mac_lte_info);
3101             break;
3102
3103
3104         default:
3105             break;
3106     }
3107
3108     /* Queue tap info */
3109     tap_queue_packet(mac_lte_tap, pinfo, &tap_info);
3110 }
3111
3112
3113
3114
3115 /* Initializes the hash table and the mem_chunk area each time a new
3116  * file is loaded or re-loaded in wireshark */
3117 static void
3118 mac_lte_init_protocol(void)
3119 {
3120     /* Destroy any existing tables. */
3121     if (mac_lte_msg3_hash) {
3122         g_hash_table_destroy(mac_lte_msg3_hash);
3123     }
3124     if (mac_lte_cr_result_hash) {
3125         g_hash_table_destroy(mac_lte_cr_result_hash);
3126     }
3127
3128     if (mac_lte_dl_harq_hash) {
3129         g_hash_table_destroy(mac_lte_dl_harq_hash);
3130     }
3131     if (mac_lte_dl_harq_result_hash) {
3132         g_hash_table_destroy(mac_lte_dl_harq_result_hash);
3133     }
3134     if (mac_lte_ul_harq_hash) {
3135         g_hash_table_destroy(mac_lte_ul_harq_hash);
3136     }
3137     if (mac_lte_ul_harq_result_hash) {
3138         g_hash_table_destroy(mac_lte_ul_harq_result_hash);
3139     }
3140     if (mac_lte_ue_sr_state) {
3141         g_hash_table_destroy(mac_lte_ue_sr_state);
3142     }
3143     if (mac_lte_sr_request_hash) {
3144         g_hash_table_destroy(mac_lte_sr_request_hash);
3145     }
3146
3147     /* Now create them over */
3148     mac_lte_msg3_hash = g_hash_table_new(mac_lte_rnti_hash_func, mac_lte_rnti_hash_equal);
3149     mac_lte_cr_result_hash = g_hash_table_new(mac_lte_framenum_hash_func, mac_lte_framenum_hash_equal);
3150
3151     mac_lte_dl_harq_hash = g_hash_table_new(mac_lte_rnti_hash_func, mac_lte_rnti_hash_equal);
3152     mac_lte_dl_harq_result_hash = g_hash_table_new(mac_lte_framenum_hash_func, mac_lte_framenum_hash_equal);
3153
3154     mac_lte_ul_harq_hash = g_hash_table_new(mac_lte_rnti_hash_func, mac_lte_rnti_hash_equal);
3155     mac_lte_ul_harq_result_hash = g_hash_table_new(mac_lte_framenum_hash_func, mac_lte_framenum_hash_equal);
3156
3157     mac_lte_ue_sr_state = g_hash_table_new(mac_lte_rnti_hash_func, mac_lte_rnti_hash_equal);
3158     mac_lte_sr_request_hash = g_hash_table_new(mac_lte_framenum_hash_func, mac_lte_framenum_hash_equal);
3159 }
3160
3161
3162 static void* lcid_drb_mapping_copy_cb(void* dest, const void* orig, unsigned len _U_) 
3163 {
3164     const lcid_drb_mapping_t *o = orig;
3165     lcid_drb_mapping_t *d = dest;
3166
3167     /* Copy all items over */
3168     d->lcid = o->lcid;
3169     d->drbid = o->drbid;
3170     d->channel_type = o->channel_type;
3171
3172     return d;
3173 }
3174
3175
3176
3177 void proto_register_mac_lte(void)
3178 {
3179     static hf_register_info hf[] =
3180     {
3181         /**********************************/
3182         /* Items for decoding context     */
3183         { &hf_mac_lte_context,
3184             { "Context",
3185               "mac-lte.context", FT_STRING, BASE_NONE, NULL, 0x0,
3186               NULL, HFILL
3187             }
3188         },
3189         { &hf_mac_lte_context_radio_type,
3190             { "Radio Type",
3191               "mac-lte.radio-type", FT_UINT8, BASE_DEC, VALS(radio_type_vals), 0x0,
3192               NULL, HFILL
3193             }
3194         },
3195         { &hf_mac_lte_context_direction,
3196             { "Direction",
3197               "mac-lte.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
3198               "Direction of message", HFILL
3199             }
3200         },
3201         { &hf_mac_lte_context_rnti,
3202             { "RNTI",
3203               "mac-lte.rnti", FT_UINT16, BASE_DEC, 0, 0x0,
3204               "RNTI associated with message", HFILL
3205             }
3206         },
3207         { &hf_mac_lte_context_rnti_type,
3208             { "RNTI Type",
3209               "mac-lte.rnti-type", FT_UINT8, BASE_DEC, VALS(rnti_type_vals), 0x0,
3210               "Type of RNTI associated with message", HFILL
3211             }
3212         },
3213         { &hf_mac_lte_context_ueid,
3214             { "UEId",
3215               "mac-lte.ueid", FT_UINT16, BASE_DEC, 0, 0x0,
3216               "User Equipment Identifier associated with message", HFILL
3217             }
3218         },
3219         { &hf_mac_lte_context_subframe_number,
3220             { "Subframe",
3221               "mac-lte.subframe", FT_UINT16, BASE_DEC, 0, 0x0,
3222               "Subframe number associated with message", HFILL
3223             }
3224         },
3225         { &hf_mac_lte_context_grant_subframe_number,
3226             { "Grant Subframe",
3227               "mac-lte.grant-subframe", FT_UINT16, BASE_DEC, 0, 0x0,
3228               "Subframe grant for this PDU was received", HFILL
3229             }
3230         },
3231         { &hf_mac_lte_context_predefined_frame,
3232             { "Predefined frame",
3233               "mac-lte.is-predefined-frame", FT_UINT8, BASE_DEC, VALS(predefined_frame_vals), 0x0,
3234               "Predefined test frame (or real MAC PDU)", HFILL
3235             }
3236         },
3237         { &hf_mac_lte_context_length,
3238             { "Length of frame",
3239               "mac-lte.length", FT_UINT8, BASE_DEC, 0, 0x0,
3240               "Original length of frame (including SDUs and padding)", HFILL
3241             }
3242         },
3243         { &hf_mac_lte_context_ul_grant_size,
3244             { "Uplink grant size",
3245               "mac-lte.ul-grant-size", FT_UINT8, BASE_DEC, 0, 0x0,
3246               "Uplink grant size (in bytes)", HFILL
3247             }
3248         },
3249         { &hf_mac_lte_context_bch_transport_channel,
3250             { "Transport channel",
3251               "mac-lte.bch-transport-channel", FT_UINT8, BASE_DEC, VALS(bch_transport_channel_vals), 0x0,
3252               "Transport channel BCH data was carried on", HFILL
3253             }
3254         },
3255         { &hf_mac_lte_context_retx_count,
3256             { "ReTX count",
3257               "mac-lte.retx-count", FT_UINT8, BASE_DEC, 0, 0x0,
3258               "Number of times this PDU has been retransmitted", HFILL
3259             }
3260         },
3261         { &hf_mac_lte_context_crc_status,
3262             { "CRC Status",
3263               "mac-lte.crc-status", FT_UINT8, BASE_DEC, VALS(crc_status_vals), 0x0,
3264               "CRC Status as reported by PHY", HFILL
3265             }
3266         },
3267         { &hf_mac_lte_context_rapid,
3268             { "RAPID",
3269               "mac-lte.preamble-sent.rapid", FT_UINT8, BASE_DEC, 0, 0x0,
3270               "RAPID sent in RACH preamble", HFILL
3271             }
3272         },
3273         { &hf_mac_lte_context_rach_attempt_number,
3274             { "RACH Attempt Number",
3275               "mac-lte.preamble-sent.attempt", FT_UINT8, BASE_DEC, 0, 0x0,
3276               "RACH attempt number", HFILL
3277             }
3278         },
3279
3280         /* Extra PHY context */
3281         { &hf_mac_lte_context_phy_ul,
3282             { "UL PHY attributes",
3283               "mac-lte.ul-phy", FT_STRING, BASE_NONE, 0, 0x0,
3284               NULL, HFILL
3285             }
3286         },
3287         { &hf_mac_lte_context_phy_ul_modulation_type,
3288             { "Modulation type",
3289               "mac-lte.ul-phy.modulation-type", FT_UINT8, BASE_DEC, VALS(modulation_type_vals), 0x0,
3290               NULL, HFILL
3291             }
3292         },
3293         { &hf_mac_lte_context_phy_ul_tbs_index,
3294             { "TBs Index",
3295               "mac-lte.ul-phy.tbs-index", FT_UINT8, BASE_DEC, 0, 0x0,
3296               NULL, HFILL
3297             }
3298         },
3299         { &hf_mac_lte_context_phy_ul_resource_block_length,
3300             { "Resource Block Length",
3301               "mac-lte.ul-phy.resource-block-length", FT_UINT8, BASE_DEC, 0, 0x0,
3302               NULL, HFILL
3303             }
3304         },
3305         { &hf_mac_lte_context_phy_ul_resource_block_start,
3306             { "Resource Block Start",
3307               "mac-lte.ul-phy.resource-block-start", FT_UINT8, BASE_DEC, 0, 0x0,
3308               NULL, HFILL
3309             }
3310         },
3311
3312
3313         { &hf_mac_lte_context_phy_dl,
3314             { "DL PHY attributes",
3315               "mac-lte.dl-phy", FT_STRING, BASE_NONE, 0, 0x0,
3316               NULL, HFILL
3317             }
3318         },
3319         { &hf_mac_lte_context_phy_dl_dci_format,
3320             { "DCI format",
3321               "mac-lte.dl-phy.dci-format", FT_UINT8, BASE_DEC, VALS(dci_format_vals), 0x0,
3322               NULL, HFILL
3323             }
3324         },
3325         { &hf_mac_lte_context_phy_dl_resource_allocation_type,
3326             { "Resource Allocation Type",
3327               "mac-lte.dl-phy.resource-allocation-type", FT_UINT8, BASE_DEC, 0, 0x0,
3328               NULL, HFILL
3329             }
3330         },
3331         { &hf_mac_lte_context_phy_dl_aggregation_level,
3332             { "Aggregation Level",
3333               "mac-lte.dl-phy.aggregation-level", FT_UINT8, BASE_DEC, VALS(aggregation_level_vals), 0x0,
3334               NULL, HFILL
3335             }
3336         },
3337         { &hf_mac_lte_context_phy_dl_mcs_index,
3338             { "MCS Index",
3339               "mac-lte.dl-phy.mcs-index", FT_UINT8, BASE_DEC, 0, 0x0,
3340               NULL, HFILL
3341             }
3342         },
3343         { &hf_mac_lte_context_phy_dl_redundancy_version_index,
3344             { "RV Index",
3345               "mac-lte.dl-phy.rv-index", FT_UINT8, BASE_DEC, 0, 0x0,
3346               NULL, HFILL
3347             }
3348         },
3349         { &hf_mac_lte_context_phy_dl_resource_block_length,
3350             { "RB Length",
3351               "mac-lte.dl-phy.rb-length", FT_UINT8, BASE_DEC, 0, 0x0,
3352               NULL, HFILL
3353             }
3354         },
3355         { &hf_mac_lte_context_phy_dl_crc_status,
3356             { "CRC Status",
3357               "mac-lte.dl-phy.crc-status", FT_UINT8, BASE_DEC, VALS(crc_status_vals), 0x0,
3358               NULL, HFILL
3359             }
3360         },
3361
3362         /* Out-of-band events */
3363         { &hf_mac_lte_oob_send_preamble,
3364             { "PRACH: ",
3365               "mac-lte.preamble-sent", FT_STRING, BASE_NONE, NULL, 0x0,
3366               NULL, HFILL
3367             }
3368         },
3369         { &hf_mac_lte_oob_send_sr,
3370             { "Scheduling Request sent",
3371               "mac-lte.sr-req", FT_NONE, BASE_NONE, NULL, 0x0,
3372               NULL, HFILL
3373             }
3374         },
3375         { &hf_mac_lte_oob_sr_failure,
3376             { "Scheduling Request failure",
3377               "mac-lte.sr-failure", FT_NONE, BASE_NONE, NULL, 0x0,
3378               NULL, HFILL
3379             }
3380         },
3381
3382         /*******************************************/
3383         /* MAC shared channel header fields        */
3384         { &hf_mac_lte_ulsch,
3385             { "UL-SCH",
3386               "mac-lte.ulsch", FT_STRING, BASE_NONE, NULL, 0x0,
3387               NULL, HFILL
3388             }
3389         },
3390         { &hf_mac_lte_ulsch_header,
3391             { "UL-SCH Header",
3392               "mac-lte.ulsch.header", FT_STRING, BASE_NONE, NULL, 0x0,
3393               NULL, HFILL
3394             }
3395         },
3396         { &hf_mac_lte_dlsch_header,
3397             { "DL-SCH Header",
3398               "mac-lte.dlsch.header", FT_STRING, BASE_NONE, NULL, 0x0,
3399               NULL, HFILL
3400             }
3401         },
3402         { &hf_mac_lte_dlsch,
3403             { "DL-SCH",
3404               "mac-lte.dlsch", FT_STRING, BASE_NONE, NULL, 0x0,
3405               NULL, HFILL
3406             }
3407         },
3408         { &hf_mac_lte_sch_subheader,
3409             { "SCH sub-header",
3410               "mac-lte.sch.subheader", FT_STRING, BASE_NONE, NULL, 0x0,
3411               NULL, HFILL
3412             }
3413         },
3414         { &hf_mac_lte_sch_reserved,
3415             { "SCH reserved bits",
3416               "mac-lte.sch.reserved", FT_UINT8, BASE_HEX, NULL, 0xc0,
3417               NULL, HFILL
3418             }
3419         },
3420         { &hf_mac_lte_sch_extended,
3421             { "Extension",
3422               "mac-lte.sch.extended", FT_UINT8, BASE_HEX, 0, 0x20,
3423               "Extension - i.e. further headers after this one", HFILL
3424             }
3425         },
3426         { &hf_mac_lte_dlsch_lcid,
3427             { "LCID",
3428               "mac-lte.dlsch.lcid", FT_UINT8, BASE_HEX, VALS(dlsch_lcid_vals), 0x1f,
3429               "DL-SCH Logical Channel Identifier", HFILL
3430             }
3431         },
3432         { &hf_mac_lte_ulsch_lcid,
3433             { "LCID",
3434               "mac-lte.ulsch.lcid", FT_UINT8, BASE_HEX, VALS(ulsch_lcid_vals), 0x1f,
3435               "UL-SCH Logical Channel Identifier", HFILL
3436             }
3437         },
3438         { &hf_mac_lte_sch_format,
3439             { "Format",
3440               "mac-lte.sch.format", FT_UINT8, BASE_HEX, VALS(format_vals), 0x80,
3441               NULL, HFILL
3442             }
3443         },
3444         { &hf_mac_lte_sch_length,
3445             { "Length",
3446               "mac-lte.sch.length", FT_UINT16, BASE_DEC, 0, 0x0,
3447               "Length of MAC SDU or MAC control element", HFILL
3448             }
3449         },
3450         { &hf_mac_lte_sch_header_only,
3451             { "MAC PDU Header only",
3452               "mac-lte.sch.header-only", FT_UINT8, BASE_DEC, VALS(header_only_vals), 0x0,
3453               NULL, HFILL
3454             }
3455         },
3456
3457         /********************************/
3458         /* Data                         */
3459         { &hf_mac_lte_sch_sdu,
3460             { "SDU",
3461               "mac-lte.sch.sdu", FT_BYTES, BASE_NONE, 0, 0x0,
3462               "Shared channel SDU", HFILL
3463             }
3464         },
3465         { &hf_mac_lte_bch_pdu,
3466             { "BCH PDU",
3467               "mac-lte.bch.pdu", FT_BYTES, BASE_NONE, 0, 0x0,
3468               NULL, HFILL
3469             }
3470         },
3471         { &hf_mac_lte_pch_pdu,
3472             { "PCH PDU",
3473               "mac-lte.pch.pdu", FT_BYTES, BASE_NONE, 0, 0x0,
3474               NULL, HFILL
3475             }
3476         },
3477         { &hf_mac_lte_predefined_pdu,
3478             { "Predefined data",
3479               "mac-lte.predefined-data", FT_BYTES, BASE_NONE, 0, 0x0,
3480               "Predefined test data", HFILL
3481             }
3482         },
3483         { &hf_mac_lte_raw_pdu,
3484             { "Raw data",
3485               "mac-lte.raw-data", FT_BYTES, BASE_NONE, 0, 0x0,
3486               "Raw bytes of PDU (e.g. if CRC failed)", HFILL
3487             }
3488         },
3489         { &hf_mac_lte_padding_data,
3490             { "Padding data",
3491               "mac-lte.padding-data", FT_BYTES, BASE_NONE, 0, 0x0,
3492               NULL, HFILL
3493             }
3494         },
3495         { &hf_mac_lte_padding_length,
3496             { "Padding length",
3497               "mac-lte.padding-length", FT_INT32, BASE_DEC, 0, 0x0,
3498               "Length of padding data not included at end of frame", HFILL
3499             }
3500         },
3501
3502
3503
3504         /*********************************/
3505         /* RAR fields                    */
3506         { &hf_mac_lte_rar,
3507             { "RAR",
3508               "mac-lte.rar", FT_NONE, BASE_NONE, NULL, 0x0,
3509               NULL, HFILL
3510             }
3511         },
3512         { &hf_mac_lte_rar_headers,
3513             { "RAR Headers",
3514               "mac-lte.rar.headers", FT_STRING, BASE_NONE, NULL, 0x0,
3515               NULL, HFILL
3516             }
3517         },
3518         { &hf_mac_lte_rar_header,
3519             { "RAR Header",
3520               "mac-lte.rar.header", FT_STRING, BASE_NONE, NULL, 0x0,
3521               NULL, HFILL
3522             }
3523         },
3524         { &hf_mac_lte_rar_extension,
3525             { "Extension",
3526               "mac-lte.rar.e", FT_UINT8, BASE_HEX, 0, 0x80,
3527               "Extension - i.e. further RAR headers after this one", HFILL
3528             }
3529         },
3530         { &hf_mac_lte_rar_t,
3531             { "Type",
3532               "mac-lte.rar.t", FT_UINT8, BASE_HEX, VALS(rar_type_vals), 0x40,
3533               "Type field indicating whether the payload is RAPID or BI", HFILL
3534             }
3535         },
3536         { &hf_mac_lte_rar_bi,
3537             { "BI",
3538               "mac-lte.rar.bi", FT_UINT8, BASE_HEX, VALS(rar_bi_vals), 0x0f,
3539               "Backoff Indicator (ms)", HFILL
3540             }
3541         },
3542         { &hf_mac_lte_rar_rapid,
3543             { "RAPID",
3544               "mac-lte.rar.rapid", FT_UINT8, BASE_HEX_DEC, 0, 0x3f,
3545               "Random Access Preamble IDentifier", HFILL
3546             }
3547         },
3548         { &hf_mac_lte_rar_reserved,
3549             { "Reserved",
3550               "mac-lte.rar.reserved", FT_UINT8, BASE_HEX, 0, 0x30,
3551               "Reserved bits in RAR header - should be 0", HFILL
3552             }
3553         },
3554
3555         { &hf_mac_lte_rar_body,
3556             { "RAR Body",
3557               "mac-lte.rar.body", FT_STRING, BASE_NONE, NULL, 0x0,
3558               NULL, HFILL
3559             }
3560         },
3561         { &hf_mac_lte_rar_reserved2,
3562             { "Reserved",
3563               "mac-lte.rar.reserved2", FT_UINT8, BASE_HEX, 0, 0x80,
3564               "Reserved bit in RAR body - should be 0", HFILL
3565             }
3566         },
3567         { &hf_mac_lte_rar_ta,
3568             { "Timing Advance",
3569               "mac-lte.rar.ta", FT_UINT16, BASE_DEC, 0, 0x7ff0,
3570               "Required adjustment to uplink transmission timing", HFILL
3571             }
3572         },
3573         { &hf_mac_lte_rar_ul_grant,
3574             { "UL Grant",
3575               "mac-lte.rar.ul-grant", FT_UINT24, BASE_DEC, 0, 0x0fffff,
3576               "Size of UL Grant", HFILL
3577             }
3578         },
3579         { &hf_mac_lte_rar_ul_grant_hopping,
3580             { "Hopping Flag",
3581               "mac-lte.rar.ul-grant.hopping", FT_UINT8, BASE_DEC, 0, 0x08,
3582               NULL, HFILL
3583             }
3584         },
3585         { &hf_mac_lte_rar_ul_grant_fsrba,
3586             { "Fixed sized resource block assignment",
3587               "mac-lte.rar.ul-grant.fsrba", FT_UINT16, BASE_DEC, 0, 0x07fe,
3588               NULL, HFILL
3589             }
3590         },
3591         { &hf_mac_lte_rar_ul_grant_tmcs,
3592             { "Truncated Modulation and coding scheme",
3593               "mac-lte.rar.ul-grant.tmcs", FT_UINT16, BASE_DEC, 0, 0x01e0,
3594               NULL, HFILL
3595             }
3596         },
3597         { &hf_mac_lte_rar_ul_grant_tcsp,
3598             { "TPC command for scheduled PUSCH",
3599               "mac-lte.rar.ul-grant.tcsp", FT_UINT8, BASE_DEC, 0, 0x01c,
3600               NULL, HFILL
3601             }
3602         },
3603         { &hf_mac_lte_rar_ul_grant_ul_delay,
3604             { "UL Delay",
3605               "mac-lte.rar.ul-grant.ul-delay", FT_UINT8, BASE_DEC, 0, 0x02,
3606               NULL, HFILL
3607             }
3608         },
3609         { &hf_mac_lte_rar_ul_grant_cqi_request,
3610             { "CQI Request",
3611               "mac-lte.rar.ul-grant.cqi-request", FT_UINT8, BASE_DEC, 0, 0x01,
3612               NULL, HFILL
3613             }
3614         },
3615         { &hf_mac_lte_rar_temporary_crnti,
3616             { "Temporary C-RNTI",
3617               "mac-lte.rar.temporary-crnti", FT_UINT16, BASE_DEC, 0, 0x0,
3618               NULL, HFILL
3619             }
3620         },
3621
3622         /**********************/
3623         /* Control PDU fields */
3624         { &hf_mac_lte_control_bsr,
3625             { "BSR",
3626               "mac-lte.control.bsr", FT_STRING, BASE_NONE, 0, 0x0,
3627               "Buffer Status Report", HFILL
3628             }
3629         },
3630         { &hf_mac_lte_control_bsr_lcg_id,
3631             { "Logical Channel Group ID",
3632               "mac-lte.control.bsr.lcg-id", FT_UINT8, BASE_DEC, 0, 0xc0,
3633               NULL, HFILL
3634             }
3635         },
3636         { &hf_mac_lte_control_short_bsr_buffer_size,
3637             { "Buffer Size",
3638               "mac-lte.control.bsr.buffer-size", FT_UINT8, BASE_DEC, VALS(buffer_size_vals), 0x3f,
3639               "Buffer Size available in all channels in group", HFILL
3640             }
3641         },
3642         { &hf_mac_lte_control_long_bsr_buffer_size_0,
3643             { "Buffer Size 0",
3644               "mac-lte.control.bsr.buffer-size-0", FT_UINT8, BASE_DEC, VALS(buffer_size_vals), 0xfc,
3645               "Buffer Size available in logical channel group 0", HFILL
3646             }
3647         },
3648         { &hf_mac_lte_control_long_bsr_buffer_size_1,
3649             { "Buffer Size 1",
3650               "mac-lte.control.bsr.buffer-size-1", FT_UINT16, BASE_DEC, VALS(buffer_size_vals), 0x03f0,
3651               "Buffer Size available in logical channel group 1", HFILL
3652             }
3653         },
3654         { &hf_mac_lte_control_long_bsr_buffer_size_2,
3655             { "Buffer Size 2",
3656               "mac-lte.control.bsr.buffer-size-2", FT_UINT16, BASE_DEC, VALS(buffer_size_vals), 0x0fc0,
3657               "Buffer Size available in logical channel group 2", HFILL
3658             }
3659         },
3660         { &hf_mac_lte_control_long_bsr_buffer_size_3,
3661             { "Buffer Size 3",
3662               "mac-lte.control.bsr.buffer-size-3", FT_UINT8, BASE_DEC, VALS(buffer_size_vals), 0x3f,
3663               "Buffer Size available in logical channel group 3", HFILL
3664             }
3665         },
3666         { &hf_mac_lte_control_crnti,
3667             { "C-RNTI",
3668               "mac-lte.control.crnti", FT_UINT16, BASE_DEC, 0, 0x0,
3669               "C-RNTI for the UE", HFILL
3670             }
3671         },
3672         { &hf_mac_lte_control_timing_advance,
3673             { "Timing Advance",
3674               "mac-lte.control.timing-advance", FT_UINT8, BASE_DEC, 0, 0x3f,
3675               "Timing Advance (0-1282 - see 36.213, 4.2.3)", HFILL
3676             }
3677         },
3678         { &hf_mac_lte_control_timing_advance_reserved,
3679             { "Reserved",
3680               "mac-lte.control.timing-advance.reserved", FT_UINT8, BASE_DEC, 0, 0xc0,
3681               "Reserved bits", HFILL
3682             }
3683         },
3684         { &hf_mac_lte_control_ue_contention_resolution,
3685             { "UE Contention Resolution",
3686               "mac-lte.control.ue-contention-resolution", FT_STRING, BASE_NONE, 0, 0x0,
3687               NULL, HFILL
3688             }
3689         },
3690         { &hf_mac_lte_control_ue_contention_resolution_identity,
3691             { "UE Contention Resolution Identity",
3692               "mac-lte.control.ue-contention-resolution.identity", FT_BYTES, BASE_NONE, 0, 0x0,
3693               NULL, HFILL
3694             }
3695         },
3696         { &hf_mac_lte_control_ue_contention_resolution_msg3,
3697             { "Msg3",
3698               "mac-lte.control.ue-contention-resolution.msg3", FT_FRAMENUM, BASE_NONE, 0, 0x0,
3699               NULL, HFILL
3700             }
3701         },
3702         { &hf_mac_lte_control_ue_contention_resolution_msg3_matched,
3703             { "UE Contention Resolution Matches Msg3",
3704               "mac-lte.control.ue-contention-resolution.matches-msg3", FT_BOOLEAN, BASE_NONE, 0, 0x0,
3705               NULL, HFILL
3706             }
3707         },
3708         { &hf_mac_lte_control_ue_contention_resolution_time_since_msg3,
3709             { "Time since Msg3",
3710               "mac-lte.control.ue-contention-resolution.time-since-msg3", FT_UINT32, BASE_DEC, 0, 0x0,
3711               "Time in ms since corresponding Msg3", HFILL
3712             }
3713         },
3714
3715         { &hf_mac_lte_control_power_headroom,
3716             { "Power Headroom",
3717               "mac-lte.control.power-headroom", FT_STRING, BASE_NONE, 0, 0x0,
3718               NULL, HFILL
3719             }
3720         },
3721         { &hf_mac_lte_control_power_headroom_reserved,
3722             { "Reserved",
3723               "mac-lte.control.power-headroom.reserved", FT_UINT8, BASE_DEC, 0, 0xc0,
3724               "Reserved bits, should be 0", HFILL
3725             }
3726         },
3727         { &hf_mac_lte_control_power_headroom_level,
3728             { "Power Headroom Level",
3729               "mac-lte.control.power-headroom.level", FT_UINT8, BASE_DEC,
3730                VALS(power_headroom_size_vals), 0x3f, "Power Headroom Level in dB", HFILL
3731             }
3732         },
3733
3734         { &hf_mac_lte_control_padding,
3735             { "Padding",
3736               "mac-lte.control.padding", FT_NONE, BASE_NONE, 0, 0x0,
3737               NULL, HFILL
3738             }
3739         },
3740
3741         /* Generated fields */
3742         { &hf_mac_lte_context_phy_dl_retx,
3743             { "DL Retx",
3744               "mac-lte.dlsch.retx", FT_BOOLEAN, BASE_DEC, 0, 0x0,
3745               NULL, HFILL
3746             }
3747         },
3748         { &hf_mac_lte_suspected_dl_retx_original_frame,
3749             { "Frame with previous tx",
3750               "mac-lte.dlsch.retx.original_frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
3751               NULL, HFILL
3752             }
3753         },
3754
3755         { &hf_mac_lte_ul_harq_resend_original_frame,
3756             { "Frame with previous tx",
3757               "mac-lte.ulsch.retx.original-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
3758               NULL, HFILL
3759             }
3760         },
3761
3762         { &hf_mac_lte_grant_answering_sr,
3763             { "First Grant Following SR from",
3764               "mac-lte.ulsch.grant-answering-sr", FT_FRAMENUM, BASE_NONE, 0, 0x0,
3765               NULL, HFILL
3766             }
3767         },
3768         { &hf_mac_lte_failure_answering_sr,
3769             { "SR which failed",
3770               "mac-lte.ulsch.failure-answering-sr", FT_FRAMENUM, BASE_NONE, 0, 0x0,
3771               NULL, HFILL
3772             }
3773         },
3774         { &hf_mac_lte_sr_leading_to_failure,
3775             { "This SR fails",
3776               "mac-lte.ulsch.failure-answering-sr-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
3777               NULL, HFILL
3778             }
3779         },
3780         { &hf_mac_lte_sr_leading_to_grant,
3781             { "This SR results in a grant here",
3782               "mac-lte.ulsch.grant-answering-sr-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
3783               NULL, HFILL
3784             }
3785         },
3786         { &hf_mac_lte_sr_invalid_event,
3787             { "Invalid event",
3788               "mac-lte.ulsch.sr-invalid-event", FT_NONE, BASE_NONE, 0, 0x0,
3789               NULL, HFILL
3790             }
3791         },
3792         { &hf_mac_lte_sr_time_since_request,
3793             { "Time since SR (ms)",
3794               "mac-lte.ulsch.time-since-sr", FT_UINT32, BASE_DEC, 0, 0x0,
3795               NULL, HFILL
3796             }
3797         },
3798         { &hf_mac_lte_sr_time_until_answer,
3799             { "Time until answer (ms)",
3800               "mac-lte.ulsch.time-until-sr-answer", FT_UINT32, BASE_DEC, 0, 0x0,
3801               NULL, HFILL
3802             }
3803         },
3804
3805     };
3806
3807     static gint *ett[] =
3808     {
3809         &ett_mac_lte,
3810         &ett_mac_lte_context,
3811         &ett_mac_lte_phy_context,
3812         &ett_mac_lte_rar_headers,
3813         &ett_mac_lte_rar_header,
3814         &ett_mac_lte_rar_body,
3815         &ett_mac_lte_rar_ul_grant,
3816         &ett_mac_lte_ulsch_header,
3817         &ett_mac_lte_dlsch_header,
3818         &ett_mac_lte_sch_subheader,
3819         &ett_mac_lte_bch,
3820         &ett_mac_lte_bsr,
3821         &ett_mac_lte_pch,
3822         &ett_mac_lte_contention_resolution,
3823         &ett_mac_lte_power_headroom,
3824         &ett_mac_lte_oob
3825     };
3826
3827     static enum_val_t show_info_col_vals[] = {
3828         {"show-phy", "PHY Info", ShowPHYLayer},
3829         {"show-mac", "MAC Info", ShowMACLayer},
3830         {"show-rlc", "RLC Info", ShowRLCLayer},
3831         {NULL, NULL, -1}
3832     };
3833
3834     module_t *mac_lte_module;
3835
3836     static uat_field_t lcid_drb_mapping_flds[] = {
3837         UAT_FLD_VS(lcid_drb_mappings, lcid, "lcid", drb_lcid_vals, "The MAC LCID"),
3838         UAT_FLD_DEC(lcid_drb_mappings, drbid,"drb id (1-32)", "Identifier of logical data channel"),
3839         UAT_FLD_VS(lcid_drb_mappings, channel_type, "RLC Channel Type", rlc_channel_type_vals, "The MAC LCID"),
3840         UAT_END_FIELDS
3841     };
3842
3843     /* Register protocol. */
3844     proto_mac_lte = proto_register_protocol("MAC-LTE", "MAC-LTE", "mac-lte");
3845     proto_register_field_array(proto_mac_lte, hf, array_length(hf));
3846     proto_register_subtree_array(ett, array_length(ett));
3847
3848     /* Allow other dissectors to find this one by name. */
3849     register_dissector("mac-lte", dissect_mac_lte, proto_mac_lte);
3850
3851     /* Register the tap name */
3852     mac_lte_tap = register_tap("mac-lte");
3853
3854     /* Preferences */
3855     mac_lte_module = prefs_register_protocol(proto_mac_lte, NULL);
3856
3857     /* Obsolete preferences */
3858     prefs_register_obsolete_preference(mac_lte_module, "single_rar");
3859     prefs_register_obsolete_preference(mac_lte_module, "check_reserved_bits");
3860     prefs_register_obsolete_preference(mac_lte_module, "decode_rar_ul_grant");
3861     prefs_register_obsolete_preference(mac_lte_module, "show_rlc_info_column");
3862     prefs_register_obsolete_preference(mac_lte_module, "attempt_to_detect_dl_harq_resend");
3863     
3864     prefs_register_uint_preference(mac_lte_module, "retx_count_warn",
3865         "Number of Re-Transmits before expert warning triggered",
3866         "Number of Re-Transmits before expert warning triggered",
3867         10, &global_mac_lte_retx_counter_trigger);
3868
3869     prefs_register_bool_preference(mac_lte_module, "attempt_rrc_decode",
3870         "Attempt to decode BCH, PCH and CCCH data using LTE RRC dissector",
3871         "Attempt to decode BCH, PCH and CCCH data using LTE RRC dissector",
3872         &global_mac_lte_attempt_rrc_decode);
3873
3874     prefs_register_bool_preference(mac_lte_module, "attempt_to_dissect_crc_failures",
3875         "Dissect frames that have failed CRC check",
3876         "Attempt to dissect frames that have failed CRC check",
3877         &global_mac_lte_dissect_crc_failures);
3878
3879     prefs_register_bool_preference(mac_lte_module, "heuristic_mac_lte_over_udp",
3880         "Try Heuristic LTE-MAC over UDP framing",
3881         "When enabled, use heuristic dissector to find MAC-LTE frames sent with "
3882         "UDP framing",
3883         &global_mac_lte_heur);
3884
3885     prefs_register_bool_preference(mac_lte_module, "attempt_to_dissect_srb_sdus",
3886         "Attempt to dissect LCID 1&2 as srb1&2",
3887         "Will call LTE RLC dissector with standard settings as per RRC spec",
3888         &global_mac_lte_attempt_srb_decode);
3889
3890     lcid_drb_mappings_uat = uat_new("LCID -> drb Table",
3891                                sizeof(lcid_drb_mapping_t),
3892                                "drb_logchans",
3893                                TRUE,
3894                                (void*) &lcid_drb_mappings,
3895                                &num_lcid_drb_mappings,
3896                                UAT_CAT_FFMT,
3897                                "",  /* TODO: is this ref to help manual? */
3898                                lcid_drb_mapping_copy_cb,
3899                                NULL,
3900                                NULL,
3901                                NULL,
3902                                lcid_drb_mapping_flds );
3903
3904     prefs_register_uat_preference(mac_lte_module,
3905                                   "drb_table",
3906                                   "LCID -> DRB Mappings Table",
3907                                   "A table that maps from configurable lcids -> RLC logical channels",
3908                                   lcid_drb_mappings_uat);
3909
3910     prefs_register_bool_preference(mac_lte_module, "attempt_to_track_ul_harq_resend",
3911         "Attempt to track UL HARQ resends",
3912         "When logging at UE side, will look for original transmission",
3913         &global_mac_lte_attempt_ul_harq_resend_track);
3914
3915     prefs_register_uint_preference(mac_lte_module, "bsr_warn_threshold",
3916         "BSR size when warning should be issued (0 - 63)",
3917         "If any BSR report is >= this number, an expert warning will be added",
3918         10, &global_mac_lte_bsr_warn_threshold);
3919
3920     prefs_register_bool_preference(mac_lte_module, "track_sr",
3921         "Track status of SRs within UEs",
3922         "Track status of SRs, providing links between requests, failure indications and grants",
3923         &global_mac_lte_track_sr);
3924
3925     prefs_register_enum_preference(mac_lte_module, "layer_to_show",
3926         "Which layer info to show in Info column",
3927         "Can show PHY, MAC or RLC layer info in Info column",
3928         &global_mac_lte_layer_to_show, show_info_col_vals, FALSE);
3929
3930     register_init_routine(&mac_lte_init_protocol);
3931 }
3932
3933 void
3934 proto_reg_handoff_mac_lte(void)
3935 {
3936     static dissector_handle_t mac_lte_handle;
3937     if (!mac_lte_handle) {
3938         mac_lte_handle = find_dissector("mac-lte");
3939
3940         /* Add as a heuristic UDP dissector */
3941         heur_dissector_add("udp", dissect_mac_lte_heur, proto_mac_lte);
3942     }
3943 }
3944