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