Tidy up info column output showing partial NACK.
[obnox/wireshark/wip.git] / epan / dissectors / packet-rlc-lte.c
1 /* Routines for LTE RLC disassembly
2  *
3  * Martin Mathieson
4  *
5  * $Id$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <string.h>
31
32 #include <epan/packet.h>
33 #include <epan/expert.h>
34 #include <epan/prefs.h>
35
36 #include "packet-rlc-lte.h"
37
38
39 /* Described in:
40  * 3GPP TS 36.322 Evolved Universal Terrestial Radio Access (E-UTRA)
41  * Radio Link Control (RLC) Protocol specification
42  */
43
44 /* TODO:
45    - AM sequence analysis/re-assembly?
46 */
47
48
49 /* By default try to analyse the sequence of messages for UM channels */
50 static gboolean global_rlc_lte_sequence_analysis = TRUE;
51
52
53
54 /* Initialize the protocol and registered fields. */
55 int proto_rlc_lte = -1;
56
57 /* Decoding context */
58 static int hf_rlc_lte_context_mode = -1;
59 static int hf_rlc_lte_context_direction = -1;
60 static int hf_rlc_lte_context_priority = -1;
61 static int hf_rlc_lte_context_ueid = -1;
62 static int hf_rlc_lte_context_channel_type = -1;
63 static int hf_rlc_lte_context_channel_id = -1;
64 static int hf_rlc_lte_context_pdu_length = -1;
65 static int hf_rlc_lte_context_um_sn_length = -1;
66
67 /* Transparent mode fields */
68 static int hf_rlc_lte_tm_data = -1;
69
70 /* Unacknowledged mode fields */
71 static int hf_rlc_lte_um_header = -1;
72 static int hf_rlc_lte_um_fi = -1;
73 static int hf_rlc_lte_um_fixed_e = -1;
74 static int hf_rlc_lte_um_sn = -1;
75 static int hf_rlc_lte_um_fixed_reserved = -1;
76 static int hf_rlc_lte_um_data = -1;
77 static int hf_rlc_lte_extension_part = -1;
78
79 /* Extended header (common to UM and AM) */
80 static int hf_rlc_lte_extension_e = -1;
81 static int hf_rlc_lte_extension_li = -1;
82 static int hf_rlc_lte_extension_padding = -1;
83
84
85 /* Acknowledged mode fields */
86 static int hf_rlc_lte_am_header = -1;
87 static int hf_rlc_lte_am_data_control = -1;
88 static int hf_rlc_lte_am_rf = -1;
89 static int hf_rlc_lte_am_p = -1;
90 static int hf_rlc_lte_am_fi = -1;
91 static int hf_rlc_lte_am_fixed_e = -1;
92 static int hf_rlc_lte_am_fixed_sn = -1;
93 static int hf_rlc_lte_am_segment_lsf = -1;
94 static int hf_rlc_lte_am_segment_so = -1;
95 static int hf_rlc_lte_am_data = -1;
96
97 /* Control fields */
98 static int hf_rlc_lte_am_cpt = -1;
99 static int hf_rlc_lte_am_ack_sn = -1;
100 static int hf_rlc_lte_am_e1 = -1;
101 static int hf_rlc_lte_am_e2 = -1;
102 static int hf_rlc_lte_am_nack_sn = -1;
103 static int hf_rlc_lte_am_so_start = -1;
104 static int hf_rlc_lte_am_so_end = -1;
105
106 static int hf_rlc_lte_predefined_pdu = -1;
107
108 /* Sequence Analysis */
109 static int hf_rlc_lte_sequence_analysis = -1;
110 static int hf_rlc_lte_sequence_analysis_previous_frame = -1;
111 static int hf_rlc_lte_sequence_analysis_expected_sn = -1;
112 static int hf_rlc_lte_sequence_analysis_framing_info_correct = -1;
113
114
115 /* Subtrees. */
116 static int ett_rlc_lte = -1;
117 static int ett_rlc_lte_um_header = -1;
118 static int ett_rlc_lte_am_header = -1;
119 static int ett_rlc_lte_extension_part = -1;
120 static int ett_rlc_lte_sequence_analysis = -1;
121
122
123 static const value_string direction_vals[] =
124 {
125     { DIRECTION_UPLINK,      "Uplink"},
126     { DIRECTION_DOWNLINK,    "Downlink"},
127     { 0, NULL }
128 };
129
130 static const value_string rlc_mode_short_vals[] =
131 {
132     { RLC_TM_MODE,      "TM"},
133     { RLC_UM_MODE,      "UM"},
134     { RLC_AM_MODE,      "AM"},
135     { RLC_PREDEF,       "PREDEFINED"},
136     { 0, NULL }
137 };
138
139 static const value_string rlc_mode_vals[] =
140 {
141     { RLC_TM_MODE,      "Transparent Mode"},
142     { RLC_UM_MODE,      "Unacknowledged Mode"},
143     { RLC_AM_MODE,      "Acknowledged Mode"},
144     { 0, NULL }
145 };
146
147
148 static const value_string rlc_channel_type_vals[] =
149 {
150     { CHANNEL_TYPE_CCCH,     "CCCH"},
151     { CHANNEL_TYPE_BCCH,     "BCCH"},
152     { CHANNEL_TYPE_PCCH,     "PCCH"},
153     { CHANNEL_TYPE_SRB,      "SRB"},
154     { CHANNEL_TYPE_DRB,      "DRB"},
155     { 0, NULL }
156 };
157
158
159 static const value_string framing_info_vals[] =
160 {
161     { 0,      "First byte begins an RLC SDU and last byte ends an RLC SDU"},
162     { 1,      "First byte begins an RLC SDU and last byte does not end an RLC SDU"},
163     { 2,      "First byte does not begin an RLC SDU and last byte ends an RLC SDU"},
164     { 3,      "First byte does not begin an RLC SDU and last byte does not end an RLC SDU"},
165     { 0, NULL }
166 };
167
168 static const value_string fixed_extension_vals[] =
169 {
170     { 0,      "Data field follows from the octet following the fixed part of the header"},
171     { 1,      "A set of E field and LI field follows from the octet following the fixed part of the header"},
172     { 0, NULL }
173 };
174
175 static const value_string extension_extension_vals[] =
176 {
177     { 0,      "Data field follows from the octet following the LI field following this E field"},
178     { 1,      "A set of E field and LI field follows from the bit following the LI field following this E field"},
179     { 0, NULL }
180 };
181
182 static const value_string data_or_control_vals[] =
183 {
184     { 0,      "Control PDU"},
185     { 1,      "Data PDU"},
186     { 0, NULL }
187 };
188
189 static const value_string resegmentation_flag_vals[] =
190 {
191     { 0,      "AMD PDU"},
192     { 1,      "AND PDU segment"},
193     { 0, NULL }
194 };
195
196 static const value_string polling_bit_vals[] =
197 {
198     { 0,      "Status report not requested"},
199     { 1,      "Status report is requested"},
200     { 0, NULL }
201 };
202
203
204 static const value_string lsf_vals[] =
205 {
206     { 0,      "Last byte of the AMD PDU segment does not correspond to the last byte of an AMD PDU"},
207     { 1,      "Last byte of the AMD PDU segment corresponds to the last byte of an AND PDU"},
208     { 0, NULL }
209 };
210
211
212 static const value_string control_pdu_type_vals[] =
213 {
214     { 0,      "STATUS PDU"},
215     { 0, NULL }
216 };
217
218 static const value_string am_e1_vals[] =
219 {
220     { 0,      "A set of NACK_SN, E1 and E2 does not follow"},
221     { 1,      "A set of NACK_SN, E1 and E2 follows"},
222     { 0, NULL }
223 };
224
225 static const value_string am_e2_vals[] =
226 {
227     { 0,      "A set of SOstart and SOend does not follow for this NACK_SN"},
228     { 1,      "A set of SOstart and SOend follows for this NACK_SN"},
229     { 0, NULL }
230 };
231
232
233
234 /**********************************************************************************/
235 /* These are for keeping track of UM/AM extension headers, and the lengths found  */
236 /* in them                                                                        */
237 guint8  s_number_of_extensions = 0;
238 #define MAX_RLC_SDUS 64
239 guint16 s_lengths[MAX_RLC_SDUS];
240
241
242 /* Dissect extension headers (common to both UM and AM) */
243 static int dissect_rlc_lte_extension_header(tvbuff_t *tvb, packet_info *pinfo,
244                                             proto_tree *tree,
245                                             int offset)
246 {
247     guint8  isOdd;
248     guint64 extension = 1;
249     guint64 length;
250
251     /* Reset this count */
252     s_number_of_extensions = 0;
253
254     while (extension && (s_number_of_extensions < MAX_RLC_SDUS)) {
255         proto_tree *extension_part_tree;
256         proto_item *extension_part_ti;
257
258         isOdd = (s_number_of_extensions % 2);
259
260         /* Extension part subtree */
261         extension_part_ti = proto_tree_add_string_format(tree,
262                                                          hf_rlc_lte_extension_part,
263                                                          tvb, offset, 2,
264                                                          "",
265                                                          "Extension Part");
266         extension_part_tree = proto_item_add_subtree(extension_part_ti,
267                                                      ett_rlc_lte_extension_part);
268
269         /* Read next extension */
270         proto_tree_add_bits_ret_val(extension_part_tree, hf_rlc_lte_extension_e, tvb,
271                                     (offset*8) + ((isOdd) ? 4 : 0),
272                                     1,
273                                     &extension, FALSE);
274
275         /* Read length field */
276         proto_tree_add_bits_ret_val(extension_part_tree, hf_rlc_lte_extension_li, tvb,
277                                     (offset*8) + ((isOdd) ? 5 : 1),
278                                     11,
279                                     &length, FALSE);
280
281         proto_item_append_text(extension_part_tree, " (length=%u)", (guint16)length);
282
283         /* Move on to byte of next extension */
284         if (isOdd) {
285             offset += 2;
286         } else {
287             offset++;
288         }
289  
290         s_lengths[s_number_of_extensions++] = (guint16)length;
291     }
292
293     /* May need to skip padding after last extension part */
294     isOdd = (s_number_of_extensions % 2);
295     if (isOdd) {
296         guint8 padding;
297         proto_item *ti;
298
299         padding = tvb_get_guint8(tvb, offset) & 0x0f;
300         ti = proto_tree_add_item(tree, hf_rlc_lte_extension_padding,
301                                  tvb, offset, 1, FALSE);
302         if (padding != 0) {
303             expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
304                       "Extension Header padding not zero (found 0x%x)", padding);
305         }
306         offset++;
307     }
308
309     return offset;
310 }
311
312
313 /* Show in the info column how many bytes are in the UM/AM PDU, and indicate
314    whether or not the beginning and end are included in this packet */
315 static void show_PDU_in_info(packet_info *pinfo,
316                              proto_item *top_ti,
317                              guint16 length,
318                              gboolean first_includes_start,
319                              gboolean last_includes_end)
320 {
321     /* Reflect this PDU in the info column */
322     col_append_fstr(pinfo->cinfo, COL_INFO, "  %s%u-byte%s%s",
323                     (first_includes_start) ? "[" : "..",
324                     length,
325                     (length > 1) ? "s" : "",
326                     (last_includes_end) ? "]" : "..");
327
328     proto_item_append_text(top_ti, "  %s%u-byte%s%s",
329                           (first_includes_start) ? "[" : "..",
330                           length,
331                           (length > 1) ? "s" : "",
332                           (last_includes_end) ? "]" : "..");
333 }
334
335
336
337 /*********************************************************************/
338 /* UM/AM sequence analysis                                           */
339
340 /* Types for RLC channel hash table                                   */
341 /* This table is maintained during initial dissection of RLC          */
342 /* frames, mapping from rlc_channel_hash_key -> rlc_channel_status    */
343
344 /* Channel key */
345 typedef struct
346 {
347     guint16  ueId;
348     guint16  channelType;
349     guint16  channelId;
350     guint8   direction;
351 } rlc_channel_hash_key;
352
353 /* Conversation-type status for channel */
354 typedef struct
355 {
356     guint16  previousSequenceNumber;
357     guint32  previousFrameNum;
358     gboolean previousSegmentIncomplete;
359 } rlc_channel_status;
360
361
362 /* Hash table functions for RLC channels */
363
364 /* Equal keys */
365 static gint rlc_channel_equal(gconstpointer v, gconstpointer v2)
366 {
367     const rlc_channel_hash_key* val1 = v;
368     const rlc_channel_hash_key* val2 = v2;
369
370     /* All fields must match */
371     return ((val1->ueId        == val2->ueId) &&
372             (val1->channelType == val2->channelType) &&
373             (val1->channelId   == val2->channelId) &&
374             (val1->direction   == val2->direction));
375 }
376
377 /* Compute a hash value for a given key. */
378 static guint rlc_channel_hash_func(gconstpointer v)
379 {
380     const rlc_channel_hash_key* val1 = v;
381
382     /* TODO: check/reduce multipliers */
383     return ((val1->ueId * 1024) + (val1->channelType*64) + (val1->channelId*2) + val1->direction);
384 }
385
386 /* The channel hash table instance itself        */
387 static GHashTable *rlc_lte_channel_hash = NULL;
388
389
390
391
392 /* Types for frame report hash table                                    */
393 /* This is a table from framenum -> state_report_in_frame               */
394 /* This is necessary because the per-packet info is already being used  */
395 /* for conext information before the dissector is called                */
396
397 /* Info to attach to frame when first read, recording what to show about sequence */
398 typedef struct
399 {
400     guint8  sequenceExpectedCorrect;
401     guint16 sequenceExpected;
402     guint32 previousFrameNum;
403     guint8  previousSegmentIncomplete;
404 } state_report_in_frame;
405
406
407 /* Hash table functions for frame reports */
408
409 /* Equal keys */
410 static gint rlc_frame_equal(gconstpointer v, gconstpointer v2)
411 {
412     return (v == v2);
413 }
414
415 /* Compute a hash value for a given key. */
416 static guint rlc_frame_hash_func(gconstpointer v)
417 {
418     return GPOINTER_TO_UINT(v);
419 }
420
421 /* The frame report hash table instance itself   */
422 static GHashTable *rlc_lte_frame_report_hash = NULL;
423
424
425
426 /* Add to the tree values associated with sequence analysis for this frame */
427 static void addChannelSequenceInfo(state_report_in_frame *p,
428                                    guint16 sequenceNumber,
429                                    gboolean  newSegmentStarted,
430                                    packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb)
431 {
432     proto_tree *seqnum_tree;
433     proto_item *seqnum_ti;
434     proto_item *ti;
435
436     /* Create subtree */
437     seqnum_ti = proto_tree_add_string_format(tree,
438                                              hf_rlc_lte_sequence_analysis,
439                                              tvb, 0, 0,
440                                              "",
441                                              "Sequence Analysis");
442     seqnum_tree = proto_item_add_subtree(seqnum_ti,
443                                          ett_rlc_lte_sequence_analysis);
444     PROTO_ITEM_SET_GENERATED(seqnum_ti);
445
446     /* Previous channel frame */
447     if (p->previousFrameNum != 0) {
448         proto_tree_add_uint(seqnum_tree, hf_rlc_lte_sequence_analysis_previous_frame,
449                             tvb, 0, 0, p->previousFrameNum);
450     }
451
452     /* Expected sequence number */
453     ti = proto_tree_add_uint(seqnum_tree, hf_rlc_lte_sequence_analysis_expected_sn,
454                             tvb, 0, 0, p->sequenceExpected);
455     PROTO_ITEM_SET_GENERATED(ti);
456     if (!p->sequenceExpectedCorrect) {
457         /* Incorrect sequence number */
458         expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
459                                "Wrong Sequence Number - got %u, expected %u",
460                                sequenceNumber, p->sequenceExpected);
461     }
462     else {
463         /* Correct sequence number, so check frame indication bits consistent */
464         if (p->previousSegmentIncomplete) {
465             /* Previous segment was incomplete, so this PDU should continue it */
466             if (newSegmentStarted) {
467                 ti = proto_tree_add_uint(seqnum_tree, hf_rlc_lte_sequence_analysis_framing_info_correct,
468                                          tvb, 0, 0, FALSE);
469                 if (!p->sequenceExpectedCorrect) {
470                     expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
471                                            "Last segment of previous PDU was not continued");
472                 }
473             }
474             else {
475                ti = proto_tree_add_uint(seqnum_tree, hf_rlc_lte_sequence_analysis_framing_info_correct,
476                                          tvb, 0, 0, TRUE);
477             }
478         }
479         else {
480             /* Previous segment was complete, so this PDU should start a new one */
481             if (!newSegmentStarted) {
482                 ti = proto_tree_add_uint(seqnum_tree, hf_rlc_lte_sequence_analysis_framing_info_correct,
483                                          tvb, 0, 0, FALSE);
484                 if (!p->sequenceExpectedCorrect) {
485                     expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
486                                            "Last segment of previous PDU was complete, but new segmeng was not started");
487                 }
488             }
489             else {
490                ti = proto_tree_add_uint(seqnum_tree, hf_rlc_lte_sequence_analysis_framing_info_correct,
491                                          tvb, 0, 0, TRUE);
492             }
493
494         }
495         PROTO_ITEM_SET_GENERATED(ti);
496     }
497 }
498
499 /* Update the channel status and set report for this frame */
500 static void checkChannelSequenceInfo(packet_info *pinfo, tvbuff_t *tvb,
501                                      rlc_lte_info *p_rlc_lte_info,
502                                      guint16 sequenceNumber,
503                                      gboolean first_includes_start, gboolean last_includes_end,
504                                      proto_tree *tree)
505 {
506     rlc_channel_hash_key   channel_key;
507     rlc_channel_hash_key   *p_channel_key;
508     rlc_channel_status     *p_channel_status;
509     state_report_in_frame  *p_report_in_frame = NULL;
510     guint8                 createdChannel = FALSE;
511     guint16                expectedSequenceNumber;
512
513     /* If find stat_report_in_frame already, use that and get out */
514     if (pinfo->fd->flags.visited) {
515         p_report_in_frame = (state_report_in_frame*)g_hash_table_lookup(rlc_lte_frame_report_hash,
516                                                                         &pinfo->fd->num);
517         if (p_report_in_frame != NULL) {
518             addChannelSequenceInfo(p_report_in_frame, sequenceNumber, first_includes_start,
519                                    pinfo, tree, tvb);
520             return;
521         }
522         else {
523             /* Give up - we must have tried already... */
524             return;
525         }
526     }
527
528
529     /**************************************************/
530     /* Create or find an entry for this channel state */
531     channel_key.ueId = p_rlc_lte_info->ueid;
532     channel_key.channelType = p_rlc_lte_info->channelType;
533     channel_key.channelId = p_rlc_lte_info->channelId;
534     channel_key.direction = p_rlc_lte_info->direction;
535
536     /* Do the table lookup */
537     p_channel_status = (rlc_channel_status*)g_hash_table_lookup(rlc_lte_channel_hash, &channel_key);
538
539     /* Create table entry if necessary */
540     if (p_channel_status == NULL) {
541         createdChannel = TRUE;
542
543         /* Allocate a new key and value */
544         p_channel_key = se_alloc(sizeof(rlc_channel_hash_key));
545         p_channel_status = se_alloc0(sizeof(rlc_channel_status));
546
547         /* Just give up if allocations failed */
548         if (!p_channel_key || !p_channel_status) {
549             return;
550         }
551
552         /* Copy key contents */
553         memcpy(p_channel_key, &channel_key, sizeof(rlc_channel_hash_key));
554
555         /* Add entry */
556         g_hash_table_insert(rlc_lte_channel_hash, p_channel_key, p_channel_status);
557     }
558
559     /* Create space for frame state_report */
560     p_report_in_frame = se_alloc(sizeof(state_report_in_frame));
561
562     /* Set expected sequence number.
563        Wrap according to number of bits in SN */
564     if (!createdChannel) {
565         guint16 snLimit = 4096;  /* AM default */
566         if (p_rlc_lte_info->rlcMode == RLC_UM_MODE) {
567             if (p_rlc_lte_info->UMSequenceNumberLength == 5) {
568                 snLimit = 32;
569             }
570             else {
571                 snLimit = 1024;
572             }
573         }
574         expectedSequenceNumber = (p_channel_status->previousSequenceNumber + 1) % snLimit;
575     }
576     else {
577         expectedSequenceNumber = 0;
578     }
579
580     /* Set report info regarding sequence number */
581     if (sequenceNumber == expectedSequenceNumber) {
582         p_report_in_frame->sequenceExpectedCorrect = TRUE;
583     }
584     else {
585         p_report_in_frame->sequenceExpectedCorrect = FALSE;
586     }
587     p_report_in_frame->sequenceExpected = expectedSequenceNumber;
588     p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
589     p_report_in_frame->previousSegmentIncomplete = p_channel_status->previousSegmentIncomplete;
590
591     /* Associate with this frame number */
592     g_hash_table_insert(rlc_lte_frame_report_hash, &pinfo->fd->num, p_report_in_frame);
593
594     /* Update channel status to remember *this* frame */
595     p_channel_status->previousFrameNum = pinfo->fd->num;
596     p_channel_status->previousSequenceNumber = sequenceNumber;
597     p_channel_status->previousSegmentIncomplete = !last_includes_end;
598
599     /* Add state report for this frame into tree */
600     addChannelSequenceInfo(p_report_in_frame, sequenceNumber, first_includes_start,
601                            pinfo, tree, tvb);
602 }
603
604
605
606
607
608 /***************************************************/
609 /* Unacknowledged mode PDU                         */
610 static void dissect_rlc_lte_um(tvbuff_t *tvb, packet_info *pinfo,
611                                proto_tree *tree,
612                                int offset,
613                                rlc_lte_info *p_rlc_lte_info,
614                                proto_item *top_ti)
615 {
616     guint64 framing_info;
617     gboolean first_includes_start;
618     gboolean last_includes_end;
619     guint64 fixed_extension;
620     guint64 sn;
621     gint    start_offset = offset;
622     proto_tree *um_header_tree;
623     proto_item *um_header_ti;
624
625     /* Add UM header subtree */
626     um_header_ti = proto_tree_add_string_format(tree,
627                                                 hf_rlc_lte_um_header,
628                                                 tvb, offset, 0,
629                                                 "",
630                                                 "UM header");
631     um_header_tree = proto_item_add_subtree(um_header_ti,
632                                             ett_rlc_lte_um_header);
633
634
635     /*******************************/
636     /* Fixed UM header             */
637     if (p_rlc_lte_info->UMSequenceNumberLength == UM_SN_LENGTH_5_BITS) {
638         /* Framing info (2 bits) */
639         proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_fi,
640                                     tvb, offset*8, 2,
641                                     &framing_info, FALSE);
642
643         /* Extension (1 bit) */
644         proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_fixed_e, tvb,
645                                     (offset*8) + 2, 1,
646                                     &fixed_extension, FALSE);
647
648         /* Sequence Number (5 bit) */
649         proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_sn, tvb,
650                                     (offset*8) + 3, 5,
651                                     &sn, FALSE);
652         offset++;
653     }
654     else if (p_rlc_lte_info->UMSequenceNumberLength == UM_SN_LENGTH_10_BITS) {
655         guint8 reserved;
656         proto_item *ti;
657
658         /* Check 3 Reserved bits */
659         reserved = (tvb_get_guint8(tvb, offset) & 0xe0) >> 5;
660         ti = proto_tree_add_item(um_header_tree, hf_rlc_lte_um_fixed_reserved, tvb, offset, 1, FALSE);
661         if (reserved != 0) {
662             expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
663                       "RLC UM Fixed header Reserved bits not zero (found 0x%x)", reserved);
664         }
665
666         /* Framing info (2 bits) */
667         proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_fi,
668                                     tvb, (offset*8)+3, 2,
669                                     &framing_info, FALSE);
670
671         /* Extension (1 bit) */
672         proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_fixed_e, tvb,
673                                     (offset*8) + 5, 1,
674                                     &fixed_extension, FALSE);
675
676         /* Sequence Number (10 bits) */
677         proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_sn, tvb,
678                                     (offset*8) + 6, 10,
679                                     &sn, FALSE);
680         offset += 2;
681     }
682     else {
683         /* Invalid length of sequence number */
684         proto_item *ti;
685         ti = proto_tree_add_text(um_header_tree, tvb, 0, 0, "Invalid sequence number length (%u bits)",
686                                  p_rlc_lte_info->UMSequenceNumberLength);
687         expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
688                                "Invalid sequence number length (%u bits)",
689                                p_rlc_lte_info->UMSequenceNumberLength);
690         return;
691     }
692
693     /* Show SN in info column */
694     col_append_fstr(pinfo->cinfo, COL_INFO, "  SN=%04u", (guint16)sn);
695
696     /* Show SN in UM header root */
697     proto_item_append_text(um_header_ti, " (SN=%u)", (guint16)sn);
698     proto_item_set_len(um_header_ti, offset-start_offset);
699
700
701     /*************************************/
702     /* UM header extension               */
703     if (fixed_extension) {
704         offset = dissect_rlc_lte_extension_header(tvb, pinfo, tree, offset);
705     }
706
707
708     /* Extract these 2 flags from framing_info */
709     first_includes_start = ((guint8)framing_info & 0x02) == 0;
710     last_includes_end =    ((guint8)framing_info & 0x01) == 0;
711
712
713     /* Call sequence analysis function now */
714     if (global_rlc_lte_sequence_analysis) {
715         checkChannelSequenceInfo(pinfo, tvb, p_rlc_lte_info,
716                                 (guint16)sn, first_includes_start, last_includes_end,
717                                 um_header_tree);
718     }
719
720
721     /*************************************/
722     /* Data                              */
723     if (s_number_of_extensions > 0) {
724         /* Show each data segment separately */
725         int n;
726         for (n=0; n < s_number_of_extensions; n++) {
727             proto_tree_add_item(tree, hf_rlc_lte_um_data, tvb, offset, s_lengths[n], FALSE);
728             show_PDU_in_info(pinfo, top_ti, s_lengths[n],
729                              (n==0) ? first_includes_start : TRUE,
730                              TRUE);
731             tvb_ensure_bytes_exist(tvb, offset, s_lengths[n]);
732             offset += s_lengths[n];
733         }
734     }
735
736     /* Final data element */
737     proto_tree_add_item(tree, hf_rlc_lte_um_data, tvb, offset, -1, FALSE);
738     show_PDU_in_info(pinfo, top_ti, (guint16)tvb_length_remaining(tvb, offset),
739                      (s_number_of_extensions == 0) ? first_includes_start : TRUE,
740                      last_includes_end);
741 }
742
743
744
745
746 /* Dissect an AM STATUS PDU */
747 static void dissect_rlc_lte_am_status_pdu(tvbuff_t *tvb,
748                                           packet_info *pinfo,
749                                           proto_tree *tree,
750                                           proto_item *status_ti,
751                                           int offset,
752                                           proto_item *top_ti)
753 {
754     guint8     cpt;
755     guint64    ack_sn, nack_sn;
756     guint64    e1 = 0, e2 = 0;
757     guint64    so_start, so_end;
758     int        bit_offset = offset * 8;
759     proto_item *ti;
760
761     /****************************************************************/
762     /* Part of RLC control PDU header                               */
763
764     /* Control PDU Type (CPT) */
765     cpt = (tvb_get_guint8(tvb, offset) & 0xf0) >> 4;
766     ti = proto_tree_add_item(tree, hf_rlc_lte_am_cpt, tvb, offset, 1, FALSE);
767     if (cpt != 0) {
768         /* Protest and stop - only know about STATUS PDUs */
769         expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
770                                "RLC Control frame type %u not handled", cpt);
771         return;
772     }
773
774
775     /*****************************************************************/
776     /* STATUS PDU                                                    */
777
778     /* The PDU itself starts 4 bits into the byte */
779     bit_offset += 4;
780
781     /* ACK SN */
782     proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_ack_sn, tvb,
783                                 bit_offset, 10, &ack_sn, FALSE);
784     bit_offset += 10;
785     col_append_fstr(pinfo->cinfo, COL_INFO, "  ACK_SN=%u", (guint16)ack_sn);
786     proto_item_append_text(top_ti, "  ACK_SN=%u", (guint16)ack_sn);
787
788     /* E1 */
789     proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_e1, tvb,
790                                 bit_offset, 1, &e1, FALSE);
791
792     /* Skip another bit to byte-align the next bit... */
793     bit_offset++;
794
795     /* Optional, extra fields */
796     do {
797         if (e1) {
798             proto_item *nack_ti;
799
800             /****************************/
801             /* Read NACK_SN, E1, E2     */
802
803             /* NACK_SN */
804             nack_ti = proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_nack_sn, tvb,
805                                                   bit_offset, 10, &nack_sn, FALSE);
806             bit_offset += 10;
807             col_append_fstr(pinfo->cinfo, COL_INFO, "  NACK_SN=%u", (guint16)nack_sn);
808             proto_item_append_text(top_ti, "  NACK_SN=%u", (guint16)nack_sn);
809             expert_add_info_format(pinfo, nack_ti, PI_SEQUENCE, PI_WARN,
810                                    "Status PDU reports NACK for SN=%u", (guint16)nack_sn);
811
812
813             /* E1 */
814             proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_e1, tvb,
815                                         bit_offset, 1, &e1, FALSE);
816             bit_offset++;
817
818             /* E2 */
819             proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_e2, tvb,
820                                         bit_offset, 1, &e2, FALSE);
821             bit_offset++;
822         }
823
824         if (e2) {
825             /* Read SOstart, SOend */
826             proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_so_start, tvb,
827                                         bit_offset, 15, &so_start, FALSE);
828             bit_offset += 15;
829
830             proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_so_end, tvb,
831                                         bit_offset, 15, &so_end, FALSE);
832             bit_offset += 15;
833
834
835             if ((guint16)so_end == 0x7fff) {
836                 col_append_fstr(pinfo->cinfo, COL_INFO, "  (SOstart=%u SOend=<END-OF_PDU>)",
837                                 (guint16)so_start);
838             }
839             else {
840                 col_append_fstr(pinfo->cinfo, COL_INFO, "  (SOstart=%u SOend=%u)",
841                                 (guint16)so_start, (guint16)so_end);
842             }
843
844             /* Reset this flag here */
845             e2 = 0;
846         }
847     } while (e1 || e2);
848
849     /* Check that we've reached the end of the PDU. If not, show malformed */
850     offset = (bit_offset+7) / 8;
851     if (tvb_length_remaining(tvb, offset) > 0) {
852         expert_add_info_format(pinfo, status_ti, PI_MALFORMED, PI_ERROR,
853                                "%u bytes remaining after Status PDU complete",
854                                tvb_length_remaining(tvb, offset));
855     }
856
857     /* Set selected length of control tree */
858     proto_item_set_len(status_ti, offset);
859 }
860
861
862 /***************************************************/
863 /* Acknowledged mode PDU                           */
864 static void dissect_rlc_lte_am(tvbuff_t *tvb, packet_info *pinfo,
865                                proto_tree *tree,
866                                int offset,
867                                rlc_lte_info *p_rlc_lte_info _U_,
868                                proto_item *top_ti)
869 {
870     guint8 is_data;
871     guint8 is_segment;
872     guint8 polling;
873     guint8 fixed_extension;
874     guint8 framing_info;
875     gboolean first_includes_start;
876     gboolean last_includes_end;
877     proto_tree *am_header_tree;
878     proto_item *am_header_ti;
879     gint   start_offset = offset;
880     guint16    sn;
881
882     /* Add UM header subtree */
883     am_header_ti = proto_tree_add_string_format(tree,
884                                                 hf_rlc_lte_am_header,
885                                                 tvb, offset, 0,
886                                                 "",
887                                                 "AM header");
888     am_header_tree = proto_item_add_subtree(am_header_ti,
889                                             ett_rlc_lte_am_header);
890
891
892     /*******************************************/
893     /* First bit is Data/Control flag           */
894     is_data = (tvb_get_guint8(tvb, offset) & 0x80) >> 7;
895     proto_tree_add_item(am_header_tree, hf_rlc_lte_am_data_control, tvb, offset, 1, FALSE);
896
897     /**************************************************/
898     if (!is_data) {
899         col_append_str(pinfo->cinfo, COL_INFO, " [CONTROL]");
900         proto_item_append_text(top_ti, " [CONTROL]");
901
902         /* Control PDUs are a completely separate format  */
903         dissect_rlc_lte_am_status_pdu(tvb, pinfo, am_header_tree, am_header_ti, offset, top_ti);
904         return;
905     }
906
907     /******************************/
908     /* Data PDU fixed header      */
909
910     /* Re-segmentation Flag (RF) field */
911     is_segment = (tvb_get_guint8(tvb, offset) & 0x40) >> 6;
912     proto_tree_add_item(am_header_tree, hf_rlc_lte_am_rf, tvb, offset, 1, FALSE);
913
914     col_append_str(pinfo->cinfo, COL_INFO, (is_segment) ? " [DATA-SEGMENT]" : " [DATA]");
915     proto_item_append_text(top_ti, (is_segment) ? " [DATA-SEGMENT]" : " [DATA]");
916
917
918     /* Polling bit */
919     polling = (tvb_get_guint8(tvb, offset) & 0x20) >> 5;
920     proto_tree_add_item(am_header_tree, hf_rlc_lte_am_p, tvb, offset, 1, FALSE);
921     col_append_str(pinfo->cinfo, COL_INFO, (polling) ? " (P) " : "     ");
922     proto_item_append_text(top_ti,  (polling) ? " (P) " : "     ");
923     if (polling) {
924         proto_item_append_text(am_header_ti, " (P)");
925     }
926
927     /* Framing Info */
928     framing_info = (tvb_get_guint8(tvb, offset) & 0x18) >> 3;
929     proto_tree_add_item(am_header_tree, hf_rlc_lte_am_fi, tvb, offset, 1, FALSE);
930
931     /* Extension bit */
932     fixed_extension = (tvb_get_guint8(tvb, offset) & 0x04) >> 2;
933     proto_tree_add_item(am_header_tree, hf_rlc_lte_am_fixed_e, tvb, offset, 1, FALSE);
934
935     /* Sequence Number */
936     sn = tvb_get_ntohs(tvb, offset) & 0x03ff;
937     proto_tree_add_item(am_header_tree, hf_rlc_lte_am_fixed_sn, tvb, offset, 2, FALSE);
938     offset += 2;
939
940     col_append_fstr(pinfo->cinfo, COL_INFO, "sn=%u", sn);
941     proto_item_append_text(top_ti, " (SN=%u)", sn);
942
943     /* Show SN in AM header root */
944     proto_item_append_text(am_header_ti, " (SN=%u)", sn);
945     proto_item_set_len(am_header_ti, offset-start_offset);
946
947     /***************************************/
948     /* Dissect extra segment header fields */
949     if (is_segment) {
950         guint16 segmentOffset;
951
952         /* Last Segment Field (LSF) */
953         proto_tree_add_item(am_header_tree, hf_rlc_lte_am_segment_lsf, tvb, offset, 1, FALSE);
954
955         /* SO */
956         segmentOffset = tvb_get_ntohs(tvb, offset) & 0x7fff;
957         proto_tree_add_item(am_header_tree, hf_rlc_lte_am_segment_so, tvb, offset, 2, FALSE);
958         col_append_fstr(pinfo->cinfo, COL_INFO, " SO=%u ", segmentOffset);
959         proto_item_append_text(top_ti, " SO=%u ", segmentOffset);
960
961         offset += 2;
962     }
963
964     /*************************************/
965     /* AM header extension               */
966     if (fixed_extension) {
967         offset = dissect_rlc_lte_extension_header(tvb, pinfo, tree, offset);
968     }
969
970
971     /* Extract these 2 flags from framing_info */
972     first_includes_start = (framing_info & 0x02) == 0;
973     last_includes_end =    (framing_info & 0x01) == 0;
974
975
976     /* Call sequence analysis function now (pretty limited for AM) */
977 #if 0
978     if (global_rlc_lte_sequence_analysis) {
979         checkChannelSequenceInfo(pinfo, tvb, p_rlc_lte_info, (guint16)sn,
980                                  first_includes_start, last_includes_end,
981                                  am_header_tree);
982     }
983 #endif
984
985
986     /*************************************/
987     /* Data                        */
988     if (s_number_of_extensions > 0) {
989         /* Show each data segment separately */
990         int n;
991         for (n=0; n < s_number_of_extensions; n++) {
992             proto_tree_add_item(tree, hf_rlc_lte_am_data, tvb, offset, s_lengths[n], FALSE);
993             show_PDU_in_info(pinfo, top_ti, s_lengths[n],
994                              (n==0) ? first_includes_start : TRUE,
995                              TRUE);
996             tvb_ensure_bytes_exist(tvb, offset, s_lengths[n]);
997             offset += s_lengths[n];
998         }
999     }
1000
1001     /* Final data element */
1002     if (tvb_length_remaining(tvb, offset) > 0) {
1003         proto_tree_add_item(tree, hf_rlc_lte_am_data, tvb, offset, -1, FALSE);
1004         show_PDU_in_info(pinfo, top_ti, (guint16)tvb_length_remaining(tvb, offset),
1005                          (s_number_of_extensions == 0) ? first_includes_start : TRUE,
1006                          last_includes_end);
1007     }
1008     else {
1009         expert_add_info_format(pinfo, am_header_ti, PI_MALFORMED, PI_WARN,
1010                                "AM data PDU doesn't contain any data");
1011
1012     }
1013 }
1014
1015
1016
1017 /*****************************/
1018 /* Main dissection function. */
1019 /*****************************/
1020
1021 void dissect_rlc_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1022 {
1023     proto_tree             *rlc_lte_tree;
1024     proto_item             *top_ti;
1025     proto_item             *ti;
1026     proto_item             *mode_ti;
1027     gint                   offset = 0;
1028     struct rlc_lte_info    *p_rlc_lte_info = NULL;
1029
1030     /* Set protocol name */
1031     col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC-LTE");
1032
1033     /* Create protocol tree. */
1034     top_ti = proto_tree_add_item(tree, proto_rlc_lte, tvb, offset, -1, FALSE);
1035     rlc_lte_tree = proto_item_add_subtree(top_ti, ett_rlc_lte);
1036
1037
1038     /* Look for packet info! */
1039     p_rlc_lte_info = p_get_proto_data(pinfo->fd, proto_rlc_lte);
1040
1041     /* Can't dissect anything without it... */
1042     if (p_rlc_lte_info == NULL) {
1043         proto_item *ti =
1044             proto_tree_add_text(rlc_lte_tree, tvb, offset, -1,
1045                                 "Can't dissect LTE RLC frame because no per-frame info was attached!");
1046         PROTO_ITEM_SET_GENERATED(ti);
1047         return;
1048     }
1049
1050     /*****************************************/
1051     /* Show context information              */
1052     /* TODO: hide inside own tree?           */
1053
1054     ti = proto_tree_add_uint(rlc_lte_tree, hf_rlc_lte_context_direction,
1055                              tvb, 0, 0, p_rlc_lte_info->direction);
1056     PROTO_ITEM_SET_GENERATED(ti);
1057
1058     mode_ti = proto_tree_add_uint(rlc_lte_tree, hf_rlc_lte_context_mode,
1059                                   tvb, 0, 0, p_rlc_lte_info->rlcMode);
1060     PROTO_ITEM_SET_GENERATED(mode_ti);
1061
1062     if (p_rlc_lte_info->ueid != 0) {
1063         ti = proto_tree_add_uint(rlc_lte_tree, hf_rlc_lte_context_ueid,
1064                                  tvb, 0, 0, p_rlc_lte_info->ueid);
1065         PROTO_ITEM_SET_GENERATED(ti);
1066     }
1067
1068     ti = proto_tree_add_uint(rlc_lte_tree, hf_rlc_lte_context_priority,
1069                              tvb, 0, 0, p_rlc_lte_info->priority);
1070     PROTO_ITEM_SET_GENERATED(ti);
1071
1072     ti = proto_tree_add_uint(rlc_lte_tree, hf_rlc_lte_context_channel_type,
1073                              tvb, 0, 0, p_rlc_lte_info->channelType);
1074     PROTO_ITEM_SET_GENERATED(ti);
1075
1076     if ((p_rlc_lte_info->channelType == CHANNEL_TYPE_SRB) ||
1077         (p_rlc_lte_info->channelType == CHANNEL_TYPE_DRB)) {
1078         ti = proto_tree_add_uint(rlc_lte_tree, hf_rlc_lte_context_channel_id,
1079                                  tvb, 0, 0, p_rlc_lte_info->channelId);
1080         PROTO_ITEM_SET_GENERATED(ti);
1081     }
1082
1083     ti = proto_tree_add_uint(rlc_lte_tree, hf_rlc_lte_context_pdu_length,
1084                              tvb, 0, 0, p_rlc_lte_info->pduLength);
1085     PROTO_ITEM_SET_GENERATED(ti);
1086
1087     if (p_rlc_lte_info->rlcMode == RLC_UM_MODE) {
1088         ti = proto_tree_add_uint(rlc_lte_tree, hf_rlc_lte_context_um_sn_length,
1089                                  tvb, 0, 0, p_rlc_lte_info->UMSequenceNumberLength);
1090         PROTO_ITEM_SET_GENERATED(ti);
1091     }
1092
1093     /* Append highlights to top-level item */
1094     if (p_rlc_lte_info->ueid != 0) {
1095         proto_item_append_text(top_ti, "   UEId=%u", p_rlc_lte_info->ueid);
1096     }
1097
1098     if (p_rlc_lte_info->channelId == 0) {
1099         proto_item_append_text(top_ti, " (%s) ",
1100                                val_to_str(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"));
1101     }
1102     else {
1103         proto_item_append_text(top_ti, " (%s:%u) ",
1104                                val_to_str(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
1105                                p_rlc_lte_info->channelId);
1106     }
1107     proto_item_append_text(top_ti, "[%s] ",
1108                            val_to_str(p_rlc_lte_info->rlcMode, rlc_mode_short_vals, "Unknown"));
1109
1110
1111     /* Append context highlights to info column */
1112     col_add_fstr(pinfo->cinfo, COL_INFO,
1113                  "[%s] [%s] ",
1114                  (p_rlc_lte_info->direction == 0) ? "UL" : "DL",
1115                  val_to_str(p_rlc_lte_info->rlcMode, rlc_mode_short_vals, "Unknown"));
1116     if (p_rlc_lte_info->ueid != 0) {
1117         col_append_fstr(pinfo->cinfo, COL_INFO, "UEId=%u ", p_rlc_lte_info->ueid);
1118     }
1119     if (p_rlc_lte_info->channelId == 0) {
1120         col_append_fstr(pinfo->cinfo, COL_INFO, "%s",
1121                         val_to_str(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"));
1122     }
1123     else {
1124         col_append_fstr(pinfo->cinfo, COL_INFO, "%s:%u",
1125                         val_to_str(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
1126                         p_rlc_lte_info->channelId);
1127     }
1128
1129     /* Reset this count */
1130     s_number_of_extensions = 0;
1131
1132     /* Dissect the RLC PDU itself. Format depends upon mode... */
1133     switch (p_rlc_lte_info->rlcMode) {
1134
1135         case RLC_TM_MODE:
1136             /* Remaining bytes are all data */
1137             proto_tree_add_item(rlc_lte_tree, hf_rlc_lte_tm_data, tvb, offset, -1, FALSE);
1138             col_append_fstr(pinfo->cinfo, COL_INFO, "   [%u-bytes]",
1139                             tvb_length_remaining(tvb, offset));
1140             break;
1141
1142         case RLC_UM_MODE:
1143             dissect_rlc_lte_um(tvb, pinfo, rlc_lte_tree, offset, p_rlc_lte_info, top_ti);
1144             break;
1145
1146         case RLC_AM_MODE:
1147             dissect_rlc_lte_am(tvb, pinfo, rlc_lte_tree, offset, p_rlc_lte_info, top_ti);
1148             break;
1149
1150         case RLC_PREDEF:
1151             /* Predefined data (i.e. not containing a valid RLC header */
1152             proto_tree_add_item(rlc_lte_tree, hf_rlc_lte_predefined_pdu, tvb, offset, -1, FALSE);
1153             col_append_fstr(pinfo->cinfo, COL_INFO, "   [%u-bytes]",
1154                             tvb_length_remaining(tvb, offset));
1155             break;
1156
1157         default:
1158             /* Error - unrecognised mode */
1159             expert_add_info_format(pinfo, mode_ti, PI_MALFORMED, PI_ERROR,
1160                                    "Unrecognised RLC Mode set (%u)", p_rlc_lte_info->rlcMode);
1161             break;
1162     }
1163 }
1164
1165
1166
1167 /* Initializes the hash table and the mem_chunk area each time a new
1168  * file is loaded or re-loaded in wireshark */
1169 static void
1170 rlc_lte_init_protocol(void)
1171 {
1172     /* Destroy any existing hashes. */
1173     if (rlc_lte_channel_hash) {
1174         g_hash_table_destroy(rlc_lte_channel_hash);
1175     }
1176
1177     if (rlc_lte_frame_report_hash) {
1178         g_hash_table_destroy(rlc_lte_frame_report_hash);
1179     }
1180
1181     /* Now create them over */
1182     rlc_lte_channel_hash = g_hash_table_new(rlc_channel_hash_func, rlc_channel_equal);
1183     rlc_lte_frame_report_hash = g_hash_table_new(rlc_frame_hash_func, rlc_frame_equal);
1184 }
1185
1186
1187
1188
1189 void proto_register_rlc_lte(void)
1190 {
1191     static hf_register_info hf[] =
1192     {
1193         /**********************************/
1194         /* Items for decoding context     */
1195         { &hf_rlc_lte_context_mode,
1196             { "RLC Mode",
1197               "rlc-lte.mode", FT_UINT8, BASE_DEC, VALS(rlc_mode_vals), 0x0,
1198               NULL, HFILL
1199             }
1200         },
1201         { &hf_rlc_lte_context_direction,
1202             { "Direction",
1203               "rlc-lte.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
1204               "Direction of message", HFILL
1205             }
1206         },
1207         { &hf_rlc_lte_context_priority,
1208             { "Priority",
1209               "rlc-lte.priority", FT_UINT8, BASE_DEC, 0, 0x0,
1210               NULL, HFILL
1211             }
1212         },
1213         { &hf_rlc_lte_context_ueid,
1214             { "UEId",
1215               "rlc-lte.ueid", FT_UINT16, BASE_DEC, 0, 0x0,
1216               "User Equipment Identifier associated with message", HFILL
1217             }
1218         },
1219         { &hf_rlc_lte_context_channel_type,
1220             { "Channel Type",
1221               "rlc-lte.channel-type", FT_UINT16, BASE_DEC, VALS(rlc_channel_type_vals), 0x0,
1222               "Channel Type associated with message", HFILL
1223             }
1224         },
1225         { &hf_rlc_lte_context_channel_id,
1226             { "Channel ID",
1227               "rlc-lte.channel-id", FT_UINT16, BASE_DEC, 0, 0x0,
1228               "Channel ID associated with message", HFILL
1229             }
1230         },
1231         { &hf_rlc_lte_context_pdu_length,
1232             { "PDU Length",
1233               "rlc-lte.pdu_length", FT_UINT16, BASE_DEC, 0, 0x0,
1234               "Length of PDU (in bytes)", HFILL
1235             }
1236         },
1237         { &hf_rlc_lte_context_um_sn_length,
1238             { "UM Sequence number length",
1239               "rlc-lte.um-seqnum-length", FT_UINT8, BASE_DEC, 0, 0x0,
1240               "Length of UM sequence number in bits", HFILL
1241             }
1242         },
1243
1244
1245         /* Transparent mode fields */
1246         { &hf_rlc_lte_tm_data,
1247             { "TM Data",
1248               "rlc-lte.tm.data", FT_BYTES, BASE_NONE, 0, 0x0,
1249               "Transparent Mode Data", HFILL
1250             }
1251         },
1252
1253         /* Unacknowledged mode fields */
1254         { &hf_rlc_lte_um_header,
1255             { "UM Header",
1256               "rlc-lte.um.header", FT_STRING, BASE_NONE, NULL, 0x0,
1257               "Unackowledged Mode Header", HFILL
1258             }
1259         },
1260         { &hf_rlc_lte_um_fi,
1261             { "Framing Info",
1262               "rlc-lte.um.fi", FT_UINT8, BASE_HEX, VALS(framing_info_vals), 0x0,
1263               NULL, HFILL
1264             }
1265         },
1266         { &hf_rlc_lte_um_fixed_e,
1267             { "Extension",
1268               "rlc-lte.um.fixed.e", FT_UINT8, BASE_HEX, VALS(fixed_extension_vals), 0x0,
1269               "Extension in fixed part of UM header", HFILL
1270             }
1271         },
1272         { &hf_rlc_lte_um_sn,
1273             { "Sequence number",
1274               "rlc-lte.um.sn", FT_UINT8, BASE_DEC, 0, 0x0,
1275               "Unacknowledged Mode Sequence Number", HFILL
1276             }
1277         },
1278         { &hf_rlc_lte_um_fixed_reserved,
1279             { "Reserved",
1280               "rlc-lte.um.reserved", FT_UINT8, BASE_DEC, 0, 0xe0,
1281               "Unacknowledged Mode Fixed header reserved bits", HFILL
1282             }
1283         },
1284         { &hf_rlc_lte_um_data,
1285             { "UM Data",
1286               "rlc-lte.um.data", FT_BYTES, BASE_NONE, 0, 0x0,
1287               "Unacknowledged Mode Data", HFILL
1288             }
1289         },
1290         { &hf_rlc_lte_extension_part,
1291             { "Extension Part",
1292               "rlc-lte.extension-part", FT_STRING, BASE_NONE, 0, 0x0,
1293               NULL, HFILL
1294             }
1295         },
1296
1297
1298         { &hf_rlc_lte_extension_e,
1299             { "Extension",
1300               "rlc-lte.extension.e", FT_UINT8, BASE_HEX, VALS(extension_extension_vals), 0x0,
1301               "Extension in extended part of the header", HFILL
1302             }
1303         },
1304         { &hf_rlc_lte_extension_li,
1305             { "Length Indicator",
1306               "rlc-lte.extension.li", FT_UINT16, BASE_DEC, 0, 0x0,
1307               NULL, HFILL
1308             }
1309         },
1310         { &hf_rlc_lte_extension_padding,
1311             { "Padding",
1312               "rlc-lte.extension.padding", FT_UINT8, BASE_HEX, 0, 0x0f,
1313               "Extension header padding", HFILL
1314             }
1315         },
1316
1317
1318         { &hf_rlc_lte_am_header,
1319             { "UM Header",
1320               "rlc-lte.am.header", FT_STRING, BASE_NONE, NULL, 0x0,
1321               "Ackowledged Mode Header", HFILL
1322             }
1323         },
1324         { &hf_rlc_lte_am_data_control,
1325             { "Frame type",
1326               "rlc-lte.am.frame_type", FT_UINT8, BASE_HEX, VALS(data_or_control_vals), 0x80,
1327               "AM Frame Type (Control or Data)", HFILL
1328             }
1329         },
1330         { &hf_rlc_lte_am_rf,
1331             { "Re-segmentation Flag",
1332               "rlc-lte.am.rf", FT_UINT8, BASE_HEX, VALS(resegmentation_flag_vals), 0x40,
1333               "AM Re-segmentation Flag", HFILL
1334             }
1335         },
1336         { &hf_rlc_lte_am_p,
1337             { "Polling Bit",
1338               "rlc-lte.am.p", FT_UINT8, BASE_HEX, VALS(polling_bit_vals), 0x20,
1339               NULL, HFILL
1340             }
1341         },
1342         { &hf_rlc_lte_am_fi,
1343             { "Framing Info",
1344               "rlc-lte.am.fi", FT_UINT8, BASE_HEX, VALS(framing_info_vals), 0x18,
1345               "AM Framing Info", HFILL
1346             }
1347         },
1348         { &hf_rlc_lte_am_fixed_e,
1349             { "Extension",
1350               "rlc-lte.am.fixed.e", FT_UINT8, BASE_HEX, VALS(fixed_extension_vals), 0x04,
1351               "Fixed Extension Bit", HFILL
1352             }
1353         },
1354         { &hf_rlc_lte_am_fixed_sn,
1355             { "Sequence Number",
1356               "rlc-lte.am.fixed.sn", FT_UINT16, BASE_HEX, 0, 0x03ff,
1357               "AM Fixed Sequence Number", HFILL
1358             }
1359         },
1360         { &hf_rlc_lte_am_segment_lsf,
1361             { "Last Segment Flag",
1362               "rlc-lte.am.segment.lsf", FT_UINT8, BASE_HEX, VALS(lsf_vals), 0x80,
1363               NULL, HFILL
1364             }
1365         },
1366         { &hf_rlc_lte_am_segment_so,
1367             { "Segment Offset",
1368               "rlc-lte.am.segment.offset", FT_UINT16, BASE_DEC, 0, 0x7fff,
1369               NULL, HFILL
1370             }
1371         },
1372         { &hf_rlc_lte_am_data,
1373             { "AM Data",
1374               "rlc-lte.am.data", FT_BYTES, BASE_NONE, 0, 0x0,
1375               "Acknowledged Mode Data", HFILL
1376             }
1377         },
1378
1379
1380         { &hf_rlc_lte_am_cpt,
1381             { "Control PDU Type",
1382               "rlc-lte.am.cpt", FT_UINT8, BASE_HEX, VALS(control_pdu_type_vals), 0x70,
1383               "AM Control PDU Type", HFILL
1384             }
1385         },
1386         { &hf_rlc_lte_am_ack_sn,
1387             { "ACK Sequence Number",
1388               "rlc-lte.am.ack-sn", FT_UINT16, BASE_DEC, 0, 0x0,
1389               "Sequence Number we're next expecting to receive", HFILL
1390             }
1391         },
1392         { &hf_rlc_lte_am_e1,
1393             { "Extension bit 1",
1394               "rlc-lte.am.e1", FT_UINT8, BASE_HEX, VALS(am_e1_vals), 0x0,
1395               NULL, HFILL
1396             }
1397         },
1398         { &hf_rlc_lte_am_e2,
1399             { "Extension bit 2",
1400               "rlc-lte.am.e2", FT_UINT8, BASE_HEX, VALS(am_e2_vals), 0x0,
1401               NULL, HFILL
1402             }
1403         },
1404         { &hf_rlc_lte_am_nack_sn,
1405             { "NACK Sequence Number",
1406               "rlc-lte.am.nack-sn", FT_UINT16, BASE_DEC, 0, 0x0,
1407               "Negative Acknowledgement Sequence Number", HFILL
1408             }
1409         },
1410         { &hf_rlc_lte_am_so_start,
1411             { "SO Start",
1412               "rlc-lte.am.so-start", FT_UINT16, BASE_DEC, 0, 0x0,
1413               NULL, HFILL
1414             }
1415         },
1416         { &hf_rlc_lte_am_so_end,
1417             { "SO End",
1418               "rlc-lte.am.so-end", FT_UINT16, BASE_DEC, 0, 0x0,
1419               NULL, HFILL
1420             }
1421         },
1422
1423         { &hf_rlc_lte_predefined_pdu,
1424             { "Predefined data",
1425               "rlc-lte.predefined-data", FT_BYTES, BASE_NONE, 0, 0x0,
1426               "Predefined test data", HFILL
1427             }
1428         },
1429
1430         { &hf_rlc_lte_sequence_analysis,
1431             { "Sequence Analysis",
1432               "rlc-lte.sequence-analysis", FT_STRING, BASE_NONE, 0, 0x0,
1433               NULL, HFILL
1434             }
1435         },
1436         { &hf_rlc_lte_sequence_analysis_previous_frame,
1437             { "Previous frame for channel",
1438               "rlc-lte.sequence-analysis.previous-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
1439               NULL, HFILL
1440             }
1441         },
1442         { &hf_rlc_lte_sequence_analysis_expected_sn,
1443             { "Expected SN",
1444               "rlc-lte.sequence-analysis.expected-sn", FT_UINT16, BASE_DEC, 0, 0x0,
1445               NULL, HFILL
1446             }
1447         },
1448         { &hf_rlc_lte_sequence_analysis_framing_info_correct,
1449             { "Frame info continued correctly",
1450               "rlc-lte.sequence-analysis.framing-info-correct", FT_UINT8, BASE_DEC, 0, 0x0,
1451               NULL, HFILL
1452             }
1453         },
1454     };
1455
1456     static gint *ett[] =
1457     {
1458         &ett_rlc_lte,
1459         &ett_rlc_lte_um_header,
1460         &ett_rlc_lte_am_header,
1461         &ett_rlc_lte_extension_part,
1462         &ett_rlc_lte_sequence_analysis
1463     };
1464
1465     module_t *rlc_lte_module;
1466
1467     /* Register protocol. */
1468     proto_rlc_lte = proto_register_protocol("RLC-LTE", "RLC-LTE", "rlc-lte");
1469     proto_register_field_array(proto_rlc_lte, hf, array_length(hf));
1470     proto_register_subtree_array(ett, array_length(ett));
1471
1472     /* Allow other dissectors to find this one by name. */
1473     register_dissector("rlc-lte", dissect_rlc_lte, proto_rlc_lte);
1474
1475     /* Preferences */
1476     rlc_lte_module = prefs_register_protocol(proto_rlc_lte, NULL);
1477
1478     prefs_register_bool_preference(rlc_lte_module, "do_sequence_analysis",
1479         "Do sequence analysis for UM channels",
1480         "Attempt to keep track of PDUs for UM channels, and point out problems",
1481         &global_rlc_lte_sequence_analysis);
1482
1483     register_init_routine(&rlc_lte_init_protocol);
1484 }
1485
1486