b38d842829117c4e1cc929426be78f0986781115
[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/AM 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                              guint16 length,
317                              gboolean first_includes_start,
318                              gboolean last_includes_end)
319 {
320     /* Reflect this PDU in the info column */
321     if (check_col(pinfo->cinfo, COL_INFO)) {
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 }
329
330
331
332 /*********************************************************************/
333 /* UM/AM sequence analysis                                           */
334
335 /* Types for RLC channel hash table                                   */
336 /* This table is maintained during initial dissection of RLC          */
337 /* frames, mapping from rlc_channel_hash_key -> rlc_channel_status    */
338
339 /* Channel key */
340 typedef struct
341 {
342     guint16 ueId;
343     guint16  channelType;
344     guint16  channelId;
345     guint8  direction;
346 } rlc_channel_hash_key;
347
348 /* Conversation-type status for channel */
349 typedef struct
350 {
351     guint16  previousSequenceNumber;
352     guint32  previousFrameNum;
353     gboolean previousSegmentIncomplete;
354 } rlc_channel_status;
355
356
357 /* Hash table functions for RLC channels */
358
359 /* Equal keys */
360 static gint rlc_channel_equal(gconstpointer v, gconstpointer v2)
361 {
362     const rlc_channel_hash_key* val1 = v;
363     const rlc_channel_hash_key* val2 = v2;
364
365     /* All fields must match */
366     return ((val1->ueId        == val2->ueId) &&
367             (val1->channelType == val2->channelType) &&
368             (val1->channelId   == val2->channelId) &&
369             (val1->direction   == val2->direction));
370 }
371
372 /* Compute a hash value for a given key. */
373 static guint rlc_channel_hash_func(gconstpointer v)
374 {
375     const rlc_channel_hash_key* val1 = v;
376
377     /* TODO: check/reduce multipliers */
378     return ((val1->ueId * 1024) + (val1->channelType*64) + (val1->channelId*2) + val1->direction);
379 }
380
381 /* The channel hash table instance itself        */
382 static GHashTable *rlc_lte_channel_hash = NULL;
383
384
385
386
387 /* Types for frame report hash table                                    */
388 /* This is a table from framenum -> state_report_in_frame               */
389 /* This is necessary because the per-packet info is already being used  */
390 /* for conext information before the dissector is called                */
391
392 /* Info to attach to frame when first read, recording what to show about sequence */
393 typedef struct
394 {
395     guint8  sequenceExpectedCorrect;
396     guint16 sequenceExpected;
397     guint32 previousFrameNum;
398     guint8  previousSegmentIncomplete;
399 } state_report_in_frame;
400
401
402 /* Hash table functions for frame reports */
403
404 /* Equal keys */
405 static gint rlc_frame_equal(gconstpointer v, gconstpointer v2)
406 {
407     return (v == v2);
408 }
409
410 /* Compute a hash value for a given key. */
411 static guint rlc_frame_hash_func(gconstpointer v)
412 {
413     return GPOINTER_TO_UINT(v);
414 }
415
416 /* The frame report hash table instance itself   */
417 static GHashTable *rlc_lte_frame_report_hash = NULL;
418
419
420
421 /* Add to the tree values associated with sequence analysis for this frame */
422 static void addChannelSequenceInfo(state_report_in_frame *p,
423                                    guint16 sequenceNumber,
424                                    gboolean  newSegmentStarted,
425                                    packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb)
426 {
427     proto_tree *seqnum_tree;
428     proto_item *seqnum_ti;
429     proto_item *ti;
430
431     /* Create subtree */
432     seqnum_ti = proto_tree_add_string_format(tree,
433                                              hf_rlc_lte_sequence_analysis,
434                                              tvb, 0, 0,
435                                              "",
436                                              "Sequence Analysis");
437     seqnum_tree = proto_item_add_subtree(seqnum_ti,
438                                          ett_rlc_lte_sequence_analysis);
439     PROTO_ITEM_SET_GENERATED(seqnum_ti);
440
441     /* Previous channel frame */
442     if (p->previousFrameNum != 0) {
443         proto_tree_add_uint(seqnum_tree, hf_rlc_lte_sequence_analysis_previous_frame,
444                             tvb, 0, 0, p->previousFrameNum);
445     }
446
447     /* Expected sequence number */
448     ti = proto_tree_add_uint(seqnum_tree, hf_rlc_lte_sequence_analysis_expected_sn,
449                             tvb, 0, 0, p->sequenceExpected);
450     PROTO_ITEM_SET_GENERATED(ti);
451     if (!p->sequenceExpectedCorrect) {
452         /* Incorrect sequence number */
453         expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
454                                "Wrong Sequence Number - got %u, expected %u",
455                                sequenceNumber, p->sequenceExpected);
456     }
457     else {
458         /* Correct sequence number, so check frame indication bits consistent */
459         if (p->previousSegmentIncomplete) {
460             /* Previous segment was incomplete, so this PDU should continue it */
461             if (newSegmentStarted) {
462                 ti = proto_tree_add_uint(seqnum_tree, hf_rlc_lte_sequence_analysis_framing_info_correct,
463                                          tvb, 0, 0, FALSE);
464                 if (!p->sequenceExpectedCorrect) {
465                     expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
466                                            "Last segment of previous PDU was not continued");
467                 }
468             }
469             else {
470                ti = proto_tree_add_uint(seqnum_tree, hf_rlc_lte_sequence_analysis_framing_info_correct,
471                                          tvb, 0, 0, TRUE);
472             }
473         }
474         else {
475             /* Previous segment was complete, so this PDU should start a new one */
476             if (!newSegmentStarted) {
477                 ti = proto_tree_add_uint(seqnum_tree, hf_rlc_lte_sequence_analysis_framing_info_correct,
478                                          tvb, 0, 0, FALSE);
479                 if (!p->sequenceExpectedCorrect) {
480                     expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
481                                            "Last segment of previous PDU was complete, but new segmeng was not started");
482                 }
483             }
484             else {
485                ti = proto_tree_add_uint(seqnum_tree, hf_rlc_lte_sequence_analysis_framing_info_correct,
486                                          tvb, 0, 0, TRUE);
487             }
488
489         }
490         PROTO_ITEM_SET_GENERATED(ti);
491     }
492 }
493
494 /* Update the channel status and set report for this frame */
495 static void checkChannelSequenceInfo(packet_info *pinfo, tvbuff_t *tvb,
496                                      rlc_lte_info *p_rlc_lte_info,
497                                      guint16 sequenceNumber,
498                                      gboolean first_includes_start, gboolean last_includes_end,
499                                      proto_tree *tree)
500 {
501     rlc_channel_hash_key   channel_key;
502     rlc_channel_hash_key   *p_channel_key;
503     rlc_channel_status     *p_channel_status;
504     state_report_in_frame  *p_report_in_frame = NULL;
505     guint8                 createdChannel = FALSE;
506     guint16                expectedSequenceNumber;
507
508     /* If find stat_report_in_frame already, use that and get out */
509     if (pinfo->fd->flags.visited) {
510         p_report_in_frame = (state_report_in_frame*)g_hash_table_lookup(rlc_lte_frame_report_hash,
511                                                                         &pinfo->fd->num);
512         if (p_report_in_frame != NULL) {
513             addChannelSequenceInfo(p_report_in_frame, sequenceNumber, first_includes_start,
514                                    pinfo, tree, tvb);
515             return;
516         }
517         else {
518             /* Give up - we must have tried already... */
519             return;
520         }
521     }
522
523
524     /**************************************************/
525     /* Create or find an entry for this channel state */
526     channel_key.ueId = p_rlc_lte_info->ueid;
527     channel_key.channelType = p_rlc_lte_info->channelType;
528     channel_key.channelId = p_rlc_lte_info->channelId;
529     channel_key.direction = p_rlc_lte_info->direction;
530
531     /* Do the table lookup */
532     p_channel_status = (rlc_channel_status*)g_hash_table_lookup(rlc_lte_channel_hash, &channel_key);
533
534     /* Create table entry if necessary */
535     if (p_channel_status == NULL) {
536         createdChannel = TRUE;
537
538         /* Allocate a new key and value */
539         p_channel_key = se_alloc(sizeof(rlc_channel_hash_key));
540         p_channel_status = se_alloc0(sizeof(rlc_channel_status));
541
542         /* Just give up if allocations failed */
543         if (!p_channel_key || !p_channel_status) {
544             return;
545         }
546
547         /* Copy key contents */
548         memcpy(p_channel_key, &channel_key, sizeof(rlc_channel_hash_key));
549
550         /* Add entry */
551         g_hash_table_insert(rlc_lte_channel_hash, p_channel_key, p_channel_status);
552     }
553
554     /* Create space for frame state_report */
555     p_report_in_frame = se_alloc(sizeof(state_report_in_frame));
556
557     /* Set expected sequence number.
558        Wrap according to number of bits in SN */
559     if (!createdChannel) {
560         guint16 snLimit = 4096;  /* AM default */
561         if (p_rlc_lte_info->rlcMode == RLC_UM_MODE) {
562             if (p_rlc_lte_info->UMSequenceNumberLength == 5) {
563                 snLimit = 32;
564             }
565             else {
566                 snLimit = 1024;
567             }
568         }
569         expectedSequenceNumber = (p_channel_status->previousSequenceNumber + 1) % snLimit;
570     }
571     else {
572         expectedSequenceNumber = 0;
573     }
574
575     /* Set report info regarding sequence number */
576     if (sequenceNumber == expectedSequenceNumber) {
577         p_report_in_frame->sequenceExpectedCorrect = TRUE;
578     }
579     else {
580         p_report_in_frame->sequenceExpectedCorrect = FALSE;
581     }
582     p_report_in_frame->sequenceExpected = expectedSequenceNumber;
583     p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
584     p_report_in_frame->previousSegmentIncomplete = p_channel_status->previousSegmentIncomplete;
585
586     /* Associate with this frame number */
587     g_hash_table_insert(rlc_lte_frame_report_hash, &pinfo->fd->num, p_report_in_frame);
588
589     /* Update channel status to remember *this* frame */
590     p_channel_status->previousFrameNum = pinfo->fd->num;
591     p_channel_status->previousSequenceNumber = sequenceNumber;
592     p_channel_status->previousSegmentIncomplete = !last_includes_end;
593
594     /* Add state report for this frame into tree */
595     addChannelSequenceInfo(p_report_in_frame, sequenceNumber, first_includes_start,
596                            pinfo, tree, tvb);
597 }
598
599
600
601
602
603 /***************************************************/
604 /* Unacknowledged mode PDU                         */
605 static void dissect_rlc_lte_um(tvbuff_t *tvb, packet_info *pinfo,
606                                proto_tree *tree,
607                                int offset,
608                                rlc_lte_info *p_rlc_lte_info)
609 {
610     guint64 framing_info;
611     gboolean first_includes_start;
612     gboolean last_includes_end;
613     guint64 fixed_extension;
614     guint64 sn;
615     gint    start_offset = offset;
616     proto_tree *um_header_tree;
617     proto_item *um_header_ti;
618
619     /* Add UM header subtree */
620     um_header_ti = proto_tree_add_string_format(tree,
621                                                 hf_rlc_lte_um_header,
622                                                 tvb, offset, 0,
623                                                 "",
624                                                 "UM header");
625     um_header_tree = proto_item_add_subtree(um_header_ti,
626                                             ett_rlc_lte_um_header);
627
628
629     /*******************************/
630     /* Fixed UM header             */
631     if (p_rlc_lte_info->UMSequenceNumberLength == UM_SN_LENGTH_5_BITS) {
632         /* Framing info (2 bits) */
633         proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_fi,
634                                     tvb, offset*8, 2,
635                                     &framing_info, FALSE);
636
637         /* Extension (1 bit) */
638         proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_fixed_e, tvb,
639                                     (offset*8) + 2, 1,
640                                     &fixed_extension, FALSE);
641
642         /* Sequence Number (5 bit) */
643         proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_sn, tvb,
644                                     (offset*8) + 3, 5,
645                                     &sn, FALSE);
646         offset++;
647     }
648     else if (p_rlc_lte_info->UMSequenceNumberLength == UM_SN_LENGTH_10_BITS) {
649         guint8 reserved;
650         proto_item *ti;
651
652         /* Check 3 Reserved bits */
653         reserved = (tvb_get_guint8(tvb, offset) & 0xe0) >> 5;
654         ti = proto_tree_add_item(um_header_tree, hf_rlc_lte_um_fixed_reserved, tvb, offset, 1, FALSE);
655         if (reserved != 0) {
656             expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
657                       "RLC UM Fixed header Reserved bits not zero (found 0x%x)", reserved);
658         }
659
660         /* Framing info (2 bits) */
661         proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_fi,
662                                     tvb, (offset*8)+3, 2,
663                                     &framing_info, FALSE);
664
665         /* Extension (1 bit) */
666         proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_fixed_e, tvb,
667                                     (offset*8) + 5, 1,
668                                     &fixed_extension, FALSE);
669
670         /* Sequence Number (10 bits) */
671         proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_sn, tvb,
672                                     (offset*8) + 6, 10,
673                                     &sn, FALSE);
674         offset += 2;
675     }
676     else {
677         /* Invalid length of sequence number */
678         proto_item *ti;
679         ti = proto_tree_add_text(um_header_tree, tvb, 0, 0, "Invalid sequence number length (%u bits)",
680                                  p_rlc_lte_info->UMSequenceNumberLength);
681         expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
682                                "Invalid sequence number length (%u bits)",
683                                p_rlc_lte_info->UMSequenceNumberLength);
684         return;
685     }
686
687     /* Show SN in info column */
688     if (check_col(pinfo->cinfo, COL_INFO)) {
689         col_append_fstr(pinfo->cinfo, COL_INFO, "  SN=%04u",
690                         (guint16)sn);
691     }
692
693     /* Show SN in UM header root */
694     proto_item_append_text(um_header_ti, " (SN=%u)", (guint16)sn);
695     proto_item_set_len(um_header_ti, offset-start_offset);
696
697
698     /*************************************/
699     /* UM header extension               */
700     if (fixed_extension) {
701         offset = dissect_rlc_lte_extension_header(tvb, pinfo, tree, offset);
702     }
703
704
705     /* Extract these 2 flags from framing_info */
706     first_includes_start = ((guint8)framing_info & 0x02) == 0;
707     last_includes_end =    ((guint8)framing_info & 0x01) == 0;
708
709
710     /* Call sequence analysis function now */
711     if (global_rlc_lte_sequence_analysis) {
712         checkChannelSequenceInfo(pinfo, tvb, p_rlc_lte_info,
713                                 (guint16)sn, first_includes_start, last_includes_end,
714                                 um_header_tree);
715     }
716
717
718     /*************************************/
719     /* Data                              */
720     if (s_number_of_extensions > 0) {
721         /* Show each data segment separately */
722         int n;
723         for (n=0; n < s_number_of_extensions; n++) {
724             proto_tree_add_item(tree, hf_rlc_lte_um_data, tvb, offset, s_lengths[n], FALSE);
725             show_PDU_in_info(pinfo, s_lengths[n],
726                              (n==0) ? first_includes_start : TRUE,
727                              TRUE);
728             tvb_ensure_bytes_exist(tvb, offset, s_lengths[n]);
729             offset += s_lengths[n];
730         }
731     }
732
733     /* Final data element */
734     proto_tree_add_item(tree, hf_rlc_lte_um_data, tvb, offset, -1, FALSE);
735     show_PDU_in_info(pinfo, (guint16)tvb_length_remaining(tvb, offset),
736                      (s_number_of_extensions == 0) ? first_includes_start : TRUE,
737                      last_includes_end);
738 }
739
740
741
742
743 /* Dissect an AM STATUS PDU */
744 static void dissect_rlc_lte_am_status_pdu(tvbuff_t *tvb,
745                                           packet_info *pinfo,
746                                           proto_tree *tree,
747                                           int offset)
748 {
749     guint8     cpt;
750     guint64    ack_sn, nack_sn;
751     guint64    e1 = 0, e2 = 0;
752     guint64    so_start, so_end;
753     int        bit_offset = offset * 8;
754     proto_item *ti;
755
756     /****************************************************************/
757     /* Part of RLC control PDU header                               */
758
759     /* Control PDU Type (CPT) */
760     cpt = (tvb_get_guint8(tvb, offset) & 0xf0) >> 4;
761     ti = proto_tree_add_item(tree, hf_rlc_lte_am_cpt, tvb, offset, 1, FALSE);
762     if (cpt != 0) {
763         /* Protest and stop - only know about STATUS PDUs */
764         expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
765                                "RLC Control frame type %u not handled", cpt);
766         return;
767     }
768
769
770     /*****************************************************************/
771     /* STATUS PDU                                                    */
772
773     /* The PDU itself starts 4 bits into the byte */
774     bit_offset += 4;
775
776     /* ACK SN */
777     proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_ack_sn, tvb,
778                                 bit_offset, 10, &ack_sn, FALSE);
779     bit_offset += 10;
780     if (check_col(pinfo->cinfo, COL_INFO)) {
781         col_append_fstr(pinfo->cinfo, COL_INFO, "  ACK_SN=%u", (guint16)ack_sn);
782     }
783
784
785     /* E1 */
786     proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_e1, tvb,
787                                 bit_offset, 1, &e1, FALSE);
788
789     /* Skip another bit to byte-align the next bit... */
790     bit_offset++;
791
792     /* Optional, extra fields */
793     do {
794         if (e1) {
795             proto_item *nack_ti;
796
797             /****************************/
798             /* Read NACK_SN, E1, E2     */
799
800             /* NACK_SN */
801             nack_ti = proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_nack_sn, tvb,
802                                                   bit_offset, 10, &nack_sn, FALSE);
803             bit_offset += 10;
804             if (check_col(pinfo->cinfo, COL_INFO)) {
805                 col_append_fstr(pinfo->cinfo, COL_INFO, "  NACK_SN=%u", (guint16)nack_sn);
806             }
807             expert_add_info_format(pinfo, nack_ti, PI_SEQUENCE, PI_WARN,
808                                    "Status PDU reports NACK for SN=%u", (guint16)nack_sn);
809
810
811             /* E1 */
812             proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_e1, tvb,
813                                         bit_offset, 1, &e1, FALSE);
814             bit_offset++;
815
816             /* E2 */
817             proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_e2, tvb,
818                                         bit_offset, 1, &e2, FALSE);
819             bit_offset++;
820         }
821
822         if (e2) {
823             /* Read SOstart, SOend */
824             proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_so_start, tvb,
825                                         bit_offset, 15, &so_start, FALSE);
826             bit_offset += 15;
827
828             proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_so_end, tvb,
829                                         bit_offset, 15, &so_end, FALSE);
830             bit_offset += 15;
831
832             if (check_col(pinfo->cinfo, COL_INFO)) {
833                 col_append_fstr(pinfo->cinfo, COL_INFO, "  (SOstart=%u SOend=%u)",
834                                 (guint16)so_start, (guint16)so_end);
835
836                 if ((guint16)so_end == 0x7fff) {
837                     col_append_str(pinfo->cinfo, COL_INFO, " (missing portion reaches end of AMD PDU)");
838                 }
839             }
840
841             /* Reset this flag here */
842             e2 = 0;
843         }
844     } while (e1 || e2);
845
846 }
847
848
849 /***************************************************/
850 /* Acknowledged mode PDU                           */
851 static void dissect_rlc_lte_am(tvbuff_t *tvb, packet_info *pinfo,
852                                proto_tree *tree,
853                                int offset,
854                                rlc_lte_info *p_rlc_lte_info _U_)
855 {
856     guint8 is_data;
857     guint8 is_segment;
858     guint8 polling;
859     guint8 fixed_extension;
860     guint8 framing_info;
861     gboolean first_includes_start;
862     gboolean last_includes_end;
863     proto_tree *am_header_tree;
864     proto_item *am_header_ti;
865     gint   start_offset = offset;
866     guint16    sn;
867
868     /* Add UM header subtree */
869     am_header_ti = proto_tree_add_string_format(tree,
870                                                 hf_rlc_lte_am_header,
871                                                 tvb, offset, 0,
872                                                 "",
873                                                 "AM header");
874     am_header_tree = proto_item_add_subtree(am_header_ti,
875                                             ett_rlc_lte_am_header);
876
877
878     /*******************************************/
879     /* First bit is Data/Control flag           */
880     is_data = (tvb_get_guint8(tvb, offset) & 0x80) >> 7;
881     proto_tree_add_item(am_header_tree, hf_rlc_lte_am_data_control, tvb, offset, 1, FALSE);
882     if (check_col(pinfo->cinfo, COL_INFO)) {
883         col_append_str(pinfo->cinfo, COL_INFO, (is_data) ? " [DATA]" : " [CONTROL]");
884     }
885
886
887     /**************************************************/
888     /* Control PDUs are a completely separate format  */
889     if (!is_data) {
890         dissect_rlc_lte_am_status_pdu(tvb, pinfo, am_header_tree, offset);
891         return;
892     }
893
894
895     /******************************/
896     /* Data PDU fixed header      */
897
898     /* Re-segmentation Flag (RF) field */
899     is_segment = (tvb_get_guint8(tvb, offset) & 0x40) >> 6;
900     proto_tree_add_item(am_header_tree, hf_rlc_lte_am_rf, tvb, offset, 1, FALSE);
901
902     /* Polling bit */
903     polling = (tvb_get_guint8(tvb, offset) & 0x20) >> 5;
904     proto_tree_add_item(am_header_tree, hf_rlc_lte_am_p, tvb, offset, 1, FALSE);
905     if (check_col(pinfo->cinfo, COL_INFO)) {
906         col_append_str(pinfo->cinfo, COL_INFO, (polling) ? " (P) " : "     ");
907     }
908     if (polling) {
909         proto_item_append_text(am_header_ti, " (P)");
910     }
911
912     /* Framing Info */
913     framing_info = (tvb_get_guint8(tvb, offset) & 0x18) >> 3;
914     proto_tree_add_item(am_header_tree, hf_rlc_lte_am_fi, tvb, offset, 1, FALSE);
915
916     /* Extension bit */
917     fixed_extension = (tvb_get_guint8(tvb, offset) & 0x04) >> 2;
918     proto_tree_add_item(am_header_tree, hf_rlc_lte_am_fixed_e, tvb, offset, 1, FALSE);
919
920     /* Sequence Number */
921     sn = tvb_get_ntohs(tvb, offset) & 0x03ff;
922     proto_tree_add_item(am_header_tree, hf_rlc_lte_am_fixed_sn, tvb, offset, 2, FALSE);
923     offset += 2;
924
925     if (check_col(pinfo->cinfo, COL_INFO)) {
926         col_append_fstr(pinfo->cinfo, COL_INFO, "sn=%u", sn);
927     }
928
929
930     /* Show SN in AM header root */
931     proto_item_append_text(am_header_ti, " (SN=%u)", sn);
932     proto_item_set_len(am_header_ti, offset-start_offset);
933
934     /***************************************/
935     /* Dissect extra segment header fields */
936     if (is_segment) {
937         /* Last Segment Field (LSF) */
938         proto_tree_add_item(am_header_tree, hf_rlc_lte_am_segment_lsf, tvb, offset, 1, FALSE);
939
940         /* SO */
941         proto_tree_add_item(am_header_tree, hf_rlc_lte_am_segment_so, tvb, offset, 2, FALSE);
942
943         offset += 2;
944     }
945
946     /*************************************/
947     /* AM header extension               */
948     if (fixed_extension) {
949         offset = dissect_rlc_lte_extension_header(tvb, pinfo, tree, offset);
950     }
951
952
953     /* Extract these 2 flags from framing_info */
954     first_includes_start = (framing_info & 0x02) == 0;
955     last_includes_end =    (framing_info & 0x01) == 0;
956
957
958     /* Call sequence analysis function now (pretty limited for AM) */
959 #if 0
960     if (global_rlc_lte_sequence_analysis) {
961         checkChannelSequenceInfo(pinfo, tvb, p_rlc_lte_info, (guint16)sn,
962                                  first_includes_start, last_includes_end,
963                                  am_header_tree);
964     }
965 #endif
966
967
968     /*************************************/
969     /* Data                        */
970     if (s_number_of_extensions > 0) {
971         /* Show each data segment separately */
972         int n;
973         for (n=0; n < s_number_of_extensions; n++) {
974             proto_tree_add_item(tree, hf_rlc_lte_am_data, tvb, offset, s_lengths[n], FALSE);
975             show_PDU_in_info(pinfo, s_lengths[n],
976                              (n==0) ? first_includes_start : TRUE,
977                              TRUE);
978             tvb_ensure_bytes_exist(tvb, offset, s_lengths[n]);
979             offset += s_lengths[n];
980         }
981     }
982
983     /* Final data element */
984     proto_tree_add_item(tree, hf_rlc_lte_am_data, tvb, offset, -1, FALSE);
985     show_PDU_in_info(pinfo, (guint16)tvb_length_remaining(tvb, offset),
986                      (s_number_of_extensions == 0) ? first_includes_start : TRUE,
987                      last_includes_end);
988 }
989
990
991
992 /*****************************/
993 /* Main dissection function. */
994 /*****************************/
995
996 void dissect_rlc_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
997 {
998     proto_tree             *rlc_lte_tree;
999     proto_item             *ti;
1000     proto_item             *mode_ti;
1001     gint                   offset = 0;
1002     struct rlc_lte_info    *p_rlc_lte_info = NULL;
1003
1004     /* Set protocol name */
1005     if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
1006         col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC-LTE");
1007     }
1008
1009     /* Create protocol tree. */
1010     ti = proto_tree_add_item(tree, proto_rlc_lte, tvb, offset, -1, FALSE);
1011     rlc_lte_tree = proto_item_add_subtree(ti, ett_rlc_lte);
1012
1013
1014     /* Look for packet info! */
1015     p_rlc_lte_info = p_get_proto_data(pinfo->fd, proto_rlc_lte);
1016
1017     /* Can't dissect anything without it... */
1018     if (p_rlc_lte_info == NULL) {
1019         proto_item *ti =
1020             proto_tree_add_text(rlc_lte_tree, tvb, offset, -1,
1021                                 "Can't dissect LTE RLC frame because no per-frame info was attached!");
1022         PROTO_ITEM_SET_GENERATED(ti);
1023         return;
1024     }
1025
1026     /*****************************************/
1027     /* Show context information              */
1028     /* TODO: hide inside own tree?           */
1029
1030     ti = proto_tree_add_uint(rlc_lte_tree, hf_rlc_lte_context_direction,
1031                              tvb, 0, 0, p_rlc_lte_info->direction);
1032     PROTO_ITEM_SET_GENERATED(ti);
1033
1034     mode_ti = proto_tree_add_uint(rlc_lte_tree, hf_rlc_lte_context_mode,
1035                                   tvb, 0, 0, p_rlc_lte_info->rlcMode);
1036     PROTO_ITEM_SET_GENERATED(mode_ti);
1037
1038     if (p_rlc_lte_info->ueid != 0) {
1039         ti = proto_tree_add_uint(rlc_lte_tree, hf_rlc_lte_context_ueid,
1040                                  tvb, 0, 0, p_rlc_lte_info->ueid);
1041         PROTO_ITEM_SET_GENERATED(ti);
1042     }
1043
1044     ti = proto_tree_add_uint(rlc_lte_tree, hf_rlc_lte_context_priority,
1045                              tvb, 0, 0, p_rlc_lte_info->priority);
1046     PROTO_ITEM_SET_GENERATED(ti);
1047
1048     ti = proto_tree_add_uint(rlc_lte_tree, hf_rlc_lte_context_channel_type,
1049                              tvb, 0, 0, p_rlc_lte_info->channelType);
1050     PROTO_ITEM_SET_GENERATED(ti);
1051
1052     if ((p_rlc_lte_info->channelType == CHANNEL_TYPE_SRB) ||
1053         (p_rlc_lte_info->channelType == CHANNEL_TYPE_DRB)) {
1054         ti = proto_tree_add_uint(rlc_lte_tree, hf_rlc_lte_context_channel_id,
1055                                  tvb, 0, 0, p_rlc_lte_info->channelId);
1056         PROTO_ITEM_SET_GENERATED(ti);
1057     }
1058
1059     ti = proto_tree_add_uint(rlc_lte_tree, hf_rlc_lte_context_pdu_length,
1060                              tvb, 0, 0, p_rlc_lte_info->pduLength);
1061     PROTO_ITEM_SET_GENERATED(ti);
1062
1063     if (p_rlc_lte_info->rlcMode == RLC_UM_MODE) {
1064         ti = proto_tree_add_uint(rlc_lte_tree, hf_rlc_lte_context_um_sn_length,
1065                                  tvb, 0, 0, p_rlc_lte_info->UMSequenceNumberLength);
1066         PROTO_ITEM_SET_GENERATED(ti);
1067     }
1068
1069
1070     /* Append context highlights to info column */
1071     if (check_col(pinfo->cinfo, COL_INFO)) {
1072         col_add_fstr(pinfo->cinfo, COL_INFO,
1073                      "[%s] [%s] ",
1074                      (p_rlc_lte_info->direction == 0) ? "UL" : "DL",
1075                      val_to_str(p_rlc_lte_info->rlcMode, rlc_mode_short_vals, "Unknown"));
1076         if (p_rlc_lte_info->ueid != 0) {
1077             col_append_fstr(pinfo->cinfo, COL_INFO, "UEId=%u ", p_rlc_lte_info->ueid);
1078         }
1079         if (p_rlc_lte_info->channelId == 0) {
1080             col_append_fstr(pinfo->cinfo, COL_INFO, "%s",
1081                             val_to_str(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"));
1082         }
1083         else {
1084             col_append_fstr(pinfo->cinfo, COL_INFO, "%s:%u",
1085                             val_to_str(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
1086                             p_rlc_lte_info->channelId);
1087         }
1088     }
1089
1090     /* Reset this count */
1091     s_number_of_extensions = 0;
1092
1093     /* Dissect the RLC PDU itself. Format depends upon mode... */
1094     switch (p_rlc_lte_info->rlcMode) {
1095
1096         case RLC_TM_MODE:
1097             /* Remaining bytes are all data */
1098             proto_tree_add_item(rlc_lte_tree, hf_rlc_lte_tm_data, tvb, offset, -1, FALSE);
1099             if (check_col(pinfo->cinfo, COL_INFO)) {
1100                 col_append_fstr(pinfo->cinfo, COL_INFO, "   [%u-bytes]",
1101                                tvb_length_remaining(tvb, offset));
1102             }
1103             break;
1104
1105         case RLC_UM_MODE:
1106             dissect_rlc_lte_um(tvb, pinfo, rlc_lte_tree, offset, p_rlc_lte_info);
1107             break;
1108
1109         case RLC_AM_MODE:
1110             dissect_rlc_lte_am(tvb, pinfo, rlc_lte_tree, offset, p_rlc_lte_info);
1111             break;
1112
1113         case RLC_PREDEF:
1114             /* Predefined data (i.e. not containing a valid RLC header */
1115             proto_tree_add_item(rlc_lte_tree, hf_rlc_lte_predefined_pdu, tvb, offset, -1, FALSE);
1116             break;
1117
1118         default:
1119             /* Error - unrecognised mode */
1120             expert_add_info_format(pinfo, mode_ti, PI_MALFORMED, PI_ERROR,
1121                                    "Unrecognised RLC Mode set (%u)", p_rlc_lte_info->rlcMode);
1122             break;
1123     }
1124 }
1125
1126
1127
1128 /* Initializes the hash table and the mem_chunk area each time a new
1129  * file is loaded or re-loaded in wireshark */
1130 static void
1131 rlc_lte_init_protocol(void)
1132 {
1133     /* Destroy any existing hashes. */
1134     if (rlc_lte_channel_hash) {
1135         g_hash_table_destroy(rlc_lte_channel_hash);
1136     }
1137
1138     if (rlc_lte_frame_report_hash) {
1139         g_hash_table_destroy(rlc_lte_frame_report_hash);
1140     }
1141
1142     /* Now create them over */
1143     rlc_lte_channel_hash = g_hash_table_new(rlc_channel_hash_func, rlc_channel_equal);
1144     rlc_lte_frame_report_hash = g_hash_table_new(rlc_frame_hash_func, rlc_frame_equal);
1145 }
1146
1147
1148
1149
1150 void proto_register_rlc_lte(void)
1151 {
1152     static hf_register_info hf[] =
1153     {
1154         /**********************************/
1155         /* Items for decoding context     */
1156         { &hf_rlc_lte_context_mode,
1157             { "RLC Mode",
1158               "rlc-lte.mode", FT_UINT8, BASE_DEC, VALS(rlc_mode_vals), 0x0,
1159               "RLC Mode", HFILL
1160             }
1161         },
1162         { &hf_rlc_lte_context_direction,
1163             { "Direction",
1164               "rlc-lte.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
1165               "Direction of message", HFILL
1166             }
1167         },
1168         { &hf_rlc_lte_context_priority,
1169             { "Priority",
1170               "rlc-lte.priority", FT_UINT8, BASE_DEC, 0, 0x0,
1171               "Priority", HFILL
1172             }
1173         },
1174         { &hf_rlc_lte_context_ueid,
1175             { "UEId",
1176               "rlc-lte.ueid", FT_UINT16, BASE_DEC, 0, 0x0,
1177               "User Equipment Identifier associated with message", HFILL
1178             }
1179         },
1180         { &hf_rlc_lte_context_channel_type,
1181             { "Channel Type",
1182               "rlc-lte.channel-type", FT_UINT16, BASE_DEC, VALS(rlc_channel_type_vals), 0x0,
1183               "Channel Type associated with message", HFILL
1184             }
1185         },
1186         { &hf_rlc_lte_context_channel_id,
1187             { "Channel ID",
1188               "rlc-lte.channel-id", FT_UINT16, BASE_DEC, 0, 0x0,
1189               "Channel ID associated with message", HFILL
1190             }
1191         },
1192         { &hf_rlc_lte_context_pdu_length,
1193             { "PDU Length",
1194               "rlc-lte.pdu_length", FT_UINT16, BASE_DEC, 0, 0x0,
1195               "Length of PDU (in bytes)", HFILL
1196             }
1197         },
1198         { &hf_rlc_lte_context_um_sn_length,
1199             { "UM Sequence number length",
1200               "rlc-lte.um-seqnum-length", FT_UINT8, BASE_DEC, 0, 0x0,
1201               "Length of UM sequence number in bits", HFILL
1202             }
1203         },
1204
1205
1206         /* Transparent mode fields */
1207         { &hf_rlc_lte_tm_data,
1208             { "TM Data",
1209               "rlc-lte.tm.data", FT_BYTES, BASE_HEX, 0, 0x0,
1210               "Transparent Mode Data", HFILL
1211             }
1212         },
1213
1214         /* Unacknowledged mode fields */
1215         { &hf_rlc_lte_um_header,
1216             { "UM Header",
1217               "rlc-lte.um.header", FT_STRING, BASE_NONE, NULL, 0x0,
1218               "Unackowledged Mode Header", HFILL
1219             }
1220         },
1221         { &hf_rlc_lte_um_fi,
1222             { "Framing Info",
1223               "rlc-lte.um.fi", FT_UINT8, BASE_HEX, VALS(framing_info_vals), 0x0,
1224               "Framing Info", HFILL
1225             }
1226         },
1227         { &hf_rlc_lte_um_fixed_e,
1228             { "Extension",
1229               "rlc-lte.um.fixed.e", FT_UINT8, BASE_HEX, VALS(fixed_extension_vals), 0x0,
1230               "Extension in fixed part of UM header", HFILL
1231             }
1232         },
1233         { &hf_rlc_lte_um_sn,
1234             { "Sequence number",
1235               "rlc-lte.um.sn", FT_UINT8, BASE_DEC, 0, 0x0,
1236               "Unacknowledged Mode Sequence Number", HFILL
1237             }
1238         },
1239         { &hf_rlc_lte_um_fixed_reserved,
1240             { "Reserved",
1241               "rlc-lte.um.reserved", FT_UINT8, BASE_DEC, 0, 0xe0,
1242               "Unacknowledged Mode Fixed header reserved bits", HFILL
1243             }
1244         },
1245         { &hf_rlc_lte_um_data,
1246             { "UM Data",
1247               "rlc-lte.um.data", FT_BYTES, BASE_HEX, 0, 0x0,
1248               "Unacknowledged Mode Data", HFILL
1249             }
1250         },
1251         { &hf_rlc_lte_extension_part,
1252             { "Extension Part",
1253               "rlc-lte.extension-part", FT_STRING, BASE_NONE, 0, 0x0,
1254               "Extension Part", HFILL
1255             }
1256         },
1257
1258
1259         { &hf_rlc_lte_extension_e,
1260             { "Extension",
1261               "rlc-lte.extension.e", FT_UINT8, BASE_HEX, VALS(extension_extension_vals), 0x0,
1262               "Extension in extended part of the header", HFILL
1263             }
1264         },
1265         { &hf_rlc_lte_extension_li,
1266             { "Length Indicator",
1267               "rlc-lte.extension.li", FT_UINT16, BASE_DEC, 0, 0x0,
1268               "Length Indicator", HFILL
1269             }
1270         },
1271         { &hf_rlc_lte_extension_padding,
1272             { "Padding",
1273               "rlc-lte.extension.padding", FT_UINT8, BASE_HEX, 0, 0x0f,
1274               "Extension header padding", HFILL
1275             }
1276         },
1277
1278
1279         { &hf_rlc_lte_am_header,
1280             { "UM Header",
1281               "rlc-lte.am.header", FT_STRING, BASE_NONE, NULL, 0x0,
1282               "Ackowledged Mode Header", HFILL
1283             }
1284         },
1285         { &hf_rlc_lte_am_data_control,
1286             { "Frame type",
1287               "rlc-lte.am.frame_type", FT_UINT8, BASE_HEX, VALS(data_or_control_vals), 0x80,
1288               "AM Frame Type (Control or Data)", HFILL
1289             }
1290         },
1291         { &hf_rlc_lte_am_rf,
1292             { "Re-segmentation Flag",
1293               "rlc-lte.am.rf", FT_UINT8, BASE_HEX, VALS(resegmentation_flag_vals), 0x40,
1294               "AM Re-segmentation Flag", HFILL
1295             }
1296         },
1297         { &hf_rlc_lte_am_p,
1298             { "Polling Bit",
1299               "rlc-lte.am.p", FT_UINT8, BASE_HEX, VALS(polling_bit_vals), 0x20,
1300               "Polling Bit", HFILL
1301             }
1302         },
1303         { &hf_rlc_lte_am_fi,
1304             { "Framing Info",
1305               "rlc-lte.am.fi", FT_UINT8, BASE_HEX, VALS(framing_info_vals), 0x18,
1306               "AM Framing Info", HFILL
1307             }
1308         },
1309         { &hf_rlc_lte_am_fixed_e,
1310             { "Extension",
1311               "rlc-lte.am.fixed.e", FT_UINT8, BASE_HEX, VALS(fixed_extension_vals), 0x04,
1312               "Fixed Extension Bit", HFILL
1313             }
1314         },
1315         { &hf_rlc_lte_am_fixed_sn,
1316             { "Sequence Number",
1317               "rlc-lte.am.fixed.sn", FT_UINT16, BASE_HEX, 0, 0x03ff,
1318               "AM Fixed Sequence Number", HFILL
1319             }
1320         },
1321         { &hf_rlc_lte_am_segment_lsf,
1322             { "Last Segment Flag",
1323               "rlc-lte.am.segment.lsf", FT_UINT8, BASE_HEX, VALS(lsf_vals), 0x80,
1324               "Last Segment Flag", HFILL
1325             }
1326         },
1327         { &hf_rlc_lte_am_segment_so,
1328             { "Segment Offset",
1329               "rlc-lte.am.segment.offset", FT_UINT16, BASE_DEC, 0, 0x7fff,
1330               "Segment Offset", HFILL
1331             }
1332         },
1333         { &hf_rlc_lte_am_data,
1334             { "AM Data",
1335               "rlc-lte.am.data", FT_BYTES, BASE_HEX, 0, 0x0,
1336               "Acknowledged Mode Data", HFILL
1337             }
1338         },
1339
1340
1341         { &hf_rlc_lte_am_cpt,
1342             { "Control PDU Type",
1343               "rlc-lte.am.cpt", FT_UINT8, BASE_HEX, VALS(control_pdu_type_vals), 0x70,
1344               "AM Control PDU Type", HFILL
1345             }
1346         },
1347         { &hf_rlc_lte_am_ack_sn,
1348             { "ACK Sequence Number",
1349               "rlc-lte.am.ack-sn", FT_UINT16, BASE_DEC, 0, 0x0,
1350               "Sequence Number we're next expecting to receive", HFILL
1351             }
1352         },
1353         { &hf_rlc_lte_am_e1,
1354             { "Extension bit 1",
1355               "rlc-lte.am.e1", FT_UINT8, BASE_HEX, VALS(am_e1_vals), 0x0,
1356               "Extension bit 1", HFILL
1357             }
1358         },
1359         { &hf_rlc_lte_am_e2,
1360             { "Extension bit 2",
1361               "rlc-lte.am.e2", FT_UINT8, BASE_HEX, VALS(am_e2_vals), 0x0,
1362               "Extension bit 2", HFILL
1363             }
1364         },
1365         { &hf_rlc_lte_am_nack_sn,
1366             { "NACK Sequence Number",
1367               "rlc-lte.am.nack-sn", FT_UINT16, BASE_DEC, 0, 0x0,
1368               "Negative Acknowledgement Sequence Number", HFILL
1369             }
1370         },
1371         { &hf_rlc_lte_am_so_start,
1372             { "SO Start",
1373               "rlc-lte.am.so-start", FT_UINT16, BASE_DEC, 0, 0x0,
1374               "SO Start", HFILL
1375             }
1376         },
1377         { &hf_rlc_lte_am_so_end,
1378             { "SO End",
1379               "rlc-lte.am.so-end", FT_UINT16, BASE_DEC, 0, 0x0,
1380               "SO End", HFILL
1381             }
1382         },
1383
1384         { &hf_rlc_lte_predefined_pdu,
1385             { "Predefined data",
1386               "rlc-lte.predefined-data", FT_BYTES, BASE_HEX, 0, 0x0,
1387               "Predefined test data", HFILL
1388             }
1389         },
1390
1391         { &hf_rlc_lte_sequence_analysis,
1392             { "Sequence Analysis",
1393               "rlc-lte.sequence-analysis", FT_STRING, BASE_NONE, 0, 0x0,
1394               "Sequence Analysis", HFILL
1395             }
1396         },
1397         { &hf_rlc_lte_sequence_analysis_previous_frame,
1398             { "Previous frame for channel",
1399               "rlc-lte.sequence-analysis.previous-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
1400               "Previous frame for channel", HFILL
1401             }
1402         },
1403         { &hf_rlc_lte_sequence_analysis_expected_sn,
1404             { "Expected SN",
1405               "rlc-lte.sequence-analysis.expected-sn", FT_UINT16, BASE_DEC, 0, 0x0,
1406               "Expected SN", HFILL
1407             }
1408         },
1409         { &hf_rlc_lte_sequence_analysis_framing_info_correct,
1410             { "Frame info continued correctly",
1411               "rlc-lte.sequence-analysis.framing-info-correct", FT_UINT8, BASE_DEC, 0, 0x0,
1412               "Frame info continued correctly", HFILL
1413             }
1414         },
1415     };
1416
1417     static gint *ett[] =
1418     {
1419         &ett_rlc_lte,
1420         &ett_rlc_lte_um_header,
1421         &ett_rlc_lte_am_header,
1422         &ett_rlc_lte_extension_part,
1423         &ett_rlc_lte_sequence_analysis
1424     };
1425
1426     module_t *rlc_lte_module;
1427
1428     /* Register protocol. */
1429     proto_rlc_lte = proto_register_protocol("RLC-LTE", "RLC-LTE", "rlc-lte");
1430     proto_register_field_array(proto_rlc_lte, hf, array_length(hf));
1431     proto_register_subtree_array(ett, array_length(ett));
1432
1433     /* Allow other dissectors to find this one by name. */
1434     register_dissector("rlc-lte", dissect_rlc_lte, proto_rlc_lte);
1435
1436     /* Preferences */
1437     rlc_lte_module = prefs_register_protocol(proto_rlc_lte, NULL);
1438
1439     prefs_register_bool_preference(rlc_lte_module, "do_sequence_analysis",
1440         "Do sequence analysis for UM/AM channels",
1441         "Attempt to keep track of PDUs for UM/AM channels, and point out problems",
1442         &global_rlc_lte_sequence_analysis);
1443
1444     register_init_routine(&rlc_lte_init_protocol);
1445 }
1446
1447