8c11cc56f086fc4498c14a058f0ab1deb1f4e921
[gd/wireshark/.git] / epan / dissectors / packet-rlc-lte.c
1 /* Routines for LTE RLC disassembly
2  *
3  * Martin Mathieson
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * SPDX-License-Identifier: GPL-2.0-or-later
10  */
11
12 #include "config.h"
13
14 #include <epan/packet.h>
15 #include <epan/exceptions.h>
16 #include <epan/expert.h>
17 #include <epan/prefs.h>
18 #include <epan/tap.h>
19 #include <epan/proto_data.h>
20 #include "packet-mac-lte.h"
21 #include "packet-rlc-lte.h"
22 #include "packet-pdcp-lte.h"
23
24
25 /* Described in:
26  * 3GPP TS 36.322 Evolved Universal Terrestial Radio Access (E-UTRA)
27  * Radio Link Control (RLC) Protocol specification v14.0.0
28  */
29
30 /* TODO:
31    - add intermediate results to segments leading to final reassembly
32    - use multiple active rlc_channel_reassembly_info's per channel
33    - sequence analysis gets confused when we change cells and skip back
34      to SN 0. Maybe add cell-id to context and add to channel/result key?
35 */
36
37 void proto_register_rlc_lte(void);
38 void proto_reg_handoff_rlc_lte(void);
39
40 /********************************/
41 /* Preference settings          */
42
43 #define SEQUENCE_ANALYSIS_MAC_ONLY 1
44 #define SEQUENCE_ANALYSIS_RLC_ONLY 2
45
46 /* By default do try to analyse the sequence of messages for AM/UM channels
47    using MAC PDUs */
48 static gint global_rlc_lte_am_sequence_analysis = SEQUENCE_ANALYSIS_MAC_ONLY;
49 static gint global_rlc_lte_um_sequence_analysis = SEQUENCE_ANALYSIS_MAC_ONLY;
50
51 /* By default do call PDCP/RRC dissectors for SDU data */
52 static gboolean global_rlc_lte_call_pdcp_for_srb = TRUE;
53
54 enum pdcp_for_drb { PDCP_drb_off, PDCP_drb_SN_7, PDCP_drb_SN_12, PDCP_drb_SN_signalled, PDCP_drb_SN_15, PDCP_drb_SN_18};
55 static const enum_val_t pdcp_drb_col_vals[] = {
56     {"pdcp-drb-off",           "Off",                 PDCP_drb_off},
57     {"pdcp-drb-sn-7",          "7-bit SN",            PDCP_drb_SN_7},
58     {"pdcp-drb-sn-12",         "12-bit SN",           PDCP_drb_SN_12},
59     {"pdcp-drb-sn-15",         "15-bit SN",           PDCP_drb_SN_15},
60     {"pdcp-drb-sn-18",         "18-bit SN",           PDCP_drb_SN_18},
61     {"pdcp-drb-sn-signalling", "Use signalled value", PDCP_drb_SN_signalled},
62     {NULL, NULL, -1}
63 };
64 static gint global_rlc_lte_call_pdcp_for_drb = (gint)PDCP_drb_SN_signalled;
65
66 static gboolean global_rlc_lte_call_rrc_for_ccch = TRUE;
67 static gboolean global_rlc_lte_call_rrc_for_mcch = FALSE;
68 static gboolean global_rlc_lte_call_ip_for_mtch = FALSE;
69
70 /* Preference to expect RLC headers without payloads */
71 static gboolean global_rlc_lte_headers_expected = FALSE;
72
73 /* Re-assembly of segments */
74 static gboolean global_rlc_lte_reassembly = TRUE;
75
76 /* Tree storing UE related parameters */
77 #define NO_EXT_LI 0x0
78 #define UL_EXT_LI 0x1
79 #define DL_EXT_LI 0x2
80 typedef struct rlc_ue_parameters {
81     guint32 id;
82     guint8 ext_li_field;
83     guint8 pdcp_sn_bits;
84 } rlc_ue_parameters;
85 static wmem_tree_t *ue_parameters_tree;
86
87 /**************************************************/
88 /* Initialize the protocol and registered fields. */
89 int proto_rlc_lte = -1;
90
91 extern int proto_mac_lte;
92 extern int proto_pdcp_lte;
93
94 static dissector_handle_t pdcp_lte_handle;
95 static dissector_handle_t ip_handle;
96 static dissector_handle_t lte_rrc_mcch;
97 static dissector_handle_t lte_rrc_ul_ccch;
98 static dissector_handle_t lte_rrc_dl_ccch;
99 static dissector_handle_t lte_rrc_bcch_bch;
100 static dissector_handle_t lte_rrc_bcch_dl_sch;
101 static dissector_handle_t lte_rrc_pcch;
102 static dissector_handle_t lte_rrc_ul_ccch_nb;
103 static dissector_handle_t lte_rrc_dl_ccch_nb;
104 static dissector_handle_t lte_rrc_bcch_bch_nb;
105 static dissector_handle_t lte_rrc_bcch_dl_sch_nb;
106 static dissector_handle_t lte_rrc_pcch_nb;
107
108
109 static int rlc_lte_tap = -1;
110
111 /* Decoding context */
112 static int hf_rlc_lte_context = -1;
113 static int hf_rlc_lte_context_mode = -1;
114 static int hf_rlc_lte_context_direction = -1;
115 static int hf_rlc_lte_context_priority = -1;
116 static int hf_rlc_lte_context_ueid = -1;
117 static int hf_rlc_lte_context_channel_type = -1;
118 static int hf_rlc_lte_context_channel_id = -1;
119 static int hf_rlc_lte_context_pdu_length = -1;
120 static int hf_rlc_lte_context_um_sn_length = -1;
121 static int hf_rlc_lte_context_am_sn_length = -1;
122
123 /* Transparent mode fields */
124 static int hf_rlc_lte_tm = -1;
125 static int hf_rlc_lte_tm_data = -1;
126
127 /* Unacknowledged mode fields */
128 static int hf_rlc_lte_um = -1;
129 static int hf_rlc_lte_um_header = -1;
130 static int hf_rlc_lte_um_fi = -1;
131 static int hf_rlc_lte_um_fixed_e = -1;
132 static int hf_rlc_lte_um_sn = -1;
133 static int hf_rlc_lte_um_fixed_reserved = -1;
134 static int hf_rlc_lte_um_data = -1;
135 static int hf_rlc_lte_extension_part = -1;
136
137 /* Extended header (common to UM and AM) */
138 static int hf_rlc_lte_extension_e = -1;
139 static int hf_rlc_lte_extension_li = -1;
140 static int hf_rlc_lte_extension_padding = -1;
141
142
143 /* Acknowledged mode fields */
144 static int hf_rlc_lte_am = -1;
145 static int hf_rlc_lte_am_header = -1;
146 static int hf_rlc_lte_am_data_control = -1;
147 static int hf_rlc_lte_am_rf = -1;
148 static int hf_rlc_lte_am_p = -1;
149 static int hf_rlc_lte_am_fi = -1;
150 static int hf_rlc_lte_am_fixed_e = -1;
151 static int hf_rlc_lte_am_fixed_sn = -1;
152 static int hf_rlc_lte_am_fixed_reserved = -1;
153 static int hf_rlc_lte_am_segment_lsf16 = -1;
154 static int hf_rlc_lte_am_fixed_reserved2 = -1;
155 static int hf_rlc_lte_am_fixed_sn16 = -1;
156 static int hf_rlc_lte_am_segment_lsf = -1;
157 static int hf_rlc_lte_am_segment_so = -1;
158 static int hf_rlc_lte_am_segment_so16 = -1;
159 static int hf_rlc_lte_am_data = -1;
160
161 /* Control fields */
162 static int hf_rlc_lte_am_cpt = -1;
163 static int hf_rlc_lte_am_ack_sn = -1;
164 static int hf_rlc_lte_am_e1 = -1;
165 static int hf_rlc_lte_am_e2 = -1;
166 static int hf_rlc_lte_am_nack_sn = -1;
167 static int hf_rlc_lte_am_nacks = -1;
168 static int hf_rlc_lte_am_so_start = -1;
169 static int hf_rlc_lte_am_so_end = -1;
170
171 static int hf_rlc_lte_predefined_pdu = -1;
172 static int hf_rlc_lte_header_only = -1;
173
174 /* Sequence Analysis */
175 static int hf_rlc_lte_sequence_analysis = -1;
176 static int hf_rlc_lte_sequence_analysis_ok = -1;
177 static int hf_rlc_lte_sequence_analysis_previous_frame = -1;
178 static int hf_rlc_lte_sequence_analysis_next_frame = -1;
179 static int hf_rlc_lte_sequence_analysis_expected_sn = -1;
180 static int hf_rlc_lte_sequence_analysis_framing_info_correct = -1;
181
182 static int hf_rlc_lte_sequence_analysis_mac_retx = -1;
183 static int hf_rlc_lte_sequence_analysis_retx = -1;
184 static int hf_rlc_lte_sequence_analysis_repeated = -1;
185 static int hf_rlc_lte_sequence_analysis_skipped = -1;
186
187 static int hf_rlc_lte_sequence_analysis_repeated_nack = -1;
188 static int hf_rlc_lte_sequence_analysis_repeated_nack_original_frame = -1;
189
190 static int hf_rlc_lte_sequence_analysis_ack_out_of_range = -1;
191 static int hf_rlc_lte_sequence_analysis_ack_out_of_range_opposite_frame = -1;
192
193 /* Reassembly */
194 static int hf_rlc_lte_reassembly_source = -1;
195 static int hf_rlc_lte_reassembly_source_number_of_segments = -1;
196 static int hf_rlc_lte_reassembly_source_total_length = -1;
197 static int hf_rlc_lte_reassembly_source_segment = -1;
198 static int hf_rlc_lte_reassembly_source_segment_sn = -1;
199 static int hf_rlc_lte_reassembly_source_segment_framenum = -1;
200 static int hf_rlc_lte_reassembly_source_segment_length = -1;
201
202 /* Subtrees. */
203 static int ett_rlc_lte = -1;
204 static int ett_rlc_lte_context = -1;
205 static int ett_rlc_lte_um_header = -1;
206 static int ett_rlc_lte_am_header = -1;
207 static int ett_rlc_lte_extension_part = -1;
208 static int ett_rlc_lte_sequence_analysis = -1;
209 static int ett_rlc_lte_reassembly_source = -1;
210 static int ett_rlc_lte_reassembly_source_segment = -1;
211
212 static expert_field ei_rlc_lte_context_mode = EI_INIT;
213 static expert_field ei_rlc_lte_am_nack_sn = EI_INIT;
214 static expert_field ei_rlc_lte_am_nack_sn_ahead_ack = EI_INIT;
215 static expert_field ei_rlc_lte_um_sn_repeated = EI_INIT;
216 static expert_field ei_rlc_lte_am_nack_sn_ack_same = EI_INIT;
217 static expert_field ei_rlc_lte_am_cpt = EI_INIT;
218 static expert_field ei_rlc_lte_am_data_no_data = EI_INIT;
219 static expert_field ei_rlc_lte_sequence_analysis_last_segment_complete = EI_INIT;
220 static expert_field ei_rlc_lte_sequence_analysis_mac_retx = EI_INIT;
221 static expert_field ei_rlc_lte_am_nack_sn_partial = EI_INIT;
222 static expert_field ei_rlc_lte_sequence_analysis_repeated_nack = EI_INIT;
223 static expert_field ei_rlc_lte_bytes_after_status_pdu_complete = EI_INIT;
224 static expert_field ei_rlc_lte_sequence_analysis_repeated = EI_INIT;
225 static expert_field ei_rlc_lte_wrong_sequence_number = EI_INIT;
226 static expert_field ei_rlc_lte_sequence_analysis_retx = EI_INIT;
227 static expert_field ei_rlc_lte_am_sn_missing = EI_INIT;
228 static expert_field ei_rlc_lte_um_sn = EI_INIT;
229 static expert_field ei_rlc_lte_header_only = EI_INIT;
230 static expert_field ei_rlc_lte_am_data_no_data_beyond_extensions = EI_INIT;
231 static expert_field ei_rlc_lte_um_sn_missing = EI_INIT;
232 static expert_field ei_rlc_lte_sequence_analysis_ack_out_of_range_opposite_frame = EI_INIT;
233 static expert_field ei_rlc_lte_sequence_analysis_last_segment_not_continued = EI_INIT;
234 static expert_field ei_rlc_lte_reserved_bits_not_zero = EI_INIT;
235 static expert_field ei_rlc_lte_no_per_frame_info = EI_INIT;
236 static expert_field ei_rlc_lte_unknown_udp_framing_tag = EI_INIT;
237 static expert_field ei_rlc_lte_missing_udp_framing_tag = EI_INIT;
238
239 /* Value-strings */
240 static const value_string direction_vals[] =
241 {
242     { DIRECTION_UPLINK,      "Uplink"},
243     { DIRECTION_DOWNLINK,    "Downlink"},
244     { 0, NULL }
245 };
246
247 static const value_string rlc_mode_short_vals[] =
248 {
249     { RLC_TM_MODE,      "TM"},
250     { RLC_UM_MODE,      "UM"},
251     { RLC_AM_MODE,      "AM"},
252     { RLC_PREDEF,       "PREDEFINED"},  /* For data testing */
253     { 0, NULL }
254 };
255
256 static const value_string rlc_mode_vals[] =
257 {
258     { RLC_TM_MODE,      "Transparent Mode"},
259     { RLC_UM_MODE,      "Unacknowledged Mode"},
260     { RLC_AM_MODE,      "Acknowledged Mode"},
261     { 0, NULL }
262 };
263
264 static const value_string rlc_channel_type_vals[] =
265 {
266     { CHANNEL_TYPE_CCCH,         "CCCH"},
267     { CHANNEL_TYPE_BCCH_BCH,     "BCCH_BCH"},
268     { CHANNEL_TYPE_PCCH,         "PCCH"},
269     { CHANNEL_TYPE_SRB,          "SRB"},
270     { CHANNEL_TYPE_DRB,          "DRB"},
271     { CHANNEL_TYPE_BCCH_DL_SCH,  "BCCH_DL_SCH"},
272     { CHANNEL_TYPE_MCCH,         "MCCH"},
273     { CHANNEL_TYPE_MTCH,         "MTCH"},
274     { 0, NULL }
275 };
276
277 static const value_string framing_info_vals[] =
278 {
279     { 0,      "First byte begins a RLC SDU and last byte ends a RLC SDU"},
280     { 1,      "First byte begins a RLC SDU and last byte does not end a RLC SDU"},
281     { 2,      "First byte does not begin a RLC SDU and last byte ends a RLC SDU"},
282     { 3,      "First byte does not begin a RLC SDU and last byte does not end a RLC SDU"},
283     { 0, NULL }
284 };
285
286 static const value_string fixed_extension_vals[] =
287 {
288     { 0,      "Data field follows from the octet following the fixed part of the header"},
289     { 1,      "A set of E field and LI field follows from the octet following the fixed part of the header"},
290     { 0, NULL }
291 };
292
293 static const value_string extension_extension_vals[] =
294 {
295     { 0,      "Data field follows from the octet following the LI field following this E field"},
296     { 1,      "A set of E field and LI field follows from the bit following the LI field following this E field"},
297     { 0, NULL }
298 };
299
300 static const value_string data_or_control_vals[] =
301 {
302     { 0,      "Control PDU"},
303     { 1,      "Data PDU"},
304     { 0, NULL }
305 };
306
307 static const value_string resegmentation_flag_vals[] =
308 {
309     { 0,      "AMD PDU"},
310     { 1,      "AMD PDU segment"},
311     { 0, NULL }
312 };
313
314 static const value_string polling_bit_vals[] =
315 {
316     { 0,      "Status report not requested"},
317     { 1,      "Status report is requested"},
318     { 0, NULL }
319 };
320
321 static const value_string lsf_vals[] =
322 {
323     { 0,      "Last byte of the AMD PDU segment does not correspond to the last byte of an AMD PDU"},
324     { 1,      "Last byte of the AMD PDU segment corresponds to the last byte of an AMD PDU"},
325     { 0, NULL }
326 };
327
328 static const value_string control_pdu_type_vals[] =
329 {
330     { 0,      "STATUS PDU"},
331     { 0, NULL }
332 };
333
334 static const value_string am_e1_vals[] =
335 {
336     { 0,      "A set of NACK_SN, E1 and E2 does not follow"},
337     { 1,      "A set of NACK_SN, E1 and E2 follows"},
338     { 0, NULL }
339 };
340
341 static const value_string am_e2_vals[] =
342 {
343     { 0,      "A set of SOstart and SOend does not follow for this NACK_SN"},
344     { 1,      "A set of SOstart and SOend follows for this NACK_SN"},
345     { 0, NULL }
346 };
347
348 static const value_string header_only_vals[] =
349 {
350     { 0,      "RLC PDU Headers and body present"},
351     { 1,      "RLC PDU Headers only"},
352     { 0, NULL }
353 };
354
355
356
357 /**********************************************************************************/
358 /* These are for keeping track of UM/AM extension headers, and the lengths found  */
359 /* in them                                                                        */
360 static guint8  s_number_of_extensions = 0;
361 #define MAX_RLC_SDUS 192
362 static guint16 s_lengths[MAX_RLC_SDUS];
363
364
365 /*********************************************************************/
366 /* UM/AM sequence analysis                                           */
367
368 /* Types for RLC channel hash table                                   */
369 /* This table is maintained during initial dissection of RLC          */
370 /* frames, mapping from channel_hash_key -> sequence_analysis_report  */
371
372 /* Channel key */
373 typedef struct
374 {
375     guint  ueId : 16;
376     guint  channelType : 3;
377     guint  channelId : 5;
378     guint  direction : 1;
379 } channel_hash_key;
380
381
382 /******************************************************************/
383 /* State maintained for AM/UM reassembly                          */
384
385 typedef struct rlc_segment {
386     guint32 frameNum;
387     guint16 SN;
388     guint8 *data;
389     guint16 length;
390 } rlc_segment;
391
392 typedef struct rlc_channel_reassembly_info
393 {
394     guint16 number_of_segments;
395     #define RLC_MAX_SEGMENTS 100
396     rlc_segment segments[RLC_MAX_SEGMENTS];
397 } rlc_channel_reassembly_info;
398
399
400
401
402 /*******************************************************************/
403 /* Conversation-type status for sequence analysis on channel       */
404 typedef struct
405 {
406     guint8   rlcMode;
407
408     /* For UM, we always expect the SN to keep advancing, and these fields
409        keep track of this.
410        For AM, these correspond to new data */
411     guint16  previousSequenceNumber;
412     guint32  previousFrameNum;
413     gboolean previousSegmentIncomplete;
414
415     /* Accumulate info about current segmented SDU */
416     struct rlc_channel_reassembly_info *reassembly_info;
417 } channel_sequence_analysis_status;
418
419 /* The sequence analysis channel hash table */
420 static wmem_map_t *sequence_analysis_channel_hash = NULL;
421
422
423 /* Types for sequence analysis frame report hash table                  */
424 /* This is a table from framenum -> state_report_in_frame               */
425 /* This is necessary because the per-packet info is already being used  */
426 /* for context information before the dissector is called               */
427
428 /* Info to attach to frame when first read, recording what to show about sequence */
429 typedef enum {
430     SN_OK, SN_Repeated, SN_MAC_Retx, SN_Retx, SN_Missing, ACK_Out_of_Window, SN_Error
431 } sequence_analysis_state;
432
433
434 typedef struct
435 {
436     gboolean  sequenceExpectedCorrect;
437     guint16   sequenceExpected;
438     guint32   previousFrameNum;
439     gboolean  previousSegmentIncomplete;
440     guint32   nextFrameNum;
441
442     guint16   firstSN;
443     guint16   lastSN;
444
445     /* AM/UM */
446     sequence_analysis_state state;
447 } sequence_analysis_report;
448
449
450 /* The sequence analysis frame report hash table instance itself   */
451 static wmem_map_t *sequence_analysis_report_hash = NULL;
452
453
454 static gpointer get_report_hash_key(guint16 SN, guint32 frameNumber,
455                                     rlc_lte_info *p_rlc_lte_info,
456                                     gboolean do_persist);
457
458
459
460
461 /* The reassembly result hash table */
462 static wmem_map_t *reassembly_report_hash = NULL;
463
464
465 /* Create a new struct for reassembly */
466 static void reassembly_reset(channel_sequence_analysis_status *status)
467 {
468     status->reassembly_info = wmem_new0(wmem_file_scope(), rlc_channel_reassembly_info);
469 }
470
471 /* Hide previous one */
472 static void reassembly_destroy(channel_sequence_analysis_status *status)
473 {
474     /* Just "leak" it. There seems to be no way to free this memory... */
475     status->reassembly_info = NULL;
476 }
477
478 /* Add a new segment to the accumulating segmented SDU */
479 static void reassembly_add_segment(channel_sequence_analysis_status *status,
480                                    guint16 SN, guint32 frame,
481                                    tvbuff_t *tvb, gint offset, gint length)
482 {
483     int segment_number =  status->reassembly_info->number_of_segments;
484     guint8 *segment_data;
485
486     /* Give up if reach segment limit */
487     if (segment_number >= (RLC_MAX_SEGMENTS-1)) {
488         reassembly_destroy(status);
489         return;
490     }
491
492     segment_data = (guint8 *)tvb_memdup(wmem_file_scope(),tvb, offset, length);
493
494     /* Add new segment */
495     status->reassembly_info->segments[segment_number].frameNum = frame;
496     status->reassembly_info->segments[segment_number].SN = SN;
497     status->reassembly_info->segments[segment_number].data = segment_data;
498     status->reassembly_info->segments[segment_number].length = length;
499
500     status->reassembly_info->number_of_segments++;
501 }
502
503
504 /* Record the current & complete segmented SDU by mapping from this frame number to
505    struct with segment info. */
506 static void reassembly_record(channel_sequence_analysis_status *status, packet_info *pinfo,
507                               guint16 SN, rlc_lte_info *p_rlc_lte_info)
508 {
509     /* Just store existing info in hash table */
510     wmem_map_insert(reassembly_report_hash,
511                         get_report_hash_key(SN, pinfo->num, p_rlc_lte_info, TRUE),
512                         status->reassembly_info);
513 }
514
515 /* Create and return a tvb based upon contents of reassembly info */
516 static tvbuff_t* reassembly_get_reassembled_tvb(rlc_channel_reassembly_info *reassembly_info,
517                                                 tvbuff_t *parent_tvb, packet_info *pinfo)
518 {
519     gint n;
520     guint   combined_length = 0;
521     guint8 *combined_data;
522     guint combined_offset = 0;
523     tvbuff_t *reassembled_tvb;
524
525     /* Allocate buffer big enough to hold re-assembled data */
526     for (n=0; n < reassembly_info->number_of_segments; n++) {
527         combined_length += reassembly_info->segments[n].length;
528     }
529     combined_data = (guint8 *)wmem_alloc(pinfo->pool, combined_length);
530
531     /* Copy data into contiguous buffer */
532     for (n=0; n < reassembly_info->number_of_segments; n++) {
533         guint8 *data = reassembly_info->segments[n].data;
534         int length = reassembly_info->segments[n].length;
535         memcpy(combined_data+combined_offset, data, length);
536         combined_offset += length;
537     }
538
539     /* Create and return tvb with this data */
540     reassembled_tvb = tvb_new_child_real_data(parent_tvb, combined_data, combined_offset, combined_offset);
541     add_new_data_source(pinfo, reassembled_tvb, "Reassembled SDU");
542     return reassembled_tvb;
543 }
544
545 /* Show where the segments came from for a reassembled SDU */
546 static void reassembly_show_source(rlc_channel_reassembly_info *reassembly_info,
547                                    proto_tree *tree, tvbuff_t *tvb, gint offset)
548 {
549     int n;
550     proto_item *source_ti, *ti;
551     proto_tree *source_tree;
552     proto_item *segment_ti;
553     proto_tree *segment_tree;
554     guint      total_length=0;
555
556     /* Create root of source info */
557     source_ti = proto_tree_add_item(tree,
558                                     hf_rlc_lte_reassembly_source,
559                                     tvb, 0, 0, ENC_ASCII|ENC_NA);
560     source_tree = proto_item_add_subtree(source_ti, ett_rlc_lte_reassembly_source);
561     PROTO_ITEM_SET_GENERATED(source_ti);
562
563     for (n=0; n < reassembly_info->number_of_segments; n++) {
564         total_length += reassembly_info->segments[n].length;
565     }
566     proto_item_append_text(source_ti, " %u segments, %u bytes", reassembly_info->number_of_segments,
567                            total_length);
568
569     /* Number of segments */
570     ti = proto_tree_add_uint(source_tree,
571                              hf_rlc_lte_reassembly_source_number_of_segments,
572                              tvb, 0, 0, reassembly_info->number_of_segments);
573     PROTO_ITEM_SET_GENERATED(ti);
574
575     /* Total length */
576     ti = proto_tree_add_uint(source_tree,
577                              hf_rlc_lte_reassembly_source_total_length,
578                              tvb, 0, 0, total_length);
579     PROTO_ITEM_SET_GENERATED(ti);
580
581     /* Now add info about each segment in turn */
582     for (n=0; n < reassembly_info->number_of_segments; n++) {
583
584         /* Add next segment as a subtree */
585         rlc_segment *segment = &(reassembly_info->segments[n]);
586         proto_item_append_text(source_ti, " (SN=%u frame=%u len=%u)",
587                                segment->SN, segment->frameNum, segment->length);
588
589         /* N.B. assume last segment from passed-in tvb! */
590         segment_ti = proto_tree_add_item(source_tree,
591                                          hf_rlc_lte_reassembly_source_segment,
592                                          tvb,
593                                          (n == reassembly_info->number_of_segments-1) ? offset : 0,
594                                          (n == reassembly_info->number_of_segments-1) ? segment->length : 0,
595                                          ENC_NA);
596         segment_tree = proto_item_add_subtree(segment_ti, ett_rlc_lte_reassembly_source_segment);
597         proto_item_append_text(segment_ti, " (SN=%u frame=%u length=%u)",
598                                segment->SN, segment->frameNum, segment->length);
599         PROTO_ITEM_SET_GENERATED(segment_ti);
600
601         /* Add details to segment tree */
602         ti = proto_tree_add_uint(segment_tree, hf_rlc_lte_reassembly_source_segment_sn,
603                                  tvb, 0, 0, segment->SN);
604         PROTO_ITEM_SET_GENERATED(ti);
605         ti = proto_tree_add_uint(segment_tree, hf_rlc_lte_reassembly_source_segment_framenum,
606                                  tvb, 0, 0, segment->frameNum);
607         PROTO_ITEM_SET_GENERATED(ti);
608         ti = proto_tree_add_uint(segment_tree, hf_rlc_lte_reassembly_source_segment_length,
609                                  tvb, 0, 0, segment->length);
610         PROTO_ITEM_SET_GENERATED(ti);
611     }
612 }
613
614
615
616
617 /******************************************************************/
618 /* Conversation-type status for repeated NACK checking on channel */
619 typedef struct
620 {
621     guint16         noOfNACKs;
622     guint16         NACKs[MAX_NACKs];
623     guint32         frameNum;
624 } channel_repeated_nack_status;
625
626 static wmem_map_t *repeated_nack_channel_hash = NULL;
627
628 typedef struct {
629     guint16         noOfNACKsRepeated;
630     guint16         repeatedNACKs[MAX_NACKs];
631     guint32         previousFrameNum;
632 } channel_repeated_nack_report;
633
634 static wmem_map_t *repeated_nack_report_hash = NULL;
635
636
637
638 /********************************************************/
639 /* Forward declarations & functions                     */
640 static void dissect_rlc_lte_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean is_udp_framing);
641
642
643 /* Write the given formatted text to:
644    - the info column
645    - the top-level RLC PDU item
646    - another subtree item (if supplied) */
647 static void write_pdu_label_and_info(proto_item *pdu_ti, proto_item *sub_ti,
648                                      packet_info *pinfo, const char *format, ...)
649 {
650     #define MAX_INFO_BUFFER 256
651     static char info_buffer[MAX_INFO_BUFFER];
652
653     va_list ap;
654
655     va_start(ap, format);
656     g_vsnprintf(info_buffer, MAX_INFO_BUFFER, format, ap);
657     va_end(ap);
658
659     /* Add to indicated places */
660     col_append_str(pinfo->cinfo, COL_INFO, info_buffer);
661     proto_item_append_text(pdu_ti, "%s", info_buffer);
662     if (sub_ti != NULL) {
663         proto_item_append_text(sub_ti, "%s", info_buffer);
664     }
665 }
666
667 /* Version of function above, where no g_vsnprintf() call needed
668    - the info column
669    - the top-level RLC PDU item
670    - another subtree item (if supplied) */
671 static void write_pdu_label_and_info_literal(proto_item *pdu_ti, proto_item *sub_ti,
672                                              packet_info *pinfo, const char *info_buffer)
673 {
674     /* Add to indicated places */
675     col_append_str(pinfo->cinfo, COL_INFO, info_buffer);
676     proto_item_append_text(pdu_ti, "%s", info_buffer);
677     if (sub_ti != NULL) {
678         proto_item_append_text(sub_ti, "%s", info_buffer);
679     }
680 }
681
682
683
684 /* Dissect extension headers (common to both UM and AM) */
685 static int dissect_rlc_lte_extension_header(tvbuff_t *tvb, packet_info *pinfo _U_,
686                                             proto_tree *tree,
687                                             int offset,
688                                             rlc_lte_info *p_rlc_lte_info)
689 {
690     guint8  isOdd;
691     guint64 extension = 1;
692     guint64 length;
693
694     /* Reset this count */
695     s_number_of_extensions = 0;
696
697     while (extension && (s_number_of_extensions < MAX_RLC_SDUS)) {
698         proto_tree *extension_part_tree;
699         proto_item *extension_part_ti;
700
701         /* Extension part subtree */
702         extension_part_ti = proto_tree_add_string_format(tree,
703                                                          hf_rlc_lte_extension_part,
704                                                          tvb, offset, 2,
705                                                          "",
706                                                          "Extension Part");
707         extension_part_tree = proto_item_add_subtree(extension_part_ti,
708                                                      ett_rlc_lte_extension_part);
709
710         if (p_rlc_lte_info->extendedLiField == FALSE) {
711             isOdd = (s_number_of_extensions % 2);
712
713             /* Read next extension */
714             proto_tree_add_bits_ret_val(extension_part_tree, hf_rlc_lte_extension_e, tvb,
715                                         (offset*8) + ((isOdd) ? 4 : 0),
716                                         1,
717                                         &extension, ENC_BIG_ENDIAN);
718
719             /* Read length field */
720             proto_tree_add_bits_ret_val(extension_part_tree, hf_rlc_lte_extension_li, tvb,
721                                         (offset*8) + ((isOdd) ? 5 : 1),
722                                         11,
723                                         &length, ENC_BIG_ENDIAN);
724
725             /* Move on to byte of next extension */
726             if (isOdd) {
727                 offset += 2;
728             } else {
729                 offset++;
730             }
731         } else {
732             /* Read next extension */
733             proto_tree_add_bits_ret_val(extension_part_tree, hf_rlc_lte_extension_e, tvb,
734                                         (offset*8),
735                                         1,
736                                         &extension, ENC_BIG_ENDIAN);
737
738             /* Read length field */
739             proto_tree_add_bits_ret_val(extension_part_tree, hf_rlc_lte_extension_li, tvb,
740                                         (offset*8) + 1,
741                                         15,
742                                         &length, ENC_BIG_ENDIAN);
743
744             /* Move on to byte of next extension */
745             offset += 2;
746         }
747
748         proto_item_append_text(extension_part_tree, " (length=%u)", (guint16)length);
749
750         s_lengths[s_number_of_extensions++] = (guint16)length;
751     }
752
753     /* May need to skip padding after last extension part */
754     isOdd = (s_number_of_extensions % 2);
755     if (isOdd && (p_rlc_lte_info->extendedLiField == FALSE)) {
756         proto_tree_add_item(tree, hf_rlc_lte_extension_padding,
757                             tvb, offset++, 1, ENC_BIG_ENDIAN);
758     }
759
760     return offset;
761 }
762
763
764 /* Show in the info column how many bytes are in the UM/AM PDU, and indicate
765    whether or not the beginning and end are included in this packet */
766 static void show_PDU_in_info(packet_info *pinfo,
767                              proto_item *top_ti,
768                              gint32 length,
769                              gboolean first_includes_start,
770                              gboolean last_includes_end)
771 {
772     /* Reflect this PDU in the info column */
773     if (length > 0) {
774         write_pdu_label_and_info(top_ti, NULL, pinfo,
775                                  "  %s%u-byte%s%s",
776                                  (first_includes_start) ? "[" : "..",
777                                  length,
778                                  (length > 1) ? "s" : "",
779                                  (last_includes_end) ? "]" : "..");
780     }
781     else {
782         write_pdu_label_and_info(top_ti, NULL, pinfo,
783                                  "  %sunknown-bytes%s",
784                                  (first_includes_start) ? "[" : "..",
785                                  (last_includes_end) ? "]" : "..");
786     }
787 }
788
789
790 /* Show an SDU. If configured, pass to PDCP/RRC/IP dissector */
791 static void show_PDU_in_tree(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, gint offset, gint length,
792                              rlc_lte_info *rlc_info, gboolean whole_pdu, rlc_channel_reassembly_info *reassembly_info,
793                              sequence_analysis_state state)
794 {
795     wmem_tree_key_t key[3];
796     guint32 id;
797     rlc_ue_parameters *params;
798
799     /* Add raw data (according to mode) */
800     proto_item *data_ti = proto_tree_add_item(tree,
801                                               (rlc_info->rlcMode == RLC_AM_MODE) ?
802                                                     hf_rlc_lte_am_data :
803                                                     hf_rlc_lte_um_data,
804                                               tvb, offset, length, ENC_NA);
805
806     if (whole_pdu || (reassembly_info != NULL)) {
807         if (((global_rlc_lte_call_pdcp_for_srb) && (rlc_info->channelType == CHANNEL_TYPE_SRB)) ||
808             ((global_rlc_lte_call_pdcp_for_drb != PDCP_drb_off) && (rlc_info->channelType == CHANNEL_TYPE_DRB))) {
809             /* Send whole PDU to PDCP */
810
811             /* TODO: made static to avoid compiler warning... */
812             static tvbuff_t *pdcp_tvb = NULL;
813             struct pdcp_lte_info *p_pdcp_lte_info;
814
815             /* Get tvb for passing to LTE PDCP dissector */
816             if (reassembly_info == NULL) {
817                 pdcp_tvb = tvb_new_subset_length(tvb, offset, length);
818             }
819             else {
820                 /* Get combined tvb. */
821                 pdcp_tvb = reassembly_get_reassembled_tvb(reassembly_info, tvb, pinfo);
822                 reassembly_show_source(reassembly_info, tree, tvb, offset);
823             }
824
825             /* Reuse or allocate struct */
826             p_pdcp_lte_info = (pdcp_lte_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_pdcp_lte, 0);
827             if (p_pdcp_lte_info == NULL) {
828                 p_pdcp_lte_info = wmem_new0(wmem_file_scope(), pdcp_lte_info);
829                 /* Store info in packet */
830                 p_add_proto_data(wmem_file_scope(), pinfo, proto_pdcp_lte, 0, p_pdcp_lte_info);
831             }
832
833             p_pdcp_lte_info->ueid = rlc_info->ueid;
834             if (rlc_info->nbMode == rlc_nb_mode) {
835                 p_pdcp_lte_info->channelType = Channel_DCCH_NB;
836             } else {
837                 p_pdcp_lte_info->channelType = Channel_DCCH;
838             }
839             p_pdcp_lte_info->channelId = rlc_info->channelId;
840             p_pdcp_lte_info->direction = rlc_info->direction;
841             p_pdcp_lte_info->is_retx = (state != SN_OK);
842
843             /* Set plane and sequence number length */
844             p_pdcp_lte_info->no_header_pdu = FALSE;
845             if (rlc_info->channelType == CHANNEL_TYPE_SRB) {
846                 p_pdcp_lte_info->plane = SIGNALING_PLANE;
847                 if ((rlc_info->nbMode == rlc_nb_mode) && (rlc_info->channelId == 3)) {
848                     p_pdcp_lte_info->no_header_pdu = TRUE;
849                     p_pdcp_lte_info->seqnum_length = 0;
850                 } else {
851                     p_pdcp_lte_info->seqnum_length = 5;
852                 }
853             }
854             else {
855                 p_pdcp_lte_info->plane = USER_PLANE;
856                 switch (global_rlc_lte_call_pdcp_for_drb) {
857                     case PDCP_drb_SN_7:
858                         p_pdcp_lte_info->seqnum_length = 7;
859                         break;
860                     case PDCP_drb_SN_12:
861                         p_pdcp_lte_info->seqnum_length = 12;
862                         break;
863                     case PDCP_drb_SN_15:
864                         p_pdcp_lte_info->seqnum_length = 15;
865                         break;
866                     case PDCP_drb_SN_18:
867                         p_pdcp_lte_info->seqnum_length = 18;
868                         break;
869                     case PDCP_drb_SN_signalled:
870                         /* Use whatever was signalled (e.g. in RRC) */
871                         id = (rlc_info->channelId << 16) | rlc_info->ueid;
872                         key[0].length = 1;
873                         key[0].key = &id;
874                         key[1].length = 1;
875                         key[1].key = &pinfo->num;
876                         key[2].length = 0;
877                         key[2].key = NULL;
878
879                         params = (rlc_ue_parameters *)wmem_tree_lookup32_array_le(ue_parameters_tree, key);
880                         if (params && (params->id != id)) {
881                             params = NULL;
882                         }
883                         if (params) {
884                             p_pdcp_lte_info->seqnum_length = params->pdcp_sn_bits;
885                         } else if (rlc_info->nbMode == rlc_nb_mode) {
886                             p_pdcp_lte_info->seqnum_length = 7;
887                         } else {
888                             p_pdcp_lte_info->seqnum_length = 12;
889                         }
890                         break;
891
892                     default:
893                         DISSECTOR_ASSERT(FALSE);
894                         break;
895                 }
896             }
897
898             TRY {
899                 call_dissector_only(pdcp_lte_handle, pdcp_tvb, pinfo, tree, NULL);
900             }
901             CATCH_ALL {
902             }
903             ENDTRY
904
905             PROTO_ITEM_SET_HIDDEN(data_ti);
906         }
907         else if (global_rlc_lte_call_rrc_for_mcch && (rlc_info->channelType == CHANNEL_TYPE_MCCH)) {
908             /* Send whole PDU to RRC */
909             static tvbuff_t *rrc_tvb = NULL;
910
911             /* Get tvb for passing to LTE RRC dissector */
912             if (reassembly_info == NULL) {
913                 rrc_tvb = tvb_new_subset_length(tvb, offset, length);
914             }
915             else {
916                 /* Get combined tvb. */
917                 rrc_tvb = reassembly_get_reassembled_tvb(reassembly_info, tvb, pinfo);
918                 reassembly_show_source(reassembly_info, tree, tvb, offset);
919             }
920
921             TRY {
922                 call_dissector_only(lte_rrc_mcch, rrc_tvb, pinfo, tree, NULL);
923             }
924             CATCH_ALL {
925             }
926             ENDTRY
927
928             PROTO_ITEM_SET_HIDDEN(data_ti);
929         }
930         else if (global_rlc_lte_call_ip_for_mtch && (rlc_info->channelType == CHANNEL_TYPE_MTCH)) {
931             /* Send whole PDU to IP */
932             static tvbuff_t *ip_tvb = NULL;
933
934             /* Get tvb for passing to IP dissector */
935             if (reassembly_info == NULL) {
936                 ip_tvb = tvb_new_subset_length(tvb, offset, length);
937             }
938             else {
939                 /* Get combined tvb. */
940                 ip_tvb = reassembly_get_reassembled_tvb(reassembly_info, tvb, pinfo);
941                 reassembly_show_source(reassembly_info, tree, tvb, offset);
942             }
943
944             TRY {
945                 call_dissector_only(ip_handle, ip_tvb, pinfo, tree, NULL);
946             }
947             CATCH_ALL {
948             }
949             ENDTRY
950
951             PROTO_ITEM_SET_HIDDEN(data_ti);
952         }
953     }
954 }
955
956 /* Hash table functions for RLC channels */
957
958 /* Equal keys */
959 static gint rlc_channel_equal(gconstpointer v, gconstpointer v2)
960 {
961     const channel_hash_key* val1 = (const channel_hash_key *)v;
962     const channel_hash_key* val2 = (const channel_hash_key *)v2;
963
964     /* All fields must match */
965     /* N.B. Currently fits into one word, so could return (*v == *v2)
966        if we're sure they're initialised to 0... */
967     return ((val1->ueId        == val2->ueId) &&
968             (val1->channelType == val2->channelType) &&
969             (val1->channelId   == val2->channelId) &&
970             (val1->direction   == val2->direction));
971 }
972
973 /* Compute a hash value for a given key. */
974 static guint rlc_channel_hash_func(gconstpointer v)
975 {
976     const channel_hash_key* val1 = (const channel_hash_key *)v;
977
978     /* TODO: check/reduce multipliers */
979     return ((val1->ueId * 1024) + (val1->channelType*64) + (val1->channelId*2) + val1->direction);
980 }
981
982
983 /*************************************************************************/
984 /* Result hash                                                           */
985
986 typedef struct {
987     guint32           frameNumber;
988     guint32           SN :             10;
989     guint32           channelType :    2;
990     guint32           channelId:       5;
991     guint32           direction:       1;
992 } rlc_result_hash_key;
993
994 /* Compare 2 rlc_result_hash_key structs */
995 static gint rlc_result_hash_equal(gconstpointer v, gconstpointer v2)
996 {
997     const rlc_result_hash_key *val1 = (const rlc_result_hash_key *)v;
998     const rlc_result_hash_key *val2 = (const rlc_result_hash_key *)v2;
999
1000     /* All fields (and any padding...) must match */
1001     return (memcmp(val1, val2, sizeof(rlc_result_hash_key)) == 0);
1002 }
1003
1004 /* Compute a hash value for a given key. */
1005 static guint rlc_result_hash_func(gconstpointer v)
1006 {
1007     const rlc_result_hash_key* val1 = (const rlc_result_hash_key *)v;
1008
1009     /* Got rid of multipliers - no evidence that they reduced collisions */
1010     return val1->frameNumber + val1->SN +
1011                                val1->channelType +
1012                                val1->channelId +
1013                                val1->direction;
1014 }
1015
1016 /* Convenience function to get a pointer for the hash_func to work with */
1017 static gpointer get_report_hash_key(guint16 SN, guint32 frameNumber,
1018                                     rlc_lte_info *p_rlc_lte_info,
1019                                     gboolean do_persist)
1020 {
1021     static rlc_result_hash_key key;
1022     rlc_result_hash_key *p_key;
1023
1024     /* Only allocate a struct when will be adding entry */
1025     if (do_persist) {
1026         p_key = wmem_new0(wmem_file_scope(), rlc_result_hash_key);
1027     }
1028     else {
1029         memset(&key, 0, sizeof(rlc_result_hash_key));
1030         p_key = &key;
1031     }
1032
1033     /* Fill in details, and return pointer */
1034     p_key->frameNumber = frameNumber;
1035     p_key->SN = SN;
1036     p_key->channelType = p_rlc_lte_info->channelType;
1037     p_key->channelId = p_rlc_lte_info->channelId;
1038     p_key->direction = p_rlc_lte_info->direction;
1039
1040     return p_key;
1041 }
1042
1043 static void checkFIconsistency(sequence_analysis_report *p,
1044                                rlc_lte_info *p_rlc_lte_info,
1045                                gboolean  newSegmentStarted,
1046                                proto_tree *seqnum_tree,
1047                                packet_info *pinfo, tvbuff_t *tvb)
1048 {
1049     proto_item *ti;
1050
1051     if (p->previousSegmentIncomplete) {
1052         /* Previous segment was incomplete, so this PDU should continue it */
1053         if (newSegmentStarted) {
1054             ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_framing_info_correct,
1055                                          tvb, 0, 0, FALSE);
1056             expert_add_info_format(pinfo, ti, &ei_rlc_lte_sequence_analysis_last_segment_not_continued,
1057                                    "Last segment of previous PDU was not continued for UE %u (%s-%u)",
1058                                    p_rlc_lte_info->ueid,
1059                                    val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
1060                                    p_rlc_lte_info->channelId);
1061         }
1062         else {
1063            ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_framing_info_correct,
1064                                        tvb, 0, 0, TRUE);
1065            PROTO_ITEM_SET_HIDDEN(ti);
1066         }
1067     }
1068     else {
1069         /* Previous segment was complete, so this PDU should start a new one */
1070         if (!newSegmentStarted) {
1071             ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_framing_info_correct,
1072                                         tvb, 0, 0, FALSE);
1073             expert_add_info_format(pinfo, ti, &ei_rlc_lte_sequence_analysis_last_segment_complete,
1074                                    "Last segment of previous PDU was complete, but new segment was not started on UE %u (%s-%u)",
1075                                    p_rlc_lte_info->ueid,
1076                                    val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
1077                                    p_rlc_lte_info->channelId);
1078         }
1079         else {
1080            ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_framing_info_correct,
1081                                        tvb, 0, 0, TRUE);
1082            PROTO_ITEM_SET_HIDDEN(ti);
1083         }
1084     }
1085     PROTO_ITEM_SET_GENERATED(ti);
1086 }
1087
1088 /* Add to the tree values associated with sequence analysis for this frame */
1089 static void addChannelSequenceInfo(sequence_analysis_report *p,
1090                                    gboolean isControlFrame,
1091                                    rlc_lte_info *p_rlc_lte_info,
1092                                    guint16   sequenceNumber,
1093                                    gboolean  newSegmentStarted,
1094                                    rlc_lte_tap_info *tap_info,
1095                                    packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb)
1096 {
1097     proto_tree *seqnum_tree;
1098     proto_item *seqnum_ti;
1099     proto_item *ti;
1100
1101     /* Create subtree */
1102     seqnum_ti = proto_tree_add_string_format(tree,
1103                                              hf_rlc_lte_sequence_analysis,
1104                                              tvb, 0, 0,
1105                                              "", "Sequence Analysis");
1106     seqnum_tree = proto_item_add_subtree(seqnum_ti,
1107                                          ett_rlc_lte_sequence_analysis);
1108     PROTO_ITEM_SET_GENERATED(seqnum_ti);
1109
1110     if (p->previousFrameNum != 0) {
1111         ti = proto_tree_add_uint(seqnum_tree, hf_rlc_lte_sequence_analysis_previous_frame,
1112                                  tvb, 0, 0, p->previousFrameNum);
1113         PROTO_ITEM_SET_GENERATED(ti);
1114     }
1115
1116     switch (p_rlc_lte_info->rlcMode) {
1117         case RLC_AM_MODE:
1118
1119             /********************************************/
1120             /* AM                                       */
1121             /********************************************/
1122
1123             switch (p->state) {
1124                 case SN_OK:
1125                     if (isControlFrame) {
1126                         return;
1127                     }
1128
1129                     ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ok,
1130                                                 tvb, 0, 0, TRUE);
1131                     PROTO_ITEM_SET_GENERATED(ti);
1132                     proto_item_append_text(seqnum_ti, " - OK");
1133
1134                     /* Link to next SN in channel (if known) */
1135                     if (p->nextFrameNum != 0) {
1136                         proto_tree_add_uint(seqnum_tree, hf_rlc_lte_sequence_analysis_next_frame,
1137                                             tvb, 0, 0, p->nextFrameNum);
1138                     }
1139                     /* Correct sequence number, so check frame indication bits consistent */
1140                     /* Deactivated for now as it gets confused by resegmentation */
1141                     /* checkFIconsistency(p, p_rlc_lte_info, newSegmentStarted, seqnum_tree, pinfo, tvb); */
1142                     break;
1143
1144                 case SN_MAC_Retx:
1145                     if (isControlFrame) {
1146                         return;
1147                     }
1148
1149                     ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ok,
1150                                                 tvb, 0, 0, FALSE);
1151                     PROTO_ITEM_SET_GENERATED(ti);
1152                     ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_mac_retx,
1153                                                 tvb, 0, 0, TRUE);
1154                     PROTO_ITEM_SET_GENERATED(ti);
1155                     expert_add_info_format(pinfo, ti, &ei_rlc_lte_sequence_analysis_mac_retx,
1156                                            "AM Frame retransmitted for %s on UE %u - due to MAC retx! (%s-%u)",
1157                                            val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
1158                                            p_rlc_lte_info->ueid,
1159                                            val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
1160                                            p_rlc_lte_info->channelId);
1161                     proto_item_append_text(seqnum_ti, " - MAC retx of SN %u", p->firstSN);
1162                     break;
1163
1164                 case SN_Retx:
1165                     if (isControlFrame) {
1166                         return;
1167                     }
1168
1169                     ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ok,
1170                                                 tvb, 0, 0, FALSE);
1171                     PROTO_ITEM_SET_GENERATED(ti);
1172                     ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_retx,
1173                                                 tvb, 0, 0, TRUE);
1174                     PROTO_ITEM_SET_GENERATED(ti);
1175                     expert_add_info_format(pinfo, ti, &ei_rlc_lte_sequence_analysis_retx,
1176                                            "AM Frame retransmitted for %s on UE %u - most likely in response to NACK (%s-%u)",
1177                                            val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
1178                                            p_rlc_lte_info->ueid,
1179                                            val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
1180                                            p_rlc_lte_info->channelId);
1181                     proto_item_append_text(seqnum_ti, " - SN %u retransmitted", p->firstSN);
1182                     break;
1183
1184                 case SN_Repeated:
1185                     if (isControlFrame) {
1186                         return;
1187                     }
1188
1189                     ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ok,
1190                                                 tvb, 0, 0, FALSE);
1191                     PROTO_ITEM_SET_GENERATED(ti);
1192                     ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_repeated,
1193                                                 tvb, 0, 0, TRUE);
1194                     PROTO_ITEM_SET_GENERATED(ti);
1195                     expert_add_info_format(pinfo, ti, &ei_rlc_lte_sequence_analysis_repeated,
1196                                            "AM SN Repeated for %s for UE %u - probably because didn't receive Status PDU? (%s-%u)",
1197                                            val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
1198                                            p_rlc_lte_info->ueid,
1199                                            val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
1200                                            p_rlc_lte_info->channelId);
1201                     proto_item_append_text(seqnum_ti, "- SN %u Repeated", p->firstSN);
1202                     break;
1203
1204                 case SN_Missing:
1205                     if (isControlFrame) {
1206                         return;
1207                     }
1208
1209                     ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ok,
1210                                                 tvb, 0, 0, FALSE);
1211                     PROTO_ITEM_SET_GENERATED(ti);
1212                     ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_skipped,
1213                                                 tvb, 0, 0, TRUE);
1214                     PROTO_ITEM_SET_GENERATED(ti);
1215                     if (p->lastSN != p->firstSN) {
1216                         expert_add_info_format(pinfo, ti, &ei_rlc_lte_am_sn_missing,
1217                                                "AM SNs (%u to %u) missing for %s on UE %u (%s-%u)",
1218                                                p->firstSN, p->lastSN,
1219                                                val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
1220                                                p_rlc_lte_info->ueid,
1221                                                val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
1222                                                p_rlc_lte_info->channelId);
1223                         proto_item_append_text(seqnum_ti, " - SNs missing (%u to %u)",
1224                                                p->firstSN, p->lastSN);
1225                         if (p_rlc_lte_info->sequenceNumberLength == AM_SN_LENGTH_16_BITS) {
1226                             tap_info->missingSNs = ((65536 + (guint32)p->lastSN - (guint32)p->firstSN) % 65536) + 1;
1227                         } else {
1228                             tap_info->missingSNs = ((1024 + p->lastSN - p->firstSN) % 1024) + 1;
1229                         }
1230                     }
1231                     else {
1232                         expert_add_info_format(pinfo, ti, &ei_rlc_lte_am_sn_missing,
1233                                                "AM SN (%u) missing for %s on UE %u (%s-%u)",
1234                                                p->firstSN,
1235                                                val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
1236                                                p_rlc_lte_info->ueid,
1237                                                val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
1238                                                p_rlc_lte_info->channelId);
1239                         proto_item_append_text(seqnum_ti, " - SN missing (%u)", p->firstSN);
1240                         tap_info->missingSNs = 1;
1241                     }
1242                     break;
1243
1244                 case ACK_Out_of_Window:
1245                     if (!isControlFrame) {
1246                         return;
1247                     }
1248
1249
1250                     /* Not OK */
1251                     ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ok,
1252                                                 tvb, 0, 0, FALSE);
1253                     /* Out of range */
1254                     PROTO_ITEM_SET_GENERATED(ti);
1255                     ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ack_out_of_range,
1256                                                 tvb, 0, 0, TRUE);
1257                     PROTO_ITEM_SET_GENERATED(ti);
1258
1259                     /* Link back to last seen SN in other direction */
1260                     ti = proto_tree_add_uint(seqnum_tree, hf_rlc_lte_sequence_analysis_ack_out_of_range_opposite_frame,
1261                                              tvb, 0, 0, p->previousFrameNum);
1262                     PROTO_ITEM_SET_GENERATED(ti);
1263
1264                     /* Expert error */
1265                     expert_add_info_format(pinfo, ti, &ei_rlc_lte_sequence_analysis_ack_out_of_range_opposite_frame,
1266                                            "AM ACK for SN %u - but last received SN in other direction is %u for UE %u (%s-%u)",
1267                                            p->firstSN, p->sequenceExpected,
1268                                            p_rlc_lte_info->ueid,
1269                                            val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
1270                                            p_rlc_lte_info->channelId);
1271                     proto_item_append_text(seqnum_ti, "- ACK SN %u Outside Rx Window - last received SN is %u",
1272                                            p->firstSN, p->sequenceExpected);
1273
1274                     break;
1275
1276                 default:
1277                     return;
1278             }
1279             break;
1280
1281         case RLC_UM_MODE:
1282
1283             /********************************************/
1284             /* UM                                       */
1285             /********************************************/
1286
1287             /* Expected sequence number */
1288             ti = proto_tree_add_uint(seqnum_tree, hf_rlc_lte_sequence_analysis_expected_sn,
1289                                     tvb, 0, 0, p->sequenceExpected);
1290             PROTO_ITEM_SET_GENERATED(ti);
1291             if (p->sequenceExpectedCorrect) {
1292                 PROTO_ITEM_SET_HIDDEN(ti);
1293             }
1294
1295             if (!p->sequenceExpectedCorrect) {
1296                 /* Work out SN wrap (in case needed below) */
1297                 guint16 snLimit;
1298                 if (p_rlc_lte_info->sequenceNumberLength == UM_SN_LENGTH_5_BITS) {
1299                     snLimit = 32;
1300                 }
1301                 else {
1302                     snLimit = 1024;
1303                 }
1304
1305                 switch (p->state) {
1306                     case SN_Missing:
1307                         ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ok,
1308                                                     tvb, 0, 0, FALSE);
1309                         PROTO_ITEM_SET_GENERATED(ti);
1310                         ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_skipped,
1311                                                     tvb, 0, 0, TRUE);
1312                         PROTO_ITEM_SET_GENERATED(ti);
1313                         if (p->lastSN != p->firstSN) {
1314                             expert_add_info_format(pinfo, ti, &ei_rlc_lte_um_sn_missing,
1315                                                    "UM SNs (%u to %u) missing for %s on UE %u (%s-%u)",
1316                                                    p->firstSN, p->lastSN,
1317                                                    val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
1318                                                    p_rlc_lte_info->ueid,
1319                                                    val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
1320                                                    p_rlc_lte_info->channelId);
1321                             proto_item_append_text(seqnum_ti, " - SNs missing (%u to %u)",
1322                                                    p->firstSN, p->lastSN);
1323                             tap_info->missingSNs = ((snLimit + p->lastSN - p->firstSN) % snLimit) + 1;
1324                         }
1325                         else {
1326                             expert_add_info_format(pinfo, ti, &ei_rlc_lte_um_sn_missing,
1327                                                    "UM SN (%u) missing for %s on UE %u (%s-%u)",
1328                                                    p->firstSN,
1329                                                    val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
1330                                                    p_rlc_lte_info->ueid,
1331                                                    val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
1332                                                    p_rlc_lte_info->channelId);
1333                             proto_item_append_text(seqnum_ti, " - SN missing (%u)",
1334                                                    p->firstSN);
1335                             tap_info->missingSNs = 1;
1336                         }
1337                         break;
1338
1339                     case SN_Repeated:
1340                         ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ok,
1341                                                     tvb, 0, 0, FALSE);
1342                         PROTO_ITEM_SET_GENERATED(ti);
1343                         ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_repeated,
1344                                                     tvb, 0, 0, TRUE);
1345                         PROTO_ITEM_SET_GENERATED(ti);
1346                         expert_add_info_format(pinfo, ti, &ei_rlc_lte_um_sn_repeated,
1347                                                "UM SN (%u) repeated for %s for UE %u (%s-%u)",
1348                                                p->firstSN,
1349                                                val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
1350                                                p_rlc_lte_info->ueid,
1351                                                val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
1352                                                p_rlc_lte_info->channelId);
1353                         proto_item_append_text(seqnum_ti, "- SN %u Repeated",
1354                                                p->firstSN);
1355                         break;
1356
1357                     case SN_MAC_Retx:
1358                         ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ok,
1359                                                     tvb, 0, 0, FALSE);
1360                         PROTO_ITEM_SET_GENERATED(ti);
1361                         ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_mac_retx,
1362                                                     tvb, 0, 0, TRUE);
1363                         PROTO_ITEM_SET_GENERATED(ti);
1364                         expert_add_info_format(pinfo, ti, &ei_rlc_lte_sequence_analysis_mac_retx,
1365                                                "UM Frame retransmitted for %s on UE %u - due to MAC retx! (%s-%u)",
1366                                                val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
1367                                                p_rlc_lte_info->ueid,
1368                                                val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
1369                                                p_rlc_lte_info->channelId);
1370                         break;
1371
1372                     default:
1373                         /* Incorrect sequence number */
1374                         expert_add_info_format(pinfo, ti, &ei_rlc_lte_wrong_sequence_number,
1375                                                "Wrong Sequence Number for %s on UE %u - got %u, expected %u (%s-%u)",
1376                                                val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
1377                                                p_rlc_lte_info->ueid, sequenceNumber, p->sequenceExpected,
1378                                                val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
1379                                                p_rlc_lte_info->channelId);
1380
1381                         break;
1382                 }
1383
1384             }
1385             else {
1386                 /* Correct sequence number, so check frame indication bits consistent */
1387                 checkFIconsistency(p, p_rlc_lte_info, newSegmentStarted, seqnum_tree, pinfo, tvb);
1388
1389                 /* Set OK here! */
1390                 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ok,
1391                                             tvb, 0, 0, TRUE);
1392                 PROTO_ITEM_SET_GENERATED(ti);
1393                 proto_item_append_text(seqnum_ti, " - OK");
1394             }
1395
1396             /* Next channel frame */
1397             if (p->nextFrameNum != 0) {
1398                 ti = proto_tree_add_uint(seqnum_tree, hf_rlc_lte_sequence_analysis_next_frame,
1399                                          tvb, 0, 0, p->nextFrameNum);
1400                 PROTO_ITEM_SET_GENERATED(ti);
1401             }
1402     }
1403 }
1404
1405 /* Update the channel status and set report for this frame */
1406 static sequence_analysis_state checkChannelSequenceInfo(packet_info *pinfo, tvbuff_t *tvb,
1407                                                         rlc_lte_info *p_rlc_lte_info,
1408                                                         gboolean isControlFrame,
1409                                                         guint8 number_of_segments,
1410                                                         guint16 firstSegmentOffset,
1411                                                         guint16 firstSegmentLength,
1412                                                         guint16 lastSegmentOffset,
1413                                                         guint16 sequenceNumber,
1414                                                         gboolean first_includes_start, gboolean last_includes_end,
1415                                                         gboolean is_resegmented _U_,
1416                                                         rlc_lte_tap_info *tap_info,
1417                                                         proto_tree *tree)
1418 {
1419     channel_hash_key   channel_key;
1420     channel_hash_key   *p_channel_key;
1421     channel_sequence_analysis_status     *p_channel_status;
1422     sequence_analysis_report *p_report_in_frame = NULL;
1423     gboolean               createdChannel = FALSE;
1424     guint16                expectedSequenceNumber = 0;
1425     guint32                snLimit = 0;
1426
1427     /* If find stat_report_in_frame already, use that and get out */
1428     if (pinfo->fd->flags.visited) {
1429         p_report_in_frame = (sequence_analysis_report*)wmem_map_lookup(sequence_analysis_report_hash,
1430                                                                            get_report_hash_key(sequenceNumber,
1431                                                                                                pinfo->num,
1432                                                                                                p_rlc_lte_info,
1433                                                                                                FALSE));
1434         if (p_report_in_frame != NULL) {
1435             addChannelSequenceInfo(p_report_in_frame, isControlFrame, p_rlc_lte_info,
1436                                    sequenceNumber, first_includes_start,
1437                                    tap_info, pinfo, tree, tvb);
1438             return p_report_in_frame->state;
1439         }
1440
1441         /* Don't just give up here... */
1442     }
1443
1444
1445     /**************************************************/
1446     /* Create or find an entry for this channel state */
1447     channel_key.ueId = p_rlc_lte_info->ueid;
1448     channel_key.channelType = p_rlc_lte_info->channelType;
1449     channel_key.channelId = p_rlc_lte_info->channelId;
1450     channel_key.direction = p_rlc_lte_info->direction;
1451
1452     /* Do the table lookup */
1453     p_channel_status = (channel_sequence_analysis_status*)wmem_map_lookup(sequence_analysis_channel_hash, &channel_key);
1454
1455     /* Create table entry if necessary */
1456     if (p_channel_status == NULL) {
1457         createdChannel = TRUE;
1458
1459         /* Allocate a new value and duplicate key contents */
1460         p_channel_status = wmem_new0(wmem_file_scope(), channel_sequence_analysis_status);
1461         p_channel_key = (channel_hash_key *)wmem_memdup(wmem_file_scope(), &channel_key, sizeof(channel_hash_key));
1462
1463         /* Set mode */
1464         p_channel_status->rlcMode = p_rlc_lte_info->rlcMode;
1465
1466         /* Add entry */
1467         wmem_map_insert(sequence_analysis_channel_hash, p_channel_key, p_channel_status);
1468     }
1469
1470     /* Create space for frame state_report */
1471     p_report_in_frame = wmem_new0(wmem_file_scope(), sequence_analysis_report);
1472
1473
1474     /* Deal with according to channel mode */
1475     switch (p_channel_status->rlcMode) {
1476         case RLC_UM_MODE:
1477
1478             if (p_rlc_lte_info->sequenceNumberLength == UM_SN_LENGTH_5_BITS) {
1479                 snLimit = 32;
1480             }
1481             else {
1482                 snLimit = 1024;
1483             }
1484
1485             /* Work out expected sequence number */
1486             if (!createdChannel) {
1487                 expectedSequenceNumber = (p_channel_status->previousSequenceNumber + 1) % snLimit;
1488             }
1489             else {
1490                 /* Whatever we got is fine.. */
1491                 expectedSequenceNumber = sequenceNumber;
1492             }
1493
1494             if ((sequenceNumber == 0) &&
1495                 ((p_rlc_lte_info->channelType == CHANNEL_TYPE_MCCH) || (p_rlc_lte_info->channelType == CHANNEL_TYPE_MTCH))) {
1496                 /* With eMBMS, SN restarts to 0 at each MCH Scheduling Period so we cannot deduce easily whether
1497                    there was a PDU loss or not without analysing the Frame Indicator; assume no loss when seeing 0 */
1498                 expectedSequenceNumber = 0;
1499             }
1500
1501             /* Set report for this frame */
1502             /* For UM, sequence number is always expectedSequence number */
1503             p_report_in_frame->sequenceExpectedCorrect = (sequenceNumber == expectedSequenceNumber);
1504
1505             /* For wrong sequence number... */
1506             if (!p_report_in_frame->sequenceExpectedCorrect) {
1507
1508                 /* Don't get confused by MAC (HARQ) retx */
1509                 if (is_mac_lte_frame_retx(pinfo, p_rlc_lte_info->direction)) {
1510                     p_report_in_frame->state = SN_MAC_Retx;
1511                     p_report_in_frame->firstSN = sequenceNumber;
1512
1513                     /* No channel state to update */
1514                     break;
1515                 }
1516
1517                 /* Frames are not missing if we get an earlier sequence number again */
1518                 /* TODO: taking time into account would give better idea of whether missing or repeated... */
1519                 else if ((p_rlc_lte_info->channelType == CHANNEL_TYPE_MCCH) || (p_rlc_lte_info->channelType == CHANNEL_TYPE_MTCH) ||
1520                          (((snLimit + sequenceNumber - expectedSequenceNumber) % snLimit) < 10)) {
1521                     reassembly_destroy(p_channel_status);
1522
1523                     p_report_in_frame->state = SN_Missing;
1524                     tap_info->missingSNs = (snLimit + sequenceNumber - expectedSequenceNumber) % snLimit;
1525                     p_report_in_frame->firstSN = expectedSequenceNumber;
1526                     p_report_in_frame->lastSN = (snLimit + sequenceNumber - 1) % snLimit;
1527
1528                     p_report_in_frame->sequenceExpected = expectedSequenceNumber;
1529                     p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
1530                     p_report_in_frame->previousSegmentIncomplete = p_channel_status->previousSegmentIncomplete;
1531
1532                     /* Update channel status to remember *this* frame */
1533                     p_channel_status->previousFrameNum = pinfo->num;
1534                     p_channel_status->previousSequenceNumber = sequenceNumber;
1535                     p_channel_status->previousSegmentIncomplete = !last_includes_end;
1536                 }
1537                 else {
1538                     /* An SN has been repeated */
1539                     p_report_in_frame->state = SN_Repeated;
1540                     p_report_in_frame->firstSN = sequenceNumber;
1541
1542                     p_report_in_frame->sequenceExpected = expectedSequenceNumber;
1543                     p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
1544                 }
1545             }
1546             else {
1547                 /* SN was OK */
1548                 p_report_in_frame->sequenceExpected = expectedSequenceNumber;
1549                 p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
1550                 p_report_in_frame->previousSegmentIncomplete = p_channel_status->previousSegmentIncomplete;
1551
1552                 /* Update channel status to remember *this* frame */
1553                 p_channel_status->previousFrameNum = pinfo->num;
1554                 p_channel_status->previousSequenceNumber = sequenceNumber;
1555                 p_channel_status->previousSegmentIncomplete = !last_includes_end;
1556
1557                 if (p_channel_status->reassembly_info) {
1558                     /* Add next segment to reassembly info */
1559                     reassembly_add_segment(p_channel_status, sequenceNumber, pinfo->num,
1560                                            tvb, firstSegmentOffset, firstSegmentLength);
1561
1562                     /* The end of existing reassembly? */
1563                     if (!first_includes_start &&
1564                         ((number_of_segments > 1) || last_includes_end)) {
1565
1566                         reassembly_record(p_channel_status, pinfo, sequenceNumber, p_rlc_lte_info);
1567                         reassembly_destroy(p_channel_status);
1568                     }
1569                 }
1570
1571                 /* The start of a new reassembly? */
1572                 if (!last_includes_end &&
1573                     ((number_of_segments > 1) || first_includes_start)) {
1574
1575                     guint16 lastSegmentLength = tvb_reported_length(tvb)-lastSegmentOffset;
1576
1577                     if (global_rlc_lte_reassembly) {
1578                         reassembly_reset(p_channel_status);
1579                         reassembly_add_segment(p_channel_status, sequenceNumber,
1580                                                pinfo->num,
1581                                                tvb, lastSegmentOffset, lastSegmentLength);
1582                     }
1583                 }
1584
1585                 if (p_report_in_frame->previousFrameNum != 0) {
1586                     /* Get report for previous frame */
1587                     sequence_analysis_report *p_previous_report;
1588                     if (p_rlc_lte_info->sequenceNumberLength == UM_SN_LENGTH_5_BITS) {
1589                         snLimit = 32;
1590                     }
1591                     else {
1592                         snLimit = 1024;
1593                     }
1594
1595                     /* Look up report for previous SN */
1596                     p_previous_report = (sequence_analysis_report*)wmem_map_lookup(sequence_analysis_report_hash,
1597                                                                                        get_report_hash_key((sequenceNumber+snLimit-1) % snLimit,
1598                                                                                                            p_report_in_frame->previousFrameNum,
1599                                                                                                            p_rlc_lte_info,
1600                                                                                                            FALSE));
1601                     /* It really shouldn't be NULL... */
1602                     if (p_previous_report != NULL) {
1603                         /* Point it forward to this one */
1604                         p_previous_report->nextFrameNum = pinfo->num;
1605                     }
1606                 }
1607             }
1608
1609             break;
1610
1611         case RLC_AM_MODE:
1612
1613             if (p_rlc_lte_info->sequenceNumberLength == AM_SN_LENGTH_16_BITS) {
1614                 snLimit = 65536;
1615             } else {
1616                 snLimit = 1024;
1617             }
1618
1619             /* Work out expected sequence number */
1620             if (!createdChannel) {
1621                 expectedSequenceNumber = (p_channel_status->previousSequenceNumber + 1) % snLimit;
1622             }
1623             else {
1624                 /* Whatever we got is fine.. */
1625                 expectedSequenceNumber = sequenceNumber;
1626             }
1627
1628             /* For AM, may be:
1629                - expected Sequence number OR
1630                - previous frame repeated
1631                - old SN being sent (in response to NACK)
1632                - new SN, but with frames missed out
1633                Assume window whose front is at expectedSequenceNumber */
1634
1635             /* First of all, check to see whether frame is judged to be MAC Retx */
1636             if (is_mac_lte_frame_retx(pinfo, p_rlc_lte_info->direction)) {
1637                 /* Just report that this is a MAC Retx */
1638                 p_report_in_frame->state = SN_MAC_Retx;
1639                 p_report_in_frame->firstSN = sequenceNumber;
1640
1641                 /* No channel state to update */
1642                 break;
1643             }
1644
1645             if (sequenceNumber != expectedSequenceNumber) {
1646                 /* Don't trash reassembly info if this looks like a close  retx... */
1647                 if (((snLimit + sequenceNumber - expectedSequenceNumber) % snLimit) < 50) {
1648                     reassembly_destroy(p_channel_status);
1649                 }
1650             }
1651
1652             /* Expected? */
1653             if (sequenceNumber == expectedSequenceNumber) {
1654                 /* Set report for this frame */
1655                 p_report_in_frame->sequenceExpectedCorrect = TRUE;
1656                 p_report_in_frame->sequenceExpected = expectedSequenceNumber;
1657                 p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
1658                 p_report_in_frame->previousSegmentIncomplete = p_channel_status->previousSegmentIncomplete;
1659                 p_report_in_frame->state = SN_OK;
1660
1661                 /* Update channel status */
1662                 p_channel_status->previousSequenceNumber = sequenceNumber;
1663                 p_channel_status->previousFrameNum = pinfo->num;
1664                 p_channel_status->previousSegmentIncomplete = !last_includes_end;
1665
1666
1667                 if (p_channel_status->reassembly_info) {
1668
1669                     /* Add next segment to reassembly info */
1670                     reassembly_add_segment(p_channel_status, sequenceNumber, pinfo->num,
1671                                            tvb, firstSegmentOffset, firstSegmentLength);
1672
1673                     /* The end of existing reassembly? */
1674                     if (!first_includes_start &&
1675                         ((number_of_segments > 1) || last_includes_end)) {
1676
1677                         reassembly_record(p_channel_status, pinfo,
1678                                           sequenceNumber, p_rlc_lte_info);
1679                         reassembly_destroy(p_channel_status);
1680                     }
1681                 }
1682
1683                 /* The start of a new reassembly? */
1684                 if (!last_includes_end &&
1685                     ((number_of_segments > 1) || first_includes_start)) {
1686
1687                     guint16 lastSegmentLength = tvb_reported_length(tvb)-lastSegmentOffset;
1688                     if (global_rlc_lte_reassembly) {
1689                         reassembly_reset(p_channel_status);
1690                         reassembly_add_segment(p_channel_status, sequenceNumber,
1691                                                pinfo->num,
1692                                                tvb, lastSegmentOffset, lastSegmentLength);
1693                     }
1694                 }
1695
1696                 if (p_report_in_frame->previousFrameNum != 0) {
1697                     /* Get report for previous frame */
1698                     sequence_analysis_report *p_previous_report;
1699                     p_previous_report = (sequence_analysis_report*)wmem_map_lookup(sequence_analysis_report_hash,
1700                                                                                        get_report_hash_key((sequenceNumber+snLimit-1) % snLimit,
1701                                                                                                            p_report_in_frame->previousFrameNum,
1702                                                                                                            p_rlc_lte_info,
1703                                                                                                            FALSE));
1704                     /* It really shouldn't be NULL... */
1705                     if (p_previous_report != NULL) {
1706                         /* Point it forward to this one */
1707                         p_previous_report->nextFrameNum = pinfo->num;
1708                     }
1709                 }
1710
1711             }
1712
1713             /* Previous subframe repeated? */
1714             else if (((sequenceNumber+1) % snLimit) == expectedSequenceNumber) {
1715                 p_report_in_frame->state = SN_Repeated;
1716
1717                 /* Set report for this frame */
1718                 p_report_in_frame->sequenceExpectedCorrect = FALSE;
1719                 p_report_in_frame->sequenceExpected = expectedSequenceNumber;
1720                 p_report_in_frame->firstSN = sequenceNumber;
1721                 p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
1722                 p_report_in_frame->previousSegmentIncomplete = p_channel_status->previousSegmentIncomplete;
1723
1724
1725                 /* Really should be nothing to update... */
1726                 p_channel_status->previousSequenceNumber = sequenceNumber;
1727                 p_channel_status->previousFrameNum = pinfo->num;
1728                 p_channel_status->previousSegmentIncomplete = !last_includes_end;
1729             }
1730
1731             else {
1732                 /* Need to work out if new (with skips, or likely a retx (due to NACK)) */
1733                 gint delta  = (snLimit + expectedSequenceNumber - sequenceNumber) % snLimit;
1734
1735                 /* Rx window is 512/32768, so check to see if this is a retx */
1736                 if (delta < (gint)(snLimit>>1)) {
1737                     /* Probably a retx due to receiving NACK */
1738                     p_report_in_frame->state = SN_Retx;
1739
1740                     p_report_in_frame->firstSN = sequenceNumber;
1741                     /* Don't update anything in channel state */
1742                 }
1743
1744                 else {
1745                     /* Ahead of expected SN. Assume frames have been missed */
1746                     p_report_in_frame->state = SN_Missing;
1747
1748                     p_report_in_frame->firstSN = expectedSequenceNumber;
1749                     p_report_in_frame->lastSN = (snLimit + sequenceNumber-1) % snLimit;
1750
1751                     /* Update channel state - forget about missed SNs */
1752                     p_report_in_frame->sequenceExpected = expectedSequenceNumber;
1753                     p_channel_status->previousSequenceNumber = sequenceNumber;
1754                     p_channel_status->previousFrameNum = pinfo->num;
1755                     p_channel_status->previousSegmentIncomplete = !last_includes_end;
1756                 }
1757             }
1758             break;
1759
1760         default:
1761             /* Shouldn't get here! */
1762             return SN_Error;
1763     }
1764
1765     /* Associate with this frame number */
1766     wmem_map_insert(sequence_analysis_report_hash,
1767                         get_report_hash_key(sequenceNumber, pinfo->num, p_rlc_lte_info, TRUE),
1768                         p_report_in_frame);
1769
1770     /* Add state report for this frame into tree */
1771     addChannelSequenceInfo(p_report_in_frame, isControlFrame, p_rlc_lte_info, sequenceNumber,
1772                            first_includes_start, tap_info, pinfo, tree, tvb);
1773
1774     return p_report_in_frame->state;
1775 }
1776
1777
1778 /* Add to the tree values associated with sequence analysis for this frame */
1779 static void addChannelRepeatedNACKInfo(channel_repeated_nack_report *p,
1780                                        rlc_lte_info *p_rlc_lte_info,
1781                                        packet_info *pinfo, proto_tree *tree,
1782                                        tvbuff_t *tvb)
1783 {
1784     proto_tree *seqnum_tree;
1785     proto_item *seqnum_ti;
1786     proto_item *ti;
1787     gint       n;
1788
1789     /* Create subtree */
1790     seqnum_ti = proto_tree_add_string_format(tree,
1791                                              hf_rlc_lte_sequence_analysis,
1792                                              tvb, 0, 0,
1793                                              "", "Sequence Analysis");
1794     seqnum_tree = proto_item_add_subtree(seqnum_ti,
1795                                          ett_rlc_lte_sequence_analysis);
1796     PROTO_ITEM_SET_GENERATED(seqnum_ti);
1797
1798     /* OK = FALSE */
1799     ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ok,
1800                                 tvb, 0, 0, FALSE);
1801     PROTO_ITEM_SET_GENERATED(ti);
1802
1803     /* Add each repeated NACK as item & expert info */
1804     for (n=0; n < p->noOfNACKsRepeated; n++) {
1805
1806         ti = proto_tree_add_uint(seqnum_tree, hf_rlc_lte_sequence_analysis_repeated_nack,
1807                                  tvb, 0, 0, p->repeatedNACKs[n]);
1808         PROTO_ITEM_SET_GENERATED(ti);
1809
1810         expert_add_info_format(pinfo, ti, &ei_rlc_lte_sequence_analysis_repeated_nack,
1811                                "Same SN  (%u) NACKd for %s on UE %u in successive Status PDUs",
1812                                p->repeatedNACKs[n],
1813                                val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
1814                                p_rlc_lte_info->ueid);
1815     }
1816
1817     /* Link back to previous status report */
1818     ti = proto_tree_add_uint(seqnum_tree, hf_rlc_lte_sequence_analysis_repeated_nack_original_frame,
1819                              tvb, 0, 0, p->previousFrameNum);
1820     PROTO_ITEM_SET_GENERATED(ti);
1821
1822     /* Append count to sequence analysis root */
1823     proto_item_append_text(seqnum_ti, " - %u SNs repeated from previous Status PDU",
1824                            p->noOfNACKsRepeated);
1825 }
1826
1827
1828 /* Update the channel repeated NACK status and set report for this frame */
1829 static void checkChannelRepeatedNACKInfo(packet_info *pinfo,
1830                                          rlc_lte_info *p_rlc_lte_info,
1831                                          rlc_lte_tap_info *tap_info,
1832                                          proto_tree *tree,
1833                                          tvbuff_t *tvb)
1834 {
1835     channel_hash_key   channel_key;
1836     channel_hash_key   *p_channel_key;
1837     channel_repeated_nack_status     *p_channel_status;
1838     channel_repeated_nack_report  *p_report_in_frame = NULL;
1839
1840     guint16         noOfNACKsRepeated = 0;
1841     guint16         repeatedNACKs[MAX_NACKs];
1842     gint            n, i, j;
1843
1844     /* If find state_report_in_frame already, use that and get out */
1845     if (pinfo->fd->flags.visited) {
1846         p_report_in_frame = (channel_repeated_nack_report*)wmem_map_lookup(repeated_nack_report_hash,
1847                                                                                get_report_hash_key(0, pinfo->num,
1848                                                                                                    p_rlc_lte_info, FALSE));
1849         if (p_report_in_frame != NULL) {
1850             addChannelRepeatedNACKInfo(p_report_in_frame, p_rlc_lte_info,
1851                                        pinfo, tree, tvb);
1852             return;
1853         }
1854         else {
1855             /* Give up - we must have tried already... */
1856             return;
1857         }
1858     }
1859
1860
1861     /**************************************************/
1862     /* Create or find an entry for this channel state */
1863     channel_key.ueId = p_rlc_lte_info->ueid;
1864     channel_key.channelType = p_rlc_lte_info->channelType;
1865     channel_key.channelId = p_rlc_lte_info->channelId;
1866     channel_key.direction = p_rlc_lte_info->direction;
1867     memset(repeatedNACKs, 0, sizeof(repeatedNACKs));
1868
1869     /* Do the table lookup */
1870     p_channel_status = (channel_repeated_nack_status*)wmem_map_lookup(repeated_nack_channel_hash, &channel_key);
1871
1872     /* Create table entry if necessary */
1873     if (p_channel_status == NULL) {
1874
1875         /* Allocate a new key and value */
1876         p_channel_key = wmem_new(wmem_file_scope(), channel_hash_key);
1877         p_channel_status = wmem_new0(wmem_file_scope(), channel_repeated_nack_status);
1878
1879         /* Copy key contents */
1880         memcpy(p_channel_key, &channel_key, sizeof(channel_hash_key));
1881
1882         /* Add entry to table */
1883         wmem_map_insert(repeated_nack_channel_hash, p_channel_key, p_channel_status);
1884     }
1885
1886     /* Compare NACKs in channel status with NACKs in tap_info.
1887        Note any that are repeated */
1888     for (i=0; i < p_channel_status->noOfNACKs; i++) {
1889         for (j=0; j < MIN(tap_info->noOfNACKs, MAX_NACKs); j++) {
1890             if (tap_info->NACKs[j] == p_channel_status->NACKs[i]) {
1891                 /* Don't add the same repeated NACK twice! */
1892                 if ((noOfNACKsRepeated == 0) ||
1893                     (repeatedNACKs[noOfNACKsRepeated-1] != p_channel_status->NACKs[i])) {
1894
1895                     repeatedNACKs[noOfNACKsRepeated++] = p_channel_status->NACKs[i];
1896                 }
1897             }
1898         }
1899     }
1900
1901     /* Copy NACKs from tap_info into channel status for next time! */
1902     p_channel_status->noOfNACKs = 0;
1903     for (n=0; n < MIN(tap_info->noOfNACKs, MAX_NACKs); n++) {
1904         p_channel_status->NACKs[p_channel_status->noOfNACKs++] = tap_info->NACKs[n];
1905     }
1906
1907     if (noOfNACKsRepeated >= 1) {
1908         /* Create space for frame state_report */
1909         p_report_in_frame = wmem_new(wmem_file_scope(), channel_repeated_nack_report);
1910
1911         /* Copy in found duplicates */
1912         for (n=0; n < MIN(tap_info->noOfNACKs, MAX_NACKs); n++) {
1913             p_report_in_frame->repeatedNACKs[n] = repeatedNACKs[n];
1914         }
1915         p_report_in_frame->noOfNACKsRepeated = noOfNACKsRepeated;
1916
1917         p_report_in_frame->previousFrameNum = p_channel_status->frameNum;
1918
1919         /* Associate with this frame number */
1920         wmem_map_insert(repeated_nack_report_hash,
1921                             get_report_hash_key(0, pinfo->num,
1922                                                 p_rlc_lte_info, TRUE),
1923                             p_report_in_frame);
1924
1925         /* Add state report for this frame into tree */
1926         addChannelRepeatedNACKInfo(p_report_in_frame, p_rlc_lte_info,
1927                                    pinfo, tree, tvb);
1928     }
1929
1930     /* Save frame number for next comparison */
1931     p_channel_status->frameNum = pinfo->num;
1932 }
1933
1934 /* Check that the ACK is consistent with data the expected sequence number
1935    in the other direction */
1936 static void checkChannelACKWindow(guint16 ack_sn,
1937                                   packet_info *pinfo,
1938                                   rlc_lte_info *p_rlc_lte_info,
1939                                   rlc_lte_tap_info *tap_info,
1940                                   proto_tree *tree,
1941                                   tvbuff_t *tvb)
1942 {
1943     channel_hash_key   channel_key;
1944     channel_sequence_analysis_status  *p_channel_status;
1945     sequence_analysis_report  *p_report_in_frame = NULL;
1946     guint32 snLimit;
1947
1948     /* If find stat_report_in_frame already, use that and get out */
1949     if (pinfo->fd->flags.visited) {
1950         p_report_in_frame = (sequence_analysis_report*)wmem_map_lookup(sequence_analysis_report_hash,
1951                                                                            get_report_hash_key(0, pinfo->num,
1952                                                                                                p_rlc_lte_info,
1953                                                                                                FALSE));
1954         if (p_report_in_frame != NULL) {
1955             /* Add any info to tree */
1956             addChannelSequenceInfo(p_report_in_frame, TRUE, p_rlc_lte_info,
1957                                    0, FALSE,
1958                                    tap_info, pinfo, tree, tvb);
1959             return;
1960         }
1961         else {
1962             /* Give up - we must have tried already... */
1963             return;
1964         }
1965     }
1966
1967     /*******************************************************************/
1968     /* Find an entry for this channel state (in the opposite direction */
1969     channel_key.ueId = p_rlc_lte_info->ueid;
1970     channel_key.channelType = p_rlc_lte_info->channelType;
1971     channel_key.channelId = p_rlc_lte_info->channelId;
1972     channel_key.direction =
1973         (p_rlc_lte_info->direction == DIRECTION_UPLINK) ? DIRECTION_DOWNLINK : DIRECTION_UPLINK;
1974
1975     /* Do the table lookup */
1976     p_channel_status = (channel_sequence_analysis_status*)wmem_map_lookup(sequence_analysis_channel_hash, &channel_key);
1977
1978     /* Create table entry if necessary */
1979     if (p_channel_status == NULL) {
1980         return;
1981     }
1982
1983     /* Is it in the rx window? This test will catch if it's ahead, but we don't
1984        really know what the back of the tx window is... */
1985     snLimit = (p_rlc_lte_info->sequenceNumberLength == AM_SN_LENGTH_16_BITS) ? 65536 : 1024;
1986     if (((snLimit + (guint32)p_channel_status->previousSequenceNumber+1 - ack_sn) % snLimit) > (snLimit>>1)) {
1987
1988         /* Set result */
1989         p_report_in_frame = wmem_new0(wmem_file_scope(), sequence_analysis_report);
1990         p_report_in_frame->state = ACK_Out_of_Window;
1991         p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
1992         p_report_in_frame->sequenceExpected = p_channel_status->previousSequenceNumber;
1993         p_report_in_frame->firstSN = ack_sn;
1994
1995         /* Associate with this frame number */
1996         wmem_map_insert(sequence_analysis_report_hash,
1997                             get_report_hash_key(0, pinfo->num,
1998                                                 p_rlc_lte_info, TRUE),
1999                             p_report_in_frame);
2000
2001         /* Add state report for this frame into tree */
2002         addChannelSequenceInfo(p_report_in_frame, TRUE, p_rlc_lte_info, 0,
2003                                FALSE, tap_info, pinfo, tree, tvb);
2004     }
2005 }
2006
2007
2008
2009
2010 /***************************************************/
2011 /* Transparent mode PDU. Call RRC if configured to */
2012 static void dissect_rlc_lte_tm(tvbuff_t *tvb, packet_info *pinfo,
2013                                proto_tree *tree,
2014                                int offset,
2015                                rlc_lte_info *p_rlc_lte_info,
2016                                proto_item *top_ti)
2017 {
2018     proto_item *raw_tm_ti;
2019     proto_item *tm_ti;
2020
2021     /* Create hidden TM root */
2022     tm_ti = proto_tree_add_string_format(tree, hf_rlc_lte_tm,
2023                                          tvb, offset, 0, "", "TM");
2024     PROTO_ITEM_SET_HIDDEN(tm_ti);
2025
2026     /* Remaining bytes are all data */
2027     raw_tm_ti = proto_tree_add_item(tree, hf_rlc_lte_tm_data, tvb, offset, -1, ENC_NA);
2028     if (!global_rlc_lte_call_rrc_for_ccch) {
2029         write_pdu_label_and_info(top_ti, NULL, pinfo,
2030                                  "                     [%u-bytes]", tvb_reported_length_remaining(tvb, offset));
2031     }
2032
2033     if (global_rlc_lte_call_rrc_for_ccch) {
2034         tvbuff_t *rrc_tvb = tvb_new_subset_remaining(tvb, offset);
2035         volatile dissector_handle_t protocol_handle;
2036
2037         switch (p_rlc_lte_info->channelType) {
2038             case CHANNEL_TYPE_CCCH:
2039                 if (p_rlc_lte_info->direction == DIRECTION_UPLINK) {
2040                     protocol_handle = (p_rlc_lte_info->nbMode == rlc_nb_mode) ?
2041                                         lte_rrc_ul_ccch_nb : lte_rrc_ul_ccch;
2042                 }
2043                 else {
2044                     protocol_handle = (p_rlc_lte_info->nbMode == rlc_nb_mode) ?
2045                                         lte_rrc_dl_ccch_nb : lte_rrc_dl_ccch;
2046                 }
2047                 break;
2048
2049             case CHANNEL_TYPE_BCCH_BCH:
2050                 protocol_handle = (p_rlc_lte_info->nbMode == rlc_nb_mode) ?
2051                                     lte_rrc_bcch_bch_nb : lte_rrc_bcch_bch;
2052                 break;
2053             case CHANNEL_TYPE_BCCH_DL_SCH:
2054                 protocol_handle = (p_rlc_lte_info->nbMode == rlc_nb_mode) ?
2055                                     lte_rrc_bcch_dl_sch_nb : lte_rrc_bcch_dl_sch;
2056                 break;
2057             case CHANNEL_TYPE_PCCH:
2058                 protocol_handle = (p_rlc_lte_info->nbMode == rlc_nb_mode) ?
2059                                     lte_rrc_pcch_nb : lte_rrc_pcch;
2060                 break;
2061
2062             case CHANNEL_TYPE_SRB:
2063             case CHANNEL_TYPE_DRB:
2064             case CHANNEL_TYPE_MCCH:
2065             case CHANNEL_TYPE_MTCH:
2066
2067             default:
2068                 /* Shouldn't happen, just return... */
2069                 return;
2070         }
2071
2072         /* Hide raw view of bytes */
2073         PROTO_ITEM_SET_HIDDEN(raw_tm_ti);
2074
2075         /* Call it (catch exceptions) */
2076         TRY {
2077             call_dissector_only(protocol_handle, rrc_tvb, pinfo, tree, NULL);
2078         }
2079         CATCH_ALL {
2080         }
2081         ENDTRY
2082     }
2083 }
2084
2085
2086
2087 /***************************************************/
2088 /* Unacknowledged mode PDU                         */
2089 static void dissect_rlc_lte_um(tvbuff_t *tvb, packet_info *pinfo,
2090                                proto_tree *tree,
2091                                int offset,
2092                                rlc_lte_info *p_rlc_lte_info,
2093                                proto_item *top_ti,
2094                                rlc_lte_tap_info *tap_info)
2095 {
2096     guint64 framing_info;
2097     gboolean first_includes_start;
2098     gboolean last_includes_end;
2099     guint64 fixed_extension;
2100     guint64 sn;
2101     gint    start_offset = offset;
2102     proto_item *um_ti;
2103     proto_tree *um_header_tree;
2104     proto_item *um_header_ti;
2105     gboolean is_truncated = FALSE;
2106     proto_item *truncated_ti;
2107     rlc_channel_reassembly_info *reassembly_info = NULL;
2108     sequence_analysis_state seq_anal_state = SN_OK;
2109
2110     /* Hidden UM root */
2111     um_ti = proto_tree_add_string_format(tree, hf_rlc_lte_um,
2112                                          tvb, offset, 0, "", "UM");
2113     PROTO_ITEM_SET_HIDDEN(um_ti);
2114
2115     /* Add UM header subtree */
2116     um_header_ti = proto_tree_add_string_format(tree, hf_rlc_lte_um_header,
2117                                                 tvb, offset, 0,
2118                                                 "", "UM header");
2119     um_header_tree = proto_item_add_subtree(um_header_ti,
2120                                             ett_rlc_lte_um_header);
2121
2122
2123     /*******************************/
2124     /* Fixed UM header             */
2125     if (p_rlc_lte_info->sequenceNumberLength == UM_SN_LENGTH_5_BITS) {
2126         /* Framing info (2 bits) */
2127         proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_fi,
2128                                     tvb, offset*8, 2,
2129                                     &framing_info, ENC_BIG_ENDIAN);
2130
2131         /* Extension (1 bit) */
2132         proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_fixed_e, tvb,
2133                                     (offset*8) + 2, 1,
2134                                     &fixed_extension, ENC_BIG_ENDIAN);
2135
2136         /* Sequence Number (5 bit) */
2137         proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_sn, tvb,
2138                                     (offset*8) + 3, 5,
2139                                     &sn, ENC_BIG_ENDIAN);
2140         offset++;
2141     }
2142     else if (p_rlc_lte_info->sequenceNumberLength == UM_SN_LENGTH_10_BITS) {
2143         guint8 reserved;
2144         proto_item *ti;
2145
2146         /* Check 3 Reserved bits */
2147         reserved = (tvb_get_guint8(tvb, offset) & 0xe0) >> 5;
2148         ti = proto_tree_add_item(um_header_tree, hf_rlc_lte_um_fixed_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
2149         if (reserved != 0) {
2150             expert_add_info_format(pinfo, ti, &ei_rlc_lte_reserved_bits_not_zero,
2151                       "RLC UM Fixed header Reserved bits not zero (found 0x%x)", reserved);
2152         }
2153
2154         /* Framing info (2 bits) */
2155         proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_fi,
2156                                     tvb, (offset*8)+3, 2,
2157                                     &framing_info, ENC_BIG_ENDIAN);
2158
2159         /* Extension (1 bit) */
2160         proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_fixed_e, tvb,
2161                                     (offset*8) + 5, 1,
2162                                     &fixed_extension, ENC_BIG_ENDIAN);
2163
2164         /* Sequence Number (10 bits) */
2165         proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_sn, tvb,
2166                                     (offset*8) + 6, 10,
2167                                     &sn, ENC_BIG_ENDIAN);
2168         offset += 2;
2169     }
2170     else {
2171         /* Invalid length of sequence number */
2172         proto_tree_add_expert_format(um_header_tree, pinfo, &ei_rlc_lte_um_sn, tvb, 0, 0,
2173                                "Invalid sequence number length (%u bits)",
2174                                p_rlc_lte_info->sequenceNumberLength);
2175         return;
2176     }
2177
2178     tap_info->sequenceNumber = (guint16)sn;
2179
2180     /* Show SN in info column */
2181     if ((p_rlc_lte_info->channelType == CHANNEL_TYPE_MCCH) || (p_rlc_lte_info->channelType == CHANNEL_TYPE_MTCH)) {
2182         write_pdu_label_and_info(top_ti, um_header_ti, pinfo, "           sn=%-4u", (guint16)sn);
2183     }
2184     else {
2185         write_pdu_label_and_info(top_ti, um_header_ti, pinfo, "            sn=%-4u", (guint16)sn);
2186     }
2187
2188     proto_item_set_len(um_header_ti, offset-start_offset);
2189
2190
2191     /*************************************/
2192     /* UM header extension               */
2193     if (fixed_extension) {
2194         offset = dissect_rlc_lte_extension_header(tvb, pinfo, um_header_tree, offset, p_rlc_lte_info);
2195     }
2196
2197     /* Extract these 2 flags from framing_info */
2198     first_includes_start = ((guint8)framing_info & 0x02) == 0;
2199     last_includes_end =    ((guint8)framing_info & 0x01) == 0;
2200
2201     if (global_rlc_lte_headers_expected) {
2202         /* There might not be any data, if only headers (plus control data) were logged */
2203         is_truncated = (tvb_captured_length_remaining(tvb, offset) == 0);
2204         truncated_ti = proto_tree_add_uint(tree, hf_rlc_lte_header_only, tvb, 0, 0,
2205                                            is_truncated);
2206         if (is_truncated) {
2207             int n;
2208             PROTO_ITEM_SET_GENERATED(truncated_ti);
2209             expert_add_info(pinfo, truncated_ti, &ei_rlc_lte_header_only);
2210
2211             /* Show in the info column how long the data would be */
2212             for (n=0; n < s_number_of_extensions; n++) {
2213                 show_PDU_in_info(pinfo, top_ti, s_lengths[n],
2214                                  (n==0) ? first_includes_start : TRUE,
2215                                  TRUE);
2216                 offset += s_lengths[n];
2217             }
2218             /* Last one */
2219             show_PDU_in_info(pinfo, top_ti, p_rlc_lte_info->pduLength - offset,
2220                              (s_number_of_extensions == 0) ? first_includes_start : TRUE,
2221                              last_includes_end);
2222         }
2223         else {
2224             PROTO_ITEM_SET_HIDDEN(truncated_ti);
2225         }
2226     }
2227
2228     /* Show number of extensions in header root */
2229     if (s_number_of_extensions > 0) {
2230         proto_item_append_text(um_header_ti, " (%u extensions)", s_number_of_extensions);
2231     }
2232
2233     /* Call sequence analysis function now */
2234     if (((global_rlc_lte_um_sequence_analysis == SEQUENCE_ANALYSIS_MAC_ONLY) &&
2235          (p_get_proto_data(wmem_file_scope(), pinfo, proto_mac_lte, 0) != NULL)) ||
2236         ((global_rlc_lte_um_sequence_analysis == SEQUENCE_ANALYSIS_RLC_ONLY) &&
2237          (p_get_proto_data(wmem_file_scope(), pinfo, proto_mac_lte, 0) == NULL))) {
2238
2239         guint16 lastSegmentOffset = offset;
2240         if (s_number_of_extensions >= 1) {
2241             int n;
2242             lastSegmentOffset = offset;
2243             for (n=0; n < s_number_of_extensions; n++) {
2244                 lastSegmentOffset += s_lengths[n];
2245             }
2246         }
2247
2248         seq_anal_state = checkChannelSequenceInfo(pinfo, tvb, p_rlc_lte_info,
2249                                                   FALSE,
2250                                                   s_number_of_extensions+1,
2251                                                   offset,
2252                                                   s_number_of_extensions ?
2253                                                       s_lengths[0] :
2254                                                       p_rlc_lte_info->pduLength - offset,
2255                                                   lastSegmentOffset,
2256                                                   (guint16)sn, first_includes_start, last_includes_end,
2257                                                   FALSE, /* UM doesn't re-segment */
2258                                                   tap_info, um_header_tree);
2259     }
2260
2261     if (is_truncated) {
2262         return;
2263     }
2264
2265     /*************************************/
2266     /* Data                              */
2267
2268     reassembly_info = (rlc_channel_reassembly_info *)wmem_map_lookup(reassembly_report_hash,
2269                                                                          get_report_hash_key((guint16)sn, pinfo->num,
2270                                                                                              p_rlc_lte_info, FALSE));
2271
2272     if (s_number_of_extensions > 0) {
2273         /* Show each data segment separately */
2274         int n;
2275         for (n=0; n < s_number_of_extensions; n++) {
2276             show_PDU_in_tree(pinfo, tree, tvb, offset, s_lengths[n], p_rlc_lte_info,
2277                              (n==0) ? first_includes_start : TRUE,
2278                              (n==0) ? reassembly_info : NULL,
2279                              seq_anal_state);
2280             show_PDU_in_info(pinfo, top_ti, s_lengths[n],
2281                              (n==0) ? first_includes_start : TRUE,
2282                              TRUE);
2283             /* Make sure we don't lose the summary of this SDU */
2284             col_append_str(pinfo->cinfo, COL_INFO, "  | ");
2285             col_set_fence(pinfo->cinfo, COL_INFO);
2286
2287             tvb_ensure_bytes_exist(tvb, offset, s_lengths[n]);
2288             offset += s_lengths[n];
2289         }
2290     }
2291
2292     /* Final data element */
2293     show_PDU_in_tree(pinfo, tree, tvb, offset, tvb_reported_length_remaining(tvb, offset), p_rlc_lte_info,
2294                      ((s_number_of_extensions == 0) ? first_includes_start : TRUE) && last_includes_end,
2295                      (s_number_of_extensions == 0) ? reassembly_info : NULL,
2296                      seq_anal_state);
2297     show_PDU_in_info(pinfo, top_ti, (guint16)tvb_reported_length_remaining(tvb, offset),
2298                      (s_number_of_extensions == 0) ? first_includes_start : TRUE,
2299                      last_includes_end);
2300 }
2301
2302
2303
2304 /* Dissect an AM STATUS PDU */
2305 static void dissect_rlc_lte_am_status_pdu(tvbuff_t *tvb,
2306                                           packet_info *pinfo,
2307                                           proto_tree *tree,
2308                                           proto_item *status_ti,
2309                                           int offset,
2310                                           proto_item *top_ti,
2311                                           rlc_lte_info *p_rlc_lte_info,
2312                                           rlc_lte_tap_info *tap_info)
2313 {
2314     guint8     cpt, sn_size, so_size;
2315     guint32    sn_limit;
2316     guint64    ack_sn, nack_sn;
2317     guint16    nack_count = 0, so_end_of_pdu;
2318     guint64    e1 = 0, e2 = 0;
2319     guint64    so_start, so_end;
2320     int        bit_offset = offset * 8;
2321     proto_item *ti;
2322
2323     /****************************************************************/
2324     /* Part of RLC control PDU header                               */
2325
2326     /* Control PDU Type (CPT) */
2327     cpt = (tvb_get_guint8(tvb, offset) & 0xf0) >> 4;
2328     ti = proto_tree_add_item(tree, hf_rlc_lte_am_cpt, tvb, offset, 1, ENC_BIG_ENDIAN);
2329     if (cpt != 0) {
2330         /* Protest and stop - only know about STATUS PDUs */
2331         expert_add_info_format(pinfo, ti, &ei_rlc_lte_am_cpt,
2332                                "RLC Control frame type %u not handled", cpt);
2333         return;
2334     }
2335
2336     if (p_rlc_lte_info->sequenceNumberLength == AM_SN_LENGTH_16_BITS) {
2337         sn_size = 16;
2338         sn_limit = 65536;
2339         so_size = 16;
2340         so_end_of_pdu = 0xffff;
2341     } else {
2342         sn_size = 10;
2343         sn_limit = 1024;
2344         so_size = 15;
2345         so_end_of_pdu = 0x7fff;
2346     }
2347
2348     /* The Status PDU itself starts 4 bits into the byte */
2349     bit_offset += 4;
2350
2351     /* ACK SN */
2352     proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_ack_sn, tvb,
2353                                 bit_offset, sn_size, &ack_sn, ENC_BIG_ENDIAN);
2354     bit_offset += sn_size;
2355     write_pdu_label_and_info(top_ti, status_ti, pinfo, "  ACK_SN=%-4u", (guint16)ack_sn);
2356
2357     tap_info->ACKNo = (guint16)ack_sn;
2358
2359     /* E1 */
2360     proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_e1, tvb,
2361                                 bit_offset, 1, &e1, ENC_BIG_ENDIAN);
2362
2363     /* Skip another bit to byte-align the next bit... */
2364     bit_offset++;
2365
2366     /* Optional, extra fields */
2367     do {
2368         if (e1) {
2369             proto_item *nack_ti;
2370
2371             /****************************/
2372             /* Read NACK_SN, E1, E2     */
2373
2374             /* NACK_SN */
2375             nack_ti = proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_nack_sn, tvb,
2376                                                   bit_offset, sn_size, &nack_sn, ENC_BIG_ENDIAN);
2377             bit_offset += sn_size;
2378             write_pdu_label_and_info(top_ti, NULL, pinfo, "  NACK_SN=%-4u", (guint16)nack_sn);
2379
2380             /* We shouldn't NACK the ACK_SN! */
2381             if (nack_sn == ack_sn) {
2382                 expert_add_info_format(pinfo, nack_ti, &ei_rlc_lte_am_nack_sn_ack_same,
2383                                        "Status PDU shouldn't ACK and NACK the same sequence number (%" G_GINT64_MODIFIER "u)",
2384                                        ack_sn);
2385             }
2386
2387             /* NACK should always be 'behind' the ACK */
2388             if ((sn_limit + ack_sn - nack_sn) % sn_limit > (sn_limit>>1)) {
2389                 expert_add_info(pinfo, nack_ti, &ei_rlc_lte_am_nack_sn_ahead_ack);
2390             }
2391
2392             /* Copy into struct, but don't exceed buffer */
2393             if (nack_count < MAX_NACKs) {
2394                 tap_info->NACKs[nack_count++] = (guint16)nack_sn;
2395             }
2396             else {
2397                 /* Let it get bigger than the array for accurate stats... */
2398                 nack_count++;
2399             }
2400
2401             /* E1 */
2402             proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_e1, tvb,
2403                                         bit_offset, 1, &e1, ENC_BIG_ENDIAN);
2404             bit_offset++;
2405
2406             /* E2 */
2407             proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_e2, tvb,
2408                                         bit_offset, 1, &e2, ENC_BIG_ENDIAN);
2409
2410             /* Report as expert info */
2411             if (e2) {
2412                 expert_add_info_format(pinfo, nack_ti, &ei_rlc_lte_am_nack_sn_partial,
2413                                        "Status PDU reports NACK (partial) on %s for UE %u",
2414                                        val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
2415                                        p_rlc_lte_info->ueid);
2416             }
2417             else {
2418                 expert_add_info_format(pinfo, nack_ti, &ei_rlc_lte_am_nack_sn,
2419                                        "Status PDU reports NACK on %s for UE %u",
2420                                        val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
2421                                        p_rlc_lte_info->ueid);
2422             }
2423
2424             bit_offset++;
2425         }
2426
2427         if (e2) {
2428             /* Read SOstart, SOend */
2429             proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_so_start, tvb,
2430                                         bit_offset, so_size, &so_start, ENC_BIG_ENDIAN);
2431             bit_offset += so_size;
2432
2433             proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_so_end, tvb,
2434                                         bit_offset, so_size, &so_end, ENC_BIG_ENDIAN);
2435             bit_offset += so_size;
2436
2437
2438             if ((guint16)so_end == so_end_of_pdu) {
2439                 write_pdu_label_and_info(top_ti, NULL, pinfo,
2440                                          " (SOstart=%u SOend=<END-OF_PDU>)",
2441                                          (guint16)so_start);
2442             }
2443             else {
2444                 write_pdu_label_and_info(top_ti, NULL, pinfo,
2445                                          " (SOstart=%u SOend=%u)",
2446                                          (guint16)so_start, (guint16)so_end);
2447             }
2448
2449             /* Reset this flag here */
2450             e2 = 0;
2451         }
2452     } while (e1 || e2);
2453
2454     if (nack_count > 0) {
2455         proto_item *count_ti = proto_tree_add_uint(tree, hf_rlc_lte_am_nacks, tvb, 0, 1, nack_count);
2456         PROTO_ITEM_SET_GENERATED(count_ti);
2457         proto_item_append_text(status_ti, "  (%u NACKs)", nack_count);
2458         tap_info->noOfNACKs = nack_count;
2459     }
2460
2461     /* Check that we've reached the end of the PDU. If not, show malformed */
2462     offset = (bit_offset+7) / 8;
2463     if (tvb_reported_length_remaining(tvb, offset) > 0) {
2464         expert_add_info_format(pinfo, status_ti, &ei_rlc_lte_bytes_after_status_pdu_complete,
2465                                "%cL %u bytes remaining after Status PDU complete",
2466                                (p_rlc_lte_info->direction == DIRECTION_UPLINK) ? 'U' : 'D',
2467                                tvb_reported_length_remaining(tvb, offset));
2468     }
2469
2470     /* Set selected length of control tree */
2471     proto_item_set_len(status_ti, offset);
2472
2473     /* Repeated NACK analysis & check ACK-SN is in range */
2474     if (((global_rlc_lte_am_sequence_analysis == SEQUENCE_ANALYSIS_MAC_ONLY) &&
2475          (p_get_proto_data(wmem_file_scope(), pinfo, proto_mac_lte, 0) != NULL)) ||
2476         ((global_rlc_lte_am_sequence_analysis == SEQUENCE_ANALYSIS_RLC_ONLY) &&
2477          (p_get_proto_data(wmem_file_scope(), pinfo, proto_mac_lte, 0) == NULL))) {
2478
2479         if (!is_mac_lte_frame_retx(pinfo, p_rlc_lte_info->direction)) {
2480             checkChannelRepeatedNACKInfo(pinfo, p_rlc_lte_info, tap_info, tree, tvb);
2481             checkChannelACKWindow((guint16)ack_sn, pinfo, p_rlc_lte_info, tap_info, tree, tvb);
2482         }
2483      }
2484 }
2485
2486
2487 /***************************************************/
2488 /* Acknowledged mode PDU                           */
2489 static void dissect_rlc_lte_am(tvbuff_t *tvb, packet_info *pinfo,
2490                                proto_tree *tree,
2491                                int offset,
2492                                rlc_lte_info *p_rlc_lte_info,
2493                                proto_item *top_ti,
2494                                rlc_lte_tap_info *tap_info)
2495 {
2496     guint8 is_data;
2497     guint8 is_resegmented;
2498     guint8 polling;
2499     guint8 fixed_extension;
2500     guint8 framing_info;
2501     gboolean first_includes_start;
2502     gboolean last_includes_end;
2503     proto_item *am_ti;
2504     proto_tree *am_header_tree;
2505     proto_item *am_header_ti;
2506     gint   start_offset = offset;
2507     guint16    sn;
2508     gboolean is_truncated = FALSE;
2509     proto_item *truncated_ti;
2510     rlc_channel_reassembly_info *reassembly_info = NULL;
2511     sequence_analysis_state seq_anal_state = SN_OK;
2512     guint32 id;
2513     wmem_tree_key_t key[3];
2514     rlc_ue_parameters *params;
2515
2516     /* Hidden AM root */
2517     am_ti = proto_tree_add_string_format(tree, hf_rlc_lte_am,
2518                                          tvb, offset, 0, "", "AM");
2519     PROTO_ITEM_SET_HIDDEN(am_ti);
2520
2521     /* Add AM header subtree */
2522     am_header_ti = proto_tree_add_string_format(tree, hf_rlc_lte_am_header,
2523                                                 tvb, offset, 0,
2524                                                 "", "AM Header ");
2525     am_header_tree = proto_item_add_subtree(am_header_ti,
2526                                             ett_rlc_lte_am_header);
2527
2528     /* First bit is Data/Control flag           */
2529     is_data = (tvb_get_guint8(tvb, offset) & 0x80) >> 7;
2530     proto_tree_add_item(am_header_tree, hf_rlc_lte_am_data_control, tvb, offset, 1, ENC_BIG_ENDIAN);
2531     tap_info->isControlPDU = !is_data;
2532
2533     if (!is_data) {
2534         /**********************/
2535         /* Status PDU         */
2536         write_pdu_label_and_info_literal(top_ti, NULL, pinfo, " [CONTROL]");
2537
2538         /* Control PDUs are a completely separate format  */
2539         dissect_rlc_lte_am_status_pdu(tvb, pinfo, am_header_tree, am_header_ti,
2540                                       offset, top_ti,
2541                                       p_rlc_lte_info, tap_info);
2542         return;
2543     }
2544
2545     /******************************/
2546     /* Data PDU fixed header      */
2547
2548     /* Re-segmentation Flag (RF) field */
2549     is_resegmented = (tvb_get_guint8(tvb, offset) & 0x40) >> 6;
2550     proto_tree_add_item(am_header_tree, hf_rlc_lte_am_rf, tvb, offset, 1, ENC_BIG_ENDIAN);
2551     tap_info->isResegmented = is_resegmented;
2552
2553     write_pdu_label_and_info_literal(top_ti, NULL, pinfo,
2554                                      (is_resegmented) ? " [DATA-SEGMENT]" : " [DATA]");
2555
2556     /* Polling bit */
2557     polling = (tvb_get_guint8(tvb, offset) & 0x20) >> 5;
2558     proto_tree_add_item(am_header_tree, hf_rlc_lte_am_p, tvb, offset, 1, ENC_BIG_ENDIAN);
2559
2560     write_pdu_label_and_info_literal(top_ti, NULL, pinfo, (polling) ? " (P) " : "     ");
2561     if (polling) {
2562         proto_item_append_text(am_header_ti, " (P) ");
2563     }
2564
2565     /* Framing Info */
2566     framing_info = (tvb_get_guint8(tvb, offset) & 0x18) >> 3;
2567     proto_tree_add_item(am_header_tree, hf_rlc_lte_am_fi, tvb, offset, 1, ENC_BIG_ENDIAN);
2568
2569     /* Extension bit */
2570     fixed_extension = (tvb_get_guint8(tvb, offset) & 0x04) >> 2;
2571     proto_tree_add_item(am_header_tree, hf_rlc_lte_am_fixed_e, tvb, offset, 1, ENC_BIG_ENDIAN);
2572
2573     /* Sequence Number */
2574     if (p_rlc_lte_info->sequenceNumberLength == AM_SN_LENGTH_16_BITS) {
2575         guint8 reserved;
2576
2577         if (is_resegmented) {
2578             /* Last Segment Field (LSF) */
2579             proto_tree_add_item(am_header_tree, hf_rlc_lte_am_segment_lsf16, tvb, offset, 1, ENC_BIG_ENDIAN);
2580             /* Reserved (R1) */
2581             am_ti = proto_tree_add_item(am_header_tree, hf_rlc_lte_am_fixed_reserved2, tvb, offset, 1, ENC_BIG_ENDIAN);
2582             reserved = tvb_get_guint8(tvb, offset) & 0x01;
2583         } else {
2584             /* Reserved (R1) */
2585             am_ti = proto_tree_add_item(am_header_tree, hf_rlc_lte_am_fixed_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
2586             reserved = tvb_get_guint8(tvb, offset) & 0x03;
2587         }
2588         if (reserved != 0) {
2589             expert_add_info_format(pinfo, am_ti, &ei_rlc_lte_reserved_bits_not_zero,
2590                     "RLC AM Fixed header Reserved bits not zero (found 0x%x)", reserved);
2591         }
2592         offset += 1;
2593         proto_tree_add_item(am_header_tree, hf_rlc_lte_am_fixed_sn16, tvb, offset, 2, ENC_BIG_ENDIAN);
2594         sn = tvb_get_ntohs(tvb, offset);
2595         offset += 2;
2596     } else {
2597         proto_tree_add_item(am_header_tree, hf_rlc_lte_am_fixed_sn, tvb, offset, 2, ENC_BIG_ENDIAN);
2598         sn = tvb_get_ntohs(tvb, offset) & 0x03ff;
2599         offset += 2;
2600     }
2601     tap_info->sequenceNumber = sn;
2602
2603     write_pdu_label_and_info(top_ti, am_header_ti, pinfo, "sn=%-4u", sn);
2604
2605     /***************************************/
2606     /* Dissect extra segment header fields */
2607     if (is_resegmented) {
2608         guint16 segmentOffset;
2609
2610         if (p_rlc_lte_info->sequenceNumberLength == AM_SN_LENGTH_16_BITS) {
2611             /* SO */
2612             proto_tree_add_item(am_header_tree, hf_rlc_lte_am_segment_so16, tvb, offset, 2, ENC_BIG_ENDIAN);
2613             segmentOffset = tvb_get_ntohs(tvb, offset);
2614         } else {
2615             /* Last Segment Field (LSF) */
2616             proto_tree_add_item(am_header_tree, hf_rlc_lte_am_segment_lsf, tvb, offset, 1, ENC_BIG_ENDIAN);
2617
2618             /* SO */
2619             proto_tree_add_item(am_header_tree, hf_rlc_lte_am_segment_so, tvb, offset, 2, ENC_BIG_ENDIAN);
2620             segmentOffset = tvb_get_ntohs(tvb, offset) & 0x7fff;
2621         }
2622         write_pdu_label_and_info(top_ti, am_header_ti, pinfo, " SO=%u ", segmentOffset);
2623         offset += 2;
2624     }
2625
2626     /*************************************/
2627     /* AM header extension               */
2628     if (fixed_extension) {
2629         if (!PINFO_FD_VISITED(pinfo)) {
2630             id = (p_rlc_lte_info->channelId << 16) | p_rlc_lte_info->ueid;
2631             key[0].length = 1;
2632             key[0].key = &id;
2633             key[1].length = 1;
2634             key[1].key = &pinfo->num;
2635             key[2].length = 0;
2636             key[2].key = NULL;
2637             params = (rlc_ue_parameters *)wmem_tree_lookup32_array_le(ue_parameters_tree, key);
2638             if (params && (params->id == id)) {
2639                 p_rlc_lte_info->extendedLiField = (p_rlc_lte_info->direction == DIRECTION_UPLINK) ?
2640                                                    (params->ext_li_field & UL_EXT_LI): (params->ext_li_field & DL_EXT_LI);
2641             }
2642         }
2643         offset = dissect_rlc_lte_extension_header(tvb, pinfo, am_header_tree, offset, p_rlc_lte_info);
2644     }
2645
2646     /* Header is now complete */
2647     proto_item_set_len(am_header_ti, offset-start_offset);
2648
2649     /* Show number of extensions in header root */
2650     if (s_number_of_extensions > 0) {
2651         proto_item_append_text(am_header_ti, " (%u extensions)", s_number_of_extensions);
2652     }
2653
2654     /* Extract these 2 flags from framing_info */
2655     first_includes_start = (framing_info & 0x02) == 0;
2656     last_includes_end =    (framing_info & 0x01) == 0;
2657
2658     /* There might not be any data, if only headers (plus control data) were logged */
2659     if (global_rlc_lte_headers_expected) {
2660         is_truncated = (tvb_captured_length_remaining(tvb, offset) == 0);
2661         truncated_ti = proto_tree_add_uint(tree, hf_rlc_lte_header_only, tvb, 0, 0,
2662                                            is_truncated);
2663         if (is_truncated) {
2664             int n;
2665             PROTO_ITEM_SET_GENERATED(truncated_ti);
2666             expert_add_info(pinfo, truncated_ti, &ei_rlc_lte_header_only);
2667             /* Show in the info column how long the data would be */
2668             for (n=0; n < s_number_of_extensions; n++) {
2669                 show_PDU_in_info(pinfo, top_ti, s_lengths[n],
2670                                  (n==0) ? first_includes_start : TRUE,
2671                                  TRUE);
2672                 offset += s_lengths[n];
2673             }
2674             /* Last one */
2675             show_PDU_in_info(pinfo, top_ti, p_rlc_lte_info->pduLength - offset,
2676                              (s_number_of_extensions == 0) ? first_includes_start : TRUE,
2677                              last_includes_end);
2678         }
2679         else {
2680             PROTO_ITEM_SET_HIDDEN(truncated_ti);
2681         }
2682     }
2683
2684     /* Call sequence analysis function now */
2685     if (((global_rlc_lte_am_sequence_analysis == SEQUENCE_ANALYSIS_MAC_ONLY) &&
2686          (p_get_proto_data(wmem_file_scope(), pinfo, proto_mac_lte, 0) != NULL)) ||
2687         ((global_rlc_lte_am_sequence_analysis == SEQUENCE_ANALYSIS_RLC_ONLY) &&
2688          (p_get_proto_data(wmem_file_scope(), pinfo, proto_mac_lte, 0) == NULL))) {
2689
2690         guint16 firstSegmentLength;
2691         guint16 lastSegmentOffset = offset;
2692         if (s_number_of_extensions >= 1) {
2693             int n;
2694             for (n=0; n < s_number_of_extensions; n++) {
2695                 lastSegmentOffset += s_lengths[n];
2696             }
2697
2698             firstSegmentLength = s_lengths[0];
2699         }
2700         else {
2701             firstSegmentLength = tvb_reported_length_remaining(tvb, offset);
2702         }
2703
2704         seq_anal_state = checkChannelSequenceInfo(pinfo, tvb, p_rlc_lte_info, FALSE,
2705                                                   s_number_of_extensions+1,
2706                                                   offset, firstSegmentLength,
2707                                                   lastSegmentOffset,
2708                                                   (guint16)sn,
2709                                                   first_includes_start, last_includes_end,
2710                                                   is_resegmented, tap_info, tree);
2711     }
2712
2713     if (is_truncated) {
2714         return;
2715     }
2716
2717     /*************************************/
2718     /* Data                              */
2719
2720     if (!first_includes_start) {
2721         reassembly_info = (rlc_channel_reassembly_info *)wmem_map_lookup(reassembly_report_hash,
2722                                                                              get_report_hash_key((guint16)sn,
2723                                                                                                  pinfo->num,
2724                                                                                                  p_rlc_lte_info,
2725                                                                                                  FALSE));
2726     }
2727
2728     if (s_number_of_extensions > 0) {
2729         /* Show each data segment separately */
2730         int n;
2731         for (n=0; n < s_number_of_extensions; n++) {
2732             show_PDU_in_tree(pinfo, tree, tvb, offset, s_lengths[n], p_rlc_lte_info,
2733                              (n==0) ? first_includes_start : TRUE,
2734                              (n==0) ? reassembly_info : NULL,
2735                              seq_anal_state);
2736             show_PDU_in_info(pinfo, top_ti, s_lengths[n],
2737                              (n==0) ? first_includes_start : TRUE,
2738                              TRUE);
2739             /* Make sure we don't lose the summary of this SDU */
2740             col_append_str(pinfo->cinfo, COL_INFO, "  | ");
2741             col_set_fence(pinfo->cinfo, COL_INFO);
2742
2743             tvb_ensure_bytes_exist(tvb, offset, s_lengths[n]);
2744             offset += s_lengths[n];
2745         }
2746     }
2747
2748     /* Final data element */
2749     if (tvb_reported_length_remaining(tvb, offset) > 0) {
2750         show_PDU_in_tree(pinfo, tree, tvb, offset, tvb_reported_length_remaining(tvb, offset), p_rlc_lte_info,
2751                          ((s_number_of_extensions == 0) ? first_includes_start : TRUE) && last_includes_end,
2752                          (s_number_of_extensions == 0) ? reassembly_info : NULL,
2753                          seq_anal_state);
2754         show_PDU_in_info(pinfo, top_ti, (guint16)tvb_reported_length_remaining(tvb, offset),
2755                          (s_number_of_extensions == 0) ? first_includes_start : TRUE,
2756                          last_includes_end);
2757     }
2758     else {
2759         /* Report that expected data was missing (unless we know it might happen) */
2760         if (!global_rlc_lte_headers_expected) {
2761             if (s_number_of_extensions > 0) {
2762                 expert_add_info(pinfo, am_header_ti, &ei_rlc_lte_am_data_no_data_beyond_extensions);
2763             }
2764             else {
2765                 expert_add_info(pinfo, am_header_ti, &ei_rlc_lte_am_data_no_data);
2766             }
2767         }
2768     }
2769 }
2770
2771 static void report_heur_error(proto_tree *tree, packet_info *pinfo, expert_field *eiindex,
2772                               tvbuff_t *tvb, gint start, gint length)
2773 {
2774     proto_item *ti;
2775     proto_tree *subtree;
2776
2777     col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC-LTE");
2778     col_clear(pinfo->cinfo, COL_INFO);
2779     ti = proto_tree_add_item(tree, proto_rlc_lte, tvb, 0, -1, ENC_NA);
2780     subtree = proto_item_add_subtree(ti, ett_rlc_lte);
2781     proto_tree_add_expert(subtree, pinfo, eiindex, tvb, start, length);
2782 }
2783
2784 /* Heuristic dissector looks for supported framing protocol (see wiki page)  */
2785 static gboolean dissect_rlc_lte_heur(tvbuff_t *tvb, packet_info *pinfo,
2786                                      proto_tree *tree, void *data _U_)
2787 {
2788     gint                 offset = 0;
2789     struct rlc_lte_info  *p_rlc_lte_info;
2790     tvbuff_t             *rlc_tvb;
2791     guint8               tag = 0;
2792     gboolean             seqNumLengthTagPresent = FALSE;
2793
2794     /* Needs to be at least as long as:
2795        - the signature string
2796        - fixed header bytes
2797        - tag for data
2798        - at least one byte of RLC PDU payload */
2799     if (tvb_captured_length_remaining(tvb, offset) < (gint)(strlen(RLC_LTE_START_STRING)+1+2)) {
2800         return FALSE;
2801     }
2802
2803     /* OK, compare with signature string */
2804     if (tvb_strneql(tvb, offset, RLC_LTE_START_STRING, (gint)strlen(RLC_LTE_START_STRING)) != 0) {
2805         return FALSE;
2806     }
2807     offset += (gint)strlen(RLC_LTE_START_STRING);
2808
2809
2810     /* If redissecting, use previous info struct (if available) */
2811     p_rlc_lte_info = (rlc_lte_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc_lte, 0);
2812     if (p_rlc_lte_info == NULL) {
2813         /* Allocate new info struct for this frame */
2814         p_rlc_lte_info = wmem_new0(wmem_file_scope(), struct rlc_lte_info);
2815
2816         /* Read fixed fields */
2817         p_rlc_lte_info->rlcMode = tvb_get_guint8(tvb, offset++);
2818         if (p_rlc_lte_info->rlcMode == RLC_AM_MODE) {
2819             p_rlc_lte_info->sequenceNumberLength = AM_SN_LENGTH_10_BITS;
2820         }
2821
2822         /* Read optional fields */
2823         while (tag != RLC_LTE_PAYLOAD_TAG) {
2824             /* Process next tag */
2825             tag = tvb_get_guint8(tvb, offset++);
2826             switch (tag) {
2827                 case RLC_LTE_SN_LENGTH_TAG:
2828                     p_rlc_lte_info->sequenceNumberLength = tvb_get_guint8(tvb, offset);
2829                     offset++;
2830                     seqNumLengthTagPresent = TRUE;
2831                     break;
2832                 case RLC_LTE_DIRECTION_TAG:
2833                     p_rlc_lte_info->direction = tvb_get_guint8(tvb, offset);
2834                     offset++;
2835                     break;
2836                 case RLC_LTE_PRIORITY_TAG:
2837                     p_rlc_lte_info->priority = tvb_get_guint8(tvb, offset);
2838                     offset++;
2839                     break;
2840                 case RLC_LTE_UEID_TAG:
2841                     p_rlc_lte_info->ueid = tvb_get_ntohs(tvb, offset);
2842                     offset += 2;
2843                     break;
2844                 case RLC_LTE_CHANNEL_TYPE_TAG:
2845                     p_rlc_lte_info->channelType = tvb_get_ntohs(tvb, offset);
2846                     offset += 2;
2847                     break;
2848                 case RLC_LTE_CHANNEL_ID_TAG:
2849                     p_rlc_lte_info->channelId = tvb_get_ntohs(tvb, offset);
2850                     offset += 2;
2851                     break;
2852                 case RLC_LTE_EXT_LI_FIELD_TAG:
2853                     p_rlc_lte_info->extendedLiField = TRUE;
2854                     break;
2855                 case RLC_LTE_NB_MODE_TAG:
2856                     p_rlc_lte_info->nbMode =
2857                         (rlc_lte_nb_mode)tvb_get_guint8(tvb, offset);
2858                     offset++;
2859                     break;
2860
2861                 case RLC_LTE_PAYLOAD_TAG:
2862                     /* Have reached data, so set payload length and get out of loop */
2863                     p_rlc_lte_info->pduLength = tvb_reported_length_remaining(tvb, offset);
2864                     continue;
2865
2866                 default:
2867                     /* It must be a recognised tag */
2868                     report_heur_error(tree, pinfo, &ei_rlc_lte_unknown_udp_framing_tag, tvb, offset-1, 1);
2869                     wmem_free(wmem_file_scope(), p_rlc_lte_info);
2870                     return TRUE;
2871             }
2872         }
2873
2874         if ((p_rlc_lte_info->rlcMode == RLC_UM_MODE) && (seqNumLengthTagPresent == FALSE)) {
2875             /* Conditional field is not present */
2876             report_heur_error(tree, pinfo, &ei_rlc_lte_missing_udp_framing_tag, tvb, 0, offset);
2877             wmem_free(wmem_file_scope(), p_rlc_lte_info);
2878             return TRUE;
2879         }
2880
2881         /* Store info in packet */
2882         p_add_proto_data(wmem_file_scope(), pinfo, proto_rlc_lte, 0, p_rlc_lte_info);
2883     }
2884     else {
2885         offset = tvb_reported_length(tvb) - p_rlc_lte_info->pduLength;
2886     }
2887
2888     /**************************************/
2889     /* OK, now dissect as RLC LTE         */
2890
2891     /* Create tvb that starts at actual RLC PDU */
2892     rlc_tvb = tvb_new_subset_remaining(tvb, offset);
2893     dissect_rlc_lte_common(rlc_tvb, pinfo, tree, TRUE);
2894     return TRUE;
2895 }
2896
2897
2898
2899 /*****************************/
2900 /* Main dissection function. */
2901 /*****************************/
2902
2903 static int dissect_rlc_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2904 {
2905     dissect_rlc_lte_common(tvb, pinfo, tree, FALSE);
2906     return tvb_captured_length(tvb);
2907 }
2908
2909 static void dissect_rlc_lte_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean is_udp_framing)
2910 {
2911     proto_tree             *rlc_lte_tree;
2912     proto_tree             *context_tree;
2913     proto_item             *top_ti;
2914     proto_item             *context_ti;
2915     proto_item             *ti;
2916     proto_item             *mode_ti;
2917     gint                   offset = 0;
2918     struct rlc_lte_info    *p_rlc_lte_info = NULL;
2919
2920     /* Allocate and Zero tap struct */
2921     rlc_lte_tap_info *tap_info = wmem_new0(wmem_packet_scope(), rlc_lte_tap_info);
2922
2923     /* Set protocol name */
2924     col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC-LTE");
2925
2926     /* Create protocol tree. */
2927     top_ti = proto_tree_add_item(tree, proto_rlc_lte, tvb, offset, -1, ENC_NA);
2928     rlc_lte_tree = proto_item_add_subtree(top_ti, ett_rlc_lte);
2929
2930
2931     /* Look for packet info! */
2932     p_rlc_lte_info = (rlc_lte_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc_lte, 0);
2933
2934     /* Can't dissect anything without it... */
2935     if (p_rlc_lte_info == NULL) {
2936         proto_tree_add_expert(rlc_lte_tree, pinfo, &ei_rlc_lte_no_per_frame_info, tvb, offset, -1);
2937         return;
2938     }
2939
2940     /* Clear info column when using UDP framing */
2941     if (is_udp_framing) {
2942         col_clear(pinfo->cinfo, COL_INFO);
2943     }
2944
2945     /*****************************************/
2946     /* Show context information              */
2947
2948     /* Create context root */
2949     context_ti = proto_tree_add_string_format(rlc_lte_tree, hf_rlc_lte_context,
2950                                               tvb, offset, 0, "", "Context");
2951     context_tree = proto_item_add_subtree(context_ti, ett_rlc_lte_context);
2952     PROTO_ITEM_SET_GENERATED(context_ti);
2953
2954     ti = proto_tree_add_uint(context_tree, hf_rlc_lte_context_direction,
2955                              tvb, 0, 0, p_rlc_lte_info->direction);
2956     PROTO_ITEM_SET_GENERATED(ti);
2957
2958     mode_ti = proto_tree_add_uint(context_tree, hf_rlc_lte_context_mode,
2959                                   tvb, 0, 0, p_rlc_lte_info->rlcMode);
2960     PROTO_ITEM_SET_GENERATED(mode_ti);
2961
2962     if (p_rlc_lte_info->ueid != 0) {
2963         ti = proto_tree_add_uint(context_tree, hf_rlc_lte_context_ueid,
2964                                  tvb, 0, 0, p_rlc_lte_info->ueid);
2965         PROTO_ITEM_SET_GENERATED(ti);
2966     }
2967
2968     if ((p_rlc_lte_info->priority >= 1) && (p_rlc_lte_info->priority <=16)) {
2969         ti = proto_tree_add_uint(context_tree, hf_rlc_lte_context_priority,
2970                                  tvb, 0, 0, p_rlc_lte_info->priority);
2971         PROTO_ITEM_SET_GENERATED(ti);
2972     }
2973
2974     ti = proto_tree_add_uint(context_tree, hf_rlc_lte_context_channel_type,
2975                              tvb, 0, 0, p_rlc_lte_info->channelType);
2976     PROTO_ITEM_SET_GENERATED(ti);
2977
2978     if ((p_rlc_lte_info->channelType == CHANNEL_TYPE_SRB) ||
2979         (p_rlc_lte_info->channelType == CHANNEL_TYPE_DRB) ||
2980         (p_rlc_lte_info->channelType == CHANNEL_TYPE_MTCH)) {
2981         ti = proto_tree_add_uint(context_tree, hf_rlc_lte_context_channel_id,
2982                                  tvb, 0, 0, p_rlc_lte_info->channelId);
2983         PROTO_ITEM_SET_GENERATED(ti);
2984     }
2985
2986     ti = proto_tree_add_uint(context_tree, hf_rlc_lte_context_pdu_length,
2987                              tvb, 0, 0, p_rlc_lte_info->pduLength);
2988     PROTO_ITEM_SET_GENERATED(ti);
2989
2990     if (p_rlc_lte_info->rlcMode == RLC_UM_MODE) {
2991         ti = proto_tree_add_uint(context_tree, hf_rlc_lte_context_um_sn_length,
2992                                  tvb, 0, 0, p_rlc_lte_info->sequenceNumberLength);
2993         PROTO_ITEM_SET_GENERATED(ti);
2994     }
2995
2996     if (p_rlc_lte_info->rlcMode == RLC_AM_MODE) {
2997         ti = proto_tree_add_uint(context_tree, hf_rlc_lte_context_am_sn_length,
2998                                  tvb, 0, 0, p_rlc_lte_info->sequenceNumberLength ?
2999                                     p_rlc_lte_info->sequenceNumberLength : 10);
3000         PROTO_ITEM_SET_GENERATED(ti);
3001     }
3002
3003     /* Append highlights to top-level item */
3004     if (p_rlc_lte_info->ueid != 0) {
3005         proto_item_append_text(top_ti, "   UEId=%u", p_rlc_lte_info->ueid);
3006         col_append_fstr(pinfo->cinfo, COL_INFO, "UEId=%-4u ", p_rlc_lte_info->ueid);
3007     }
3008
3009     /* Append context highlights to info column */
3010     write_pdu_label_and_info(top_ti, NULL, pinfo,
3011                              " [%s] [%s] ",
3012                              (p_rlc_lte_info->direction == 0) ? "UL" : "DL",
3013                              val_to_str_const(p_rlc_lte_info->rlcMode, rlc_mode_short_vals, "Unknown"));
3014
3015     if (p_rlc_lte_info->channelId == 0) {
3016         write_pdu_label_and_info(top_ti, NULL, pinfo, "%s   ",
3017                                  val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"));
3018     }
3019     else {
3020         write_pdu_label_and_info(top_ti, NULL, pinfo, "%s:%-2u",
3021                                  val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
3022                                  p_rlc_lte_info->channelId);
3023     }
3024
3025     /* Set context-info parts of tap struct */
3026     tap_info->rlcMode = p_rlc_lte_info->rlcMode;
3027     tap_info->direction = p_rlc_lte_info->direction;
3028     tap_info->priority = p_rlc_lte_info->priority;
3029     tap_info->ueid = p_rlc_lte_info->ueid;
3030     tap_info->channelType = p_rlc_lte_info->channelType;
3031     tap_info->channelId = p_rlc_lte_info->channelId;
3032     tap_info->pduLength = p_rlc_lte_info->pduLength;
3033     tap_info->sequenceNumberLength = p_rlc_lte_info->sequenceNumberLength;
3034     tap_info->loggedInMACFrame = (p_get_proto_data(wmem_file_scope(), pinfo, proto_mac_lte, 0) != NULL);
3035
3036     tap_info->rlc_lte_time = pinfo->abs_ts;
3037
3038     /* Reset this count */
3039     s_number_of_extensions = 0;
3040
3041     /* Dissect the RLC PDU itself. Format depends upon mode... */
3042     switch (p_rlc_lte_info->rlcMode) {
3043
3044         case RLC_TM_MODE:
3045             dissect_rlc_lte_tm(tvb, pinfo, rlc_lte_tree, offset, p_rlc_lte_info, top_ti);
3046             break;
3047
3048         case RLC_UM_MODE:
3049             dissect_rlc_lte_um(tvb, pinfo, rlc_lte_tree, offset, p_rlc_lte_info, top_ti,
3050                                tap_info);
3051             break;
3052
3053         case RLC_AM_MODE:
3054             dissect_rlc_lte_am(tvb, pinfo, rlc_lte_tree, offset, p_rlc_lte_info, top_ti,
3055                                tap_info);
3056             break;
3057
3058         case RLC_PREDEF:
3059             /* Predefined data (i.e. not containing a valid RLC header */
3060             proto_tree_add_item(rlc_lte_tree, hf_rlc_lte_predefined_pdu, tvb, offset, -1, ENC_NA);
3061             write_pdu_label_and_info(top_ti, NULL, pinfo, "   [%u-bytes]",
3062                                      tvb_reported_length_remaining(tvb, offset));
3063             break;
3064
3065         default:
3066             /* Error - unrecognised mode */
3067             expert_add_info_format(pinfo, mode_ti, &ei_rlc_lte_context_mode,
3068                                    "Unrecognised RLC Mode set (%u)", p_rlc_lte_info->rlcMode);
3069             break;
3070     }
3071
3072     /* Queue tap info */
3073     tap_queue_packet(rlc_lte_tap, pinfo, tap_info);
3074 }
3075
3076
3077
3078 /* Configure number of PDCP SN bits to use for DRB channels */
3079 void set_rlc_lte_drb_pdcp_seqnum_length(packet_info *pinfo, guint16 ueid, guint8 drbid,
3080                                         guint8 userplane_seqnum_length)
3081 {
3082     wmem_tree_key_t key[3];
3083     guint32 id;
3084     rlc_ue_parameters *params;
3085
3086     if (PINFO_FD_VISITED(pinfo)) {
3087         return;
3088     }
3089
3090     id = (drbid << 16) | ueid;
3091     key[0].length = 1;
3092     key[0].key = &id;
3093     key[1].length = 1;
3094     key[1].key = &pinfo->num;
3095     key[2].length = 0;
3096     key[2].key = NULL;
3097
3098     params = (rlc_ue_parameters *)wmem_tree_lookup32_array_le(ue_parameters_tree, key);
3099     if (params && (params->id != id)) {
3100         params = NULL;
3101     }
3102     if (params == NULL) {
3103         params = (rlc_ue_parameters *)wmem_new(wmem_file_scope(), rlc_ue_parameters);
3104         params->id = id;
3105         params->ext_li_field = NO_EXT_LI;
3106         wmem_tree_insert32_array(ue_parameters_tree, key, (void *)params);
3107     }
3108     params->pdcp_sn_bits = userplane_seqnum_length;
3109 }
3110
3111 /*Configure LI field for AM DRB channels */
3112 void set_rlc_lte_drb_li_field(packet_info *pinfo, guint16 ueid, guint8 drbid,
3113                               gboolean ul_ext_li_field, gboolean dl_ext_li_field)
3114 {
3115     wmem_tree_key_t key[3];
3116     guint32 id;
3117     rlc_ue_parameters *params;
3118
3119     if (PINFO_FD_VISITED(pinfo)) {
3120         return;
3121     }
3122
3123     id = (drbid << 16) | ueid;
3124     key[0].length = 1;
3125     key[0].key = &id;
3126     key[1].length = 1;
3127     key[1].key = &pinfo->num;
3128     key[2].length = 0;
3129     key[2].key = NULL;
3130
3131     params = (rlc_ue_parameters *)wmem_tree_lookup32_array_le(ue_parameters_tree, key);
3132     if (params && (params->id != id)) {
3133         params = NULL;
3134     }
3135     if (params == NULL) {
3136         params = (rlc_ue_parameters *)wmem_new(wmem_file_scope(), rlc_ue_parameters);
3137         params->id = id;
3138         params->pdcp_sn_bits = 12;
3139         wmem_tree_insert32_array(ue_parameters_tree, key, (void *)params);
3140     }
3141     params->ext_li_field = ul_ext_li_field ? UL_EXT_LI : NO_EXT_LI;
3142     params->ext_li_field |= dl_ext_li_field ? DL_EXT_LI : NO_EXT_LI;
3143 }
3144
3145 void proto_register_rlc_lte(void)
3146 {
3147     static hf_register_info hf[] =
3148     {
3149         /**********************************/
3150         /* Items for decoding context     */
3151         { &hf_rlc_lte_context,
3152             { "Context",
3153               "rlc-lte.context", FT_STRING, BASE_NONE, NULL, 0x0,
3154               NULL, HFILL
3155             }
3156         },
3157         { &hf_rlc_lte_context_mode,
3158             { "RLC Mode",
3159               "rlc-lte.mode", FT_UINT8, BASE_DEC, VALS(rlc_mode_vals), 0x0,
3160               NULL, HFILL
3161             }
3162         },
3163         { &hf_rlc_lte_context_direction,
3164             { "Direction",
3165               "rlc-lte.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
3166               "Direction of message", HFILL
3167             }
3168         },
3169         { &hf_rlc_lte_context_priority,
3170             { "Priority",
3171               "rlc-lte.priority", FT_UINT8, BASE_DEC, 0, 0x0,
3172               NULL, HFILL
3173             }
3174         },
3175         { &hf_rlc_lte_context_ueid,
3176             { "UEId",
3177               "rlc-lte.ueid", FT_UINT16, BASE_DEC, 0, 0x0,
3178               "User Equipment Identifier associated with message", HFILL
3179             }
3180         },
3181         { &hf_rlc_lte_context_channel_type,
3182             { "Channel Type",
3183               "rlc-lte.channel-type", FT_UINT16, BASE_DEC, VALS(rlc_channel_type_vals), 0x0,
3184               "Channel Type associated with message", HFILL
3185             }
3186         },
3187         { &hf_rlc_lte_context_channel_id,
3188             { "Channel ID",
3189               "rlc-lte.channel-id", FT_UINT16, BASE_DEC, 0, 0x0,
3190               "Channel ID associated with message", HFILL
3191             }
3192         },
3193         { &hf_rlc_lte_context_pdu_length,
3194             { "PDU Length",
3195               "rlc-lte.pdu-length", FT_UINT16, BASE_DEC, 0, 0x0,
3196               "Length of PDU (in bytes)", HFILL
3197             }
3198         },
3199         { &hf_rlc_lte_context_um_sn_length,
3200             { "UM Sequence number length",
3201               "rlc-lte.um-seqnum-length", FT_UINT8, BASE_DEC, 0, 0x0,
3202               "Length of UM sequence number in bits", HFILL
3203             }
3204         },
3205         { &hf_rlc_lte_context_am_sn_length,
3206             { "AM Sequence number length",
3207               "rlc-lte.am-seqnum-length", FT_UINT8, BASE_DEC, 0, 0x0,
3208               "Length of AM sequence number in bits", HFILL
3209             }
3210         },
3211
3212         /* Transparent mode fields */
3213         { &hf_rlc_lte_tm,
3214             { "TM",
3215               "rlc-lte.tm", FT_STRING, BASE_NONE, NULL, 0x0,
3216               "Transparent Mode", HFILL
3217             }
3218         },
3219         { &hf_rlc_lte_tm_data,
3220             { "TM Data",
3221               "rlc-lte.tm.data", FT_BYTES, BASE_NONE, 0, 0x0,
3222               "Transparent Mode Data", HFILL
3223             }
3224         },
3225
3226         /* Unacknowledged mode fields */
3227         { &hf_rlc_lte_um,
3228             { "UM",
3229               "rlc-lte.um", FT_STRING, BASE_NONE, NULL, 0x0,
3230               "Unacknowledged Mode", HFILL
3231             }
3232         },
3233         { &hf_rlc_lte_um_header,
3234             { "UM Header",
3235               "rlc-lte.um.header", FT_STRING, BASE_NONE, NULL, 0x0,
3236               "Unacknowledged Mode Header", HFILL
3237             }
3238         },
3239         { &hf_rlc_lte_um_fi,
3240             { "Framing Info",
3241               "rlc-lte.um.fi", FT_UINT8, BASE_HEX, VALS(framing_info_vals), 0x0,
3242               NULL, HFILL
3243             }
3244         },
3245         { &hf_rlc_lte_um_fixed_e,
3246             { "Extension",
3247               "rlc-lte.um.fixed.e", FT_UINT8, BASE_HEX, VALS(fixed_extension_vals), 0x0,
3248               "Extension in fixed part of UM header", HFILL
3249             }
3250         },
3251         { &hf_rlc_lte_um_sn,
3252             { "Sequence number",
3253               "rlc-lte.um.sn", FT_UINT8, BASE_DEC, 0, 0x0,
3254               "Unacknowledged Mode Sequence Number", HFILL
3255             }
3256         },
3257         { &hf_rlc_lte_um_fixed_reserved,
3258             { "Reserved",
3259               "rlc-lte.um.reserved", FT_UINT8, BASE_DEC, 0, 0xe0,
3260               "Unacknowledged Mode Fixed header reserved bits", HFILL
3261             }
3262         },
3263         { &hf_rlc_lte_um_data,
3264             { "UM Data",
3265               "rlc-lte.um.data", FT_BYTES, BASE_NONE, 0, 0x0,
3266               "Unacknowledged Mode Data", HFILL
3267             }
3268         },
3269         { &hf_rlc_lte_extension_part,
3270             { "Extension Part",
3271               "rlc-lte.extension-part", FT_STRING, BASE_NONE, 0, 0x0,
3272               NULL, HFILL
3273             }
3274         },
3275         { &hf_rlc_lte_extension_e,
3276             { "Extension",
3277               "rlc-lte.extension.e", FT_UINT8, BASE_HEX, VALS(extension_extension_vals), 0x0,
3278               "Extension in extended part of the header", HFILL
3279             }
3280         },
3281         { &hf_rlc_lte_extension_li,
3282             { "Length Indicator",
3283               "rlc-lte.extension.li", FT_UINT16, BASE_DEC, 0, 0x0,
3284               NULL, HFILL
3285             }
3286         },
3287         { &hf_rlc_lte_extension_padding,
3288             { "Padding",
3289               "rlc-lte.extension.padding", FT_UINT8, BASE_HEX, 0, 0x0f,
3290               "Extension header padding", HFILL
3291             }
3292         },
3293
3294         /* Acknowledged mode fields */
3295         { &hf_rlc_lte_am,
3296             { "AM",
3297               "rlc-lte.am", FT_STRING, BASE_NONE, NULL, 0x0,
3298               "Acknowledged Mode", HFILL
3299             }
3300         },
3301         { &hf_rlc_lte_am_header,
3302             { "AM Header",
3303               "rlc-lte.am.header", FT_STRING, BASE_NONE, NULL, 0x0,
3304               "Acknowledged Mode Header", HFILL
3305             }
3306         },
3307         { &hf_rlc_lte_am_data_control,
3308             { "Frame type",
3309               "rlc-lte.am.frame-type", FT_UINT8, BASE_HEX, VALS(data_or_control_vals), 0x80,
3310               "AM Frame Type (Control or Data)", HFILL
3311             }
3312         },
3313         { &hf_rlc_lte_am_rf,
3314             { "Re-segmentation Flag",
3315               "rlc-lte.am.rf", FT_UINT8, BASE_HEX, VALS(resegmentation_flag_vals), 0x40,
3316               "AM Re-segmentation Flag", HFILL
3317             }
3318         },
3319         { &hf_rlc_lte_am_p,
3320             { "Polling Bit",
3321               "rlc-lte.am.p", FT_UINT8, BASE_HEX, VALS(polling_bit_vals), 0x20,
3322               NULL, HFILL
3323             }
3324         },
3325         { &hf_rlc_lte_am_fi,
3326             { "Framing Info",
3327               "rlc-lte.am.fi", FT_UINT8, BASE_HEX, VALS(framing_info_vals), 0x18,
3328               "AM Framing Info", HFILL
3329             }
3330         },
3331         { &hf_rlc_lte_am_fixed_e,
3332             { "Extension",
3333               "rlc-lte.am.fixed.e", FT_UINT8, BASE_HEX, VALS(fixed_extension_vals), 0x04,
3334               "Fixed Extension Bit", HFILL
3335             }
3336         },
3337         { &hf_rlc_lte_am_fixed_sn,
3338             { "Sequence Number",
3339               "rlc-lte.am.fixed.sn", FT_UINT16, BASE_DEC, 0, 0x03ff,
3340               "AM Fixed Sequence Number", HFILL
3341             }
3342         },
3343         { &hf_rlc_lte_am_fixed_reserved,
3344             { "Reserved",
3345               "rlc-lte.am.reserved", FT_UINT8, BASE_DEC, 0, 0x03,
3346               "Acknowledged Mode Fixed header reserved bits", HFILL
3347             }
3348         },
3349         { &hf_rlc_lte_am_segment_lsf16,
3350             { "Last Segment Flag",
3351               "rlc-lte.am.segment.lsf", FT_UINT8, BASE_HEX, VALS(lsf_vals), 0x02,
3352               NULL, HFILL
3353             }
3354         },
3355         { &hf_rlc_lte_am_fixed_reserved2,
3356             { "Reserved",
3357               "rlc-lte.am.reserved", FT_UINT8, BASE_DEC, 0, 0x01,
3358               "Acknowledged Mode Fixed header reserved bit", HFILL
3359             }
3360         },
3361         { &hf_rlc_lte_am_fixed_sn16,
3362             { "Sequence Number",
3363               "rlc-lte.am.fixed.sn", FT_UINT16, BASE_DEC, 0, 0xffff,
3364               "AM Fixed Sequence Number", HFILL
3365             }
3366         },
3367         { &hf_rlc_lte_am_segment_lsf,
3368             { "Last Segment Flag",
3369               "rlc-lte.am.segment.lsf", FT_UINT8, BASE_HEX, VALS(lsf_vals), 0x80,
3370               NULL, HFILL
3371             }
3372         },
3373         { &hf_rlc_lte_am_segment_so,
3374             { "Segment Offset",
3375               "rlc-lte.am.segment.offset", FT_UINT16, BASE_DEC, 0, 0x7fff,
3376               NULL, HFILL
3377             }
3378         },
3379         { &hf_rlc_lte_am_segment_so16,
3380             { "Segment Offset",
3381               "rlc-lte.am.segment.offset", FT_UINT16, BASE_DEC, 0, 0xffff,
3382               NULL, HFILL
3383             }
3384         },
3385         { &hf_rlc_lte_am_data,
3386             { "AM Data",
3387               "rlc-lte.am.data", FT_BYTES, BASE_NONE, 0, 0x0,
3388               "Acknowledged Mode Data", HFILL
3389             }
3390         },
3391
3392         { &hf_rlc_lte_am_cpt,
3393             { "Control PDU Type",
3394               "rlc-lte.am.cpt", FT_UINT8, BASE_HEX, VALS(control_pdu_type_vals), 0x70,
3395               "AM Control PDU Type", HFILL
3396             }
3397         },
3398         { &hf_rlc_lte_am_ack_sn,
3399             { "ACK Sequence Number",
3400               "rlc-lte.am.ack-sn", FT_UINT16, BASE_DEC, 0, 0x0,
3401               "Sequence Number we expect to receive next", HFILL
3402             }
3403         },
3404         { &hf_rlc_lte_am_e1,
3405             { "Extension bit 1",
3406               "rlc-lte.am.e1", FT_UINT8, BASE_HEX, VALS(am_e1_vals), 0x0,
3407               NULL, HFILL
3408             }
3409         },
3410         { &hf_rlc_lte_am_e2,
3411             { "Extension bit 2",
3412               "rlc-lte.am.e2", FT_UINT8, BASE_HEX, VALS(am_e2_vals), 0x0,
3413               NULL, HFILL
3414             }
3415         },
3416         { &hf_rlc_lte_am_nacks,
3417             { "Number of NACKs",
3418               "rlc-lte.am.nacks", FT_UINT16, BASE_DEC, 0, 0x0,
3419               "Number of NACKs in this status PDU", HFILL
3420             }
3421         },
3422         { &hf_rlc_lte_am_nack_sn,
3423             { "NACK Sequence Number",
3424               "rlc-lte.am.nack-sn", FT_UINT16, BASE_DEC, 0, 0x0,
3425               "Negative Acknowledgement Sequence Number", HFILL
3426             }
3427         },
3428         { &hf_rlc_lte_am_so_start,
3429             { "SO Start",
3430               "rlc-lte.am.so-start", FT_UINT16, BASE_DEC, 0, 0x0,
3431               "Segment Offset Start byte index", HFILL
3432             }
3433         },
3434         { &hf_rlc_lte_am_so_end,
3435             { "SO End",
3436               "rlc-lte.am.so-end", FT_UINT16, BASE_DEC, 0, 0x0,
3437               "Segment Offset End byte index", HFILL
3438             }
3439         },
3440
3441         { &hf_rlc_lte_predefined_pdu,
3442             { "Predefined data",
3443               "rlc-lte.predefined-data", FT_BYTES, BASE_NONE, 0, 0x0,
3444               "Predefined test data", HFILL
3445             }
3446         },
3447
3448         /* Sequence analysis fields */
3449         { &hf_rlc_lte_sequence_analysis,
3450             { "Sequence Analysis",
3451               "rlc-lte.sequence-analysis", FT_STRING, BASE_NONE, 0, 0x0,
3452               NULL, HFILL
3453             }
3454         },
3455         { &hf_rlc_lte_sequence_analysis_ok,
3456             { "OK",
3457               "rlc-lte.sequence-analysis.ok", FT_BOOLEAN, BASE_NONE, 0, 0x0,
3458               NULL, HFILL
3459             }
3460         },
3461         { &hf_rlc_lte_sequence_analysis_previous_frame,
3462             { "Previous frame for channel",
3463               "rlc-lte.sequence-analysis.previous-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
3464               NULL, HFILL
3465             }
3466         },
3467         { &hf_rlc_lte_sequence_analysis_next_frame,
3468             { "Next frame for channel",
3469               "rlc-lte.sequence-analysis.next-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
3470               NULL, HFILL
3471             }
3472         },
3473         { &hf_rlc_lte_sequence_analysis_expected_sn,
3474             { "Expected SN",
3475               "rlc-lte.sequence-analysis.expected-sn", FT_UINT16, BASE_DEC, 0, 0x0,
3476               NULL, HFILL
3477             }
3478         },
3479         { &hf_rlc_lte_sequence_analysis_framing_info_correct,
3480             { "Frame info continued correctly",
3481               "rlc-lte.sequence-analysis.framing-info-correct", FT_BOOLEAN, BASE_NONE, 0, 0x0,
3482               NULL, HFILL
3483             }
3484         },
3485         { &hf_rlc_lte_sequence_analysis_mac_retx,
3486             { "Frame retransmitted by MAC",
3487               "rlc-lte.sequence-analysis.mac-retx", FT_BOOLEAN, BASE_NONE, 0, 0x0,
3488               NULL, HFILL
3489             }
3490         },
3491         { &hf_rlc_lte_sequence_analysis_retx,
3492             { "Retransmitted frame",
3493               "rlc-lte.sequence-analysis.retx", FT_BOOLEAN, BASE_NONE, 0, 0x0,
3494               NULL, HFILL
3495             }
3496         },
3497         { &hf_rlc_lte_sequence_analysis_skipped,
3498             { "Skipped frames",
3499               "rlc-lte.sequence-analysis.skipped-frames", FT_BOOLEAN, BASE_NONE, 0, 0x0,
3500               NULL, HFILL
3501             }
3502         },
3503         { &hf_rlc_lte_sequence_analysis_repeated,
3504             { "Repeated frame",
3505               "rlc-lte.sequence-analysis.repeated-frame", FT_BOOLEAN, BASE_NONE, 0, 0x0,
3506               NULL, HFILL
3507             }
3508         },
3509         { &hf_rlc_lte_sequence_analysis_repeated_nack,
3510             { "Repeated NACK",
3511               "rlc-lte.sequence-analysis.repeated-nack", FT_UINT16, BASE_DEC, 0, 0x0,
3512               NULL, HFILL
3513             }
3514         },
3515         { &hf_rlc_lte_sequence_analysis_repeated_nack_original_frame,
3516             { "Frame with previous status PDU",
3517               "rlc-lte.sequence-analysis.repeated-nack.original-frame",  FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_DUP_ACK), 0x0,
3518               NULL, HFILL
3519             }
3520         },
3521
3522         { &hf_rlc_lte_sequence_analysis_ack_out_of_range,
3523             { "Out of range ACK",
3524               "rlc-lte.sequence-analysis.ack-out-of-range", FT_BOOLEAN, BASE_NONE, 0, 0x0,
3525               NULL, HFILL
3526             }
3527         },
3528         { &hf_rlc_lte_sequence_analysis_ack_out_of_range_opposite_frame,
3529             { "Frame with most recent SN",
3530               "rlc-lte.sequence-analysis.ack-out-of-range.last-sn-frame",  FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3531               NULL, HFILL
3532             }
3533         },
3534
3535         /* Reassembly fields */
3536         { &hf_rlc_lte_reassembly_source,
3537             { "Reassembly Source",
3538               "rlc-lte.reassembly-info", FT_STRING, BASE_NONE, 0, 0x0,
3539               NULL, HFILL
3540             }
3541         },
3542         { &hf_rlc_lte_reassembly_source_number_of_segments,
3543             { "Number of segments",
3544               "rlc-lte.reassembly-info.number-of-segments", FT_UINT16, BASE_DEC, 0, 0x0,
3545               NULL, HFILL
3546             }
3547         },
3548         { &hf_rlc_lte_reassembly_source_total_length,
3549             { "Total length",
3550               "rlc-lte.reassembly-info.total-length", FT_UINT16, BASE_DEC, 0, 0x0,
3551               NULL, HFILL
3552             }
3553         },
3554         { &hf_rlc_lte_reassembly_source_segment,
3555             { "Segment",
3556               "rlc-lte.reassembly-info.segment", FT_NONE, BASE_NONE, 0, 0x0,
3557               NULL, HFILL
3558             }
3559         },
3560         { &hf_rlc_lte_reassembly_source_segment_sn,
3561             { "SN",
3562               "rlc-lte.reassembly-info.segment.sn", FT_UINT16, BASE_DEC, 0, 0x0,
3563               NULL, HFILL
3564             }
3565         },
3566         { &hf_rlc_lte_reassembly_source_segment_framenum,
3567             { "Frame",
3568               "rlc-lte.reassembly-info.segment.frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3569               NULL, HFILL
3570             }
3571         },
3572         { &hf_rlc_lte_reassembly_source_segment_length,
3573             { "Length",
3574               "rlc-lte.reassembly-info.segment.length", FT_UINT32, BASE_DEC, 0, 0x0,
3575               NULL, HFILL
3576             }
3577         },
3578
3579         { &hf_rlc_lte_header_only,
3580             { "RLC PDU Header only",
3581               "rlc-lte.header-only", FT_UINT8, BASE_DEC, VALS(header_only_vals), 0x0,
3582               NULL, HFILL
3583             }
3584         },
3585     };
3586
3587     static gint *ett[] =
3588     {
3589         &ett_rlc_lte,
3590         &ett_rlc_lte_context,
3591         &ett_rlc_lte_um_header,
3592         &ett_rlc_lte_am_header,
3593         &ett_rlc_lte_extension_part,
3594         &ett_rlc_lte_sequence_analysis,
3595         &ett_rlc_lte_reassembly_source,
3596         &ett_rlc_lte_reassembly_source_segment
3597     };
3598
3599     static ei_register_info ei[] = {
3600         { &ei_rlc_lte_sequence_analysis_last_segment_not_continued, { "rlc-lte.sequence-analysis.last-segment-not-continued", PI_SEQUENCE, PI_WARN, "Last segment of previous PDU was not continued for UE", EXPFILL }},
3601         { &ei_rlc_lte_sequence_analysis_last_segment_complete, { "rlc-lte.sequence-analysis.last-segment-complete", PI_SEQUENCE, PI_WARN, "Last segment of previous PDU was complete, but new segment was not started on UE", EXPFILL }},
3602         { &ei_rlc_lte_sequence_analysis_mac_retx, { "rlc-lte.sequence-analysis.mac-retx.expert", PI_SEQUENCE, PI_WARN, "AM Frame retransmitted due to MAC retx!", EXPFILL }},
3603         { &ei_rlc_lte_sequence_analysis_retx, { "rlc-lte.sequence-analysis.retx.expert", PI_SEQUENCE, PI_WARN, "AM Frame retransmitted most likely in response to NACK", EXPFILL }},
3604         { &ei_rlc_lte_sequence_analysis_repeated, { "rlc-lte.sequence-analysis.repeated-frame.expert", PI_SEQUENCE, PI_WARN, "AM SN Repeated - probably because didn't receive Status PDU?", EXPFILL }},
3605         { &ei_rlc_lte_am_sn_missing, { "rlc-lte.sequence-analysis.am-sn.missing", PI_SEQUENCE, PI_WARN, "AM SNs missing", EXPFILL }},
3606         { &ei_rlc_lte_sequence_analysis_ack_out_of_range_opposite_frame, { "rlc-lte.sequence-analysis.ack-out-of-range.last-sn-frame.expert", PI_SEQUENCE, PI_ERROR, "AM ACK for SN - but last received SN in other direction is X", EXPFILL }},
3607         { &ei_rlc_lte_um_sn_missing, { "rlc-lte.sequence-analysis.um-sn.missing", PI_SEQUENCE, PI_WARN, "UM SNs missing", EXPFILL }},
3608         { &ei_rlc_lte_um_sn_repeated, { "rlc-lte.sequence-analysis.um-sn.repeated", PI_SEQUENCE, PI_WARN, "UM SN repeated", EXPFILL }},
3609         { &ei_rlc_lte_wrong_sequence_number, { "rlc-lte.wrong-sequence-number", PI_SEQUENCE, PI_WARN, "Wrong Sequence Number", EXPFILL }},
3610         { &ei_rlc_lte_sequence_analysis_repeated_nack, { "rlc-lte.sequence-analysis.repeated-nack.expert", PI_SEQUENCE, PI_ERROR, "Same SN NACKd on successive Status PDUs", EXPFILL }},
3611         { &ei_rlc_lte_reserved_bits_not_zero, { "rlc-lte.reserved-bits-not-zero", PI_MALFORMED, PI_ERROR, "Reserved bits not zero", EXPFILL }},
3612         { &ei_rlc_lte_um_sn, { "rlc-lte.um.sn.invalid", PI_MALFORMED, PI_ERROR, "Invalid sequence number length", EXPFILL }},
3613         { &ei_rlc_lte_header_only, { "rlc-lte.header-only.expert", PI_SEQUENCE, PI_NOTE, "RLC PDU SDUs have been omitted", EXPFILL }},
3614         { &ei_rlc_lte_am_cpt, { "rlc-lte.am.cpt.invalid", PI_MALFORMED, PI_ERROR, "RLC Control frame type not handled", EXPFILL }},
3615         { &ei_rlc_lte_am_nack_sn_ack_same, { "rlc-lte.am.nack-sn.ack-same", PI_MALFORMED, PI_ERROR, "Status PDU shouldn't ACK and NACK the same sequence number", EXPFILL }},
3616         { &ei_rlc_lte_am_nack_sn_ahead_ack, { "rlc-lte.am.nack-sn.ahead-ack", PI_MALFORMED, PI_ERROR, "NACK must not be ahead of ACK in status PDU", EXPFILL }},
3617         { &ei_rlc_lte_am_nack_sn_partial, { "rlc-lte.am.nack-sn.partial", PI_SEQUENCE, PI_WARN, "Status PDU reports NACK (partial)", EXPFILL }},
3618         { &ei_rlc_lte_am_nack_sn, { "rlc-lte.am.nack-sn.expert", PI_SEQUENCE, PI_WARN, "Status PDU reports NACK", EXPFILL }},
3619         { &ei_rlc_lte_bytes_after_status_pdu_complete, { "rlc-lte.bytes-after-status-pdu-complete", PI_MALFORMED, PI_ERROR, "bytes remaining after Status PDU complete", EXPFILL }},
3620         { &ei_rlc_lte_am_data_no_data_beyond_extensions, { "rlc-lte.am-data.no-data-beyond-extensions", PI_MALFORMED, PI_ERROR, "AM data PDU doesn't contain any data beyond extensions", EXPFILL }},
3621         { &ei_rlc_lte_am_data_no_data, { "rlc-lte.am-data.no-data", PI_MALFORMED, PI_ERROR, "AM data PDU doesn't contain any data", EXPFILL }},
3622         { &ei_rlc_lte_context_mode, { "rlc-lte.mode.invalid", PI_MALFORMED, PI_ERROR, "Unrecognised RLC Mode set", EXPFILL }},
3623         { &ei_rlc_lte_no_per_frame_info, { "rlc-lte.no_per_frame_info", PI_UNDECODED, PI_ERROR, "Can't dissect LTE RLC frame because no per-frame info was attached!", EXPFILL }},
3624         { &ei_rlc_lte_unknown_udp_framing_tag, { "rlc-lte.unknown-udp-framing-tag", PI_UNDECODED, PI_WARN, "Unknown UDP framing tag, aborting dissection", EXPFILL }},
3625         { &ei_rlc_lte_missing_udp_framing_tag, { "rlc-lte.missing-udp-framing-tag", PI_UNDECODED, PI_WARN, "Missing UDP framing conditional tag, aborting dissection", EXPFILL }}
3626     };
3627
3628     static const enum_val_t sequence_analysis_vals[] = {
3629         {"no-analysis", "No-Analysis",     FALSE},
3630         {"mac-only",    "Only-MAC-frames", SEQUENCE_ANALYSIS_MAC_ONLY},
3631         {"rlc-only",    "Only-RLC-frames", SEQUENCE_ANALYSIS_RLC_ONLY},
3632         {NULL, NULL, -1}
3633     };
3634
3635     module_t *rlc_lte_module;
3636     expert_module_t* expert_rlc_lte;
3637
3638     /* Register protocol. */
3639     proto_rlc_lte = proto_register_protocol("RLC-LTE", "RLC-LTE", "rlc-lte");
3640     proto_register_field_array(proto_rlc_lte, hf, array_length(hf));
3641     proto_register_subtree_array(ett, array_length(ett));
3642     expert_rlc_lte = expert_register_protocol(proto_rlc_lte);
3643     expert_register_field_array(expert_rlc_lte, ei, array_length(ei));
3644
3645     /* Allow other dissectors to find this one by name. */
3646     register_dissector("rlc-lte", dissect_rlc_lte, proto_rlc_lte);
3647
3648     /* Register the tap name */
3649     rlc_lte_tap = register_tap("rlc-lte");
3650
3651     /* Preferences */
3652     rlc_lte_module = prefs_register_protocol(proto_rlc_lte, NULL);
3653
3654     prefs_register_enum_preference(rlc_lte_module, "do_sequence_analysis_am",
3655         "Do sequence analysis for AM channels",
3656         "Attempt to keep track of PDUs for AM channels, and point out problems",
3657         &global_rlc_lte_am_sequence_analysis, sequence_analysis_vals, FALSE);
3658
3659     prefs_register_enum_preference(rlc_lte_module, "do_sequence_analysis",
3660         "Do sequence analysis for UM channels",
3661         "Attempt to keep track of PDUs for UM channels, and point out problems",
3662         &global_rlc_lte_um_sequence_analysis, sequence_analysis_vals, FALSE);
3663
3664     prefs_register_bool_preference(rlc_lte_module, "call_pdcp_for_srb",
3665         "Call PDCP dissector for SRB PDUs",
3666         "Call PDCP dissector for signalling PDUs.  Note that without reassembly, it can"
3667         "only be called for complete PDUs (i.e. not segmented over RLC)",
3668         &global_rlc_lte_call_pdcp_for_srb);
3669
3670     prefs_register_enum_preference(rlc_lte_module, "call_pdcp_for_drb",
3671         "Call PDCP dissector for DRB PDUs",
3672         "Call PDCP dissector for user-plane PDUs.  Note that without reassembly, it can"
3673         "only be called for complete PDUs (i.e. not segmented over RLC)",
3674         &global_rlc_lte_call_pdcp_for_drb, pdcp_drb_col_vals, FALSE);
3675
3676
3677     prefs_register_bool_preference(rlc_lte_module, "call_rrc_for_ccch",
3678         "Call RRC dissector for CCCH PDUs",
3679         "Call RRC dissector for CCCH PDUs",
3680         &global_rlc_lte_call_rrc_for_ccch);
3681
3682     prefs_register_bool_preference(rlc_lte_module, "call_rrc_for_mcch",
3683         "Call RRC dissector for MCCH PDUs",
3684         "Call RRC dissector for MCCH PDUs  Note that without reassembly, it can"
3685         "only be called for complete PDUs (i.e. not segmented over RLC)",
3686         &global_rlc_lte_call_rrc_for_mcch);
3687
3688     prefs_register_bool_preference(rlc_lte_module, "call_ip_for_mtch",
3689         "Call IP dissector for MTCH PDUs",
3690         "Call ip dissector for MTCH PDUs  Note that without reassembly, it can"
3691         "only be called for complete PDUs (i.e. not segmented over RLC)",
3692         &global_rlc_lte_call_ip_for_mtch);
3693
3694     prefs_register_obsolete_preference(rlc_lte_module, "heuristic_rlc_lte_over_udp");
3695
3696     prefs_register_bool_preference(rlc_lte_module, "header_only_mode",
3697         "May see RLC headers only",
3698         "When enabled, if data is not present, don't report as an error, but instead "
3699         "add expert info to indicate that headers were omitted",
3700         &global_rlc_lte_headers_expected);
3701
3702     prefs_register_bool_preference(rlc_lte_module, "reassembly",
3703         "Attempt SDU reassembly",
3704         "When enabled, attempts to re-assemble upper-layer SDUs that are split over "
3705         "more than one RLC PDU.  Note: does not currently support out-of-order or "
3706         "re-segmentation. N.B. sequence analysis must also be turned on in order "
3707         "for reassembly to work",
3708         &global_rlc_lte_reassembly);
3709
3710     ue_parameters_tree = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
3711
3712     sequence_analysis_channel_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), rlc_channel_hash_func, rlc_channel_equal);
3713     sequence_analysis_report_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), rlc_result_hash_func, rlc_result_hash_equal);
3714     repeated_nack_channel_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), rlc_channel_hash_func, rlc_channel_equal);
3715     repeated_nack_report_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), rlc_result_hash_func, rlc_result_hash_equal);
3716     reassembly_report_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), rlc_result_hash_func, rlc_result_hash_equal);
3717 }
3718
3719 void proto_reg_handoff_rlc_lte(void)
3720 {
3721     /* Add as a heuristic UDP dissector */
3722     heur_dissector_add("udp", dissect_rlc_lte_heur, "RLC-LTE over UDP", "rlc_lte_udp", proto_rlc_lte, HEURISTIC_DISABLE);
3723
3724     pdcp_lte_handle        = find_dissector_add_dependency("pdcp-lte", proto_rlc_lte);
3725     ip_handle              = find_dissector_add_dependency("ip", proto_rlc_lte);
3726     lte_rrc_mcch           = find_dissector_add_dependency("lte_rrc.mcch", proto_rlc_lte);
3727     lte_rrc_ul_ccch        = find_dissector_add_dependency("lte_rrc.ul_ccch", proto_rlc_lte);
3728     lte_rrc_dl_ccch        = find_dissector_add_dependency("lte_rrc.dl_dcch", proto_rlc_lte);
3729     lte_rrc_bcch_bch       = find_dissector_add_dependency("lte_rrc.bcch_bch", proto_rlc_lte);
3730     lte_rrc_bcch_dl_sch    = find_dissector_add_dependency("lte_rrc.bcch_dl_sch", proto_rlc_lte);
3731     lte_rrc_pcch           = find_dissector_add_dependency("lte_rrc.pcch", proto_rlc_lte);
3732     lte_rrc_ul_ccch_nb     = find_dissector_add_dependency("lte_rrc.ul_ccch.nb", proto_rlc_lte);
3733     lte_rrc_dl_ccch_nb     = find_dissector_add_dependency("lte_rrc.dl_ccch.nb", proto_rlc_lte);
3734     lte_rrc_bcch_bch_nb    = find_dissector_add_dependency("lte_rrc.bcch_bch.nb", proto_rlc_lte);
3735     lte_rrc_bcch_dl_sch_nb = find_dissector_add_dependency("lte_rrc.bcch_dl_sch.nb", proto_rlc_lte);
3736     lte_rrc_pcch_nb        = find_dissector_add_dependency("lte_rrc.pcch.nb", proto_rlc_lte);
3737 }
3738
3739 /*
3740  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
3741  *
3742  * Local variables:
3743  * c-basic-offset: 4
3744  * tab-width: 8
3745  * indent-tabs-mode: nil
3746  * End:
3747  *
3748  * vi: set shiftwidth=4 tabstop=8 expandtab:
3749  * :indentSize=4:tabSize=8:noTabs=true:
3750  */