1 /* Routines for LTE RLC disassembly
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
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.
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.
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.
32 #include <epan/packet.h>
33 #include <epan/expert.h>
34 #include <epan/prefs.h>
37 #include "packet-mac-lte.h"
38 #include "packet-rlc-lte.h"
39 #include "packet-pdcp-lte.h"
43 * 3GPP TS 36.322 Evolved Universal Terrestial Radio Access (E-UTRA)
44 * Radio Link Control (RLC) Protocol specification
51 /********************************/
52 /* Preference settings */
54 #define SEQUENCE_ANALYSIS_MAC_ONLY 1
55 #define SEQUENCE_ANALYSIS_RLC_ONLY 2
57 /* By default don't try to analyse the sequence of messages for AM/UM channels */
58 static gint global_rlc_lte_am_sequence_analysis = FALSE;
59 static gint global_rlc_lte_um_sequence_analysis = FALSE;
61 /* By default don't call PDCP/RRC dissectors for SDU data */
62 static gboolean global_rlc_lte_call_pdcp_for_srb = FALSE;
64 enum pdcp_for_drb { PDCP_drb_off, PDCP_drb_SN_7, PDCP_drb_SN_12};
65 static enum_val_t pdcp_drb_col_vals[] = {
66 {"pdcp-drb-off", "Off", PDCP_drb_off},
67 {"pdcp-drb-sn-7", "7-bit SN", PDCP_drb_SN_7},
68 {"pdcp-drb-sn-12", "12-bit SN", PDCP_drb_SN_12},
71 static gint global_rlc_lte_call_pdcp_for_drb = (gint)PDCP_drb_off;
73 static gboolean global_rlc_lte_call_rrc = FALSE;
75 /* Preference to expect RLC headers without payloads */
76 static gboolean global_rlc_lte_headers_expected = FALSE;
78 /* Heuristic dissection */
79 static gboolean global_rlc_lte_heur = FALSE;
82 /**************************************************/
83 /* Initialize the protocol and registered fields. */
84 int proto_rlc_lte = -1;
86 extern int proto_mac_lte;
87 extern int proto_pdcp_lte;
89 static int rlc_lte_tap = -1;
91 /* Decoding context */
92 static int hf_rlc_lte_context = -1;
93 static int hf_rlc_lte_context_mode = -1;
94 static int hf_rlc_lte_context_direction = -1;
95 static int hf_rlc_lte_context_priority = -1;
96 static int hf_rlc_lte_context_ueid = -1;
97 static int hf_rlc_lte_context_channel_type = -1;
98 static int hf_rlc_lte_context_channel_id = -1;
99 static int hf_rlc_lte_context_pdu_length = -1;
100 static int hf_rlc_lte_context_um_sn_length = -1;
102 /* Transparent mode fields */
103 static int hf_rlc_lte_tm = -1;
104 static int hf_rlc_lte_tm_data = -1;
106 /* Unacknowledged mode fields */
107 static int hf_rlc_lte_um = -1;
108 static int hf_rlc_lte_um_header = -1;
109 static int hf_rlc_lte_um_fi = -1;
110 static int hf_rlc_lte_um_fixed_e = -1;
111 static int hf_rlc_lte_um_sn = -1;
112 static int hf_rlc_lte_um_fixed_reserved = -1;
113 static int hf_rlc_lte_um_data = -1;
114 static int hf_rlc_lte_extension_part = -1;
116 /* Extended header (common to UM and AM) */
117 static int hf_rlc_lte_extension_e = -1;
118 static int hf_rlc_lte_extension_li = -1;
119 static int hf_rlc_lte_extension_padding = -1;
122 /* Acknowledged mode fields */
123 static int hf_rlc_lte_am = -1;
124 static int hf_rlc_lte_am_header = -1;
125 static int hf_rlc_lte_am_data_control = -1;
126 static int hf_rlc_lte_am_rf = -1;
127 static int hf_rlc_lte_am_p = -1;
128 static int hf_rlc_lte_am_fi = -1;
129 static int hf_rlc_lte_am_fixed_e = -1;
130 static int hf_rlc_lte_am_fixed_sn = -1;
131 static int hf_rlc_lte_am_segment_lsf = -1;
132 static int hf_rlc_lte_am_segment_so = -1;
133 static int hf_rlc_lte_am_data = -1;
136 static int hf_rlc_lte_am_cpt = -1;
137 static int hf_rlc_lte_am_ack_sn = -1;
138 static int hf_rlc_lte_am_e1 = -1;
139 static int hf_rlc_lte_am_e2 = -1;
140 static int hf_rlc_lte_am_nack_sn = -1;
141 static int hf_rlc_lte_am_so_start = -1;
142 static int hf_rlc_lte_am_so_end = -1;
144 static int hf_rlc_lte_predefined_pdu = -1;
145 static int hf_rlc_lte_header_only = -1;
147 /* Sequence Analysis */
148 static int hf_rlc_lte_sequence_analysis = -1;
149 static int hf_rlc_lte_sequence_analysis_ok = -1;
150 static int hf_rlc_lte_sequence_analysis_previous_frame = -1;
151 static int hf_rlc_lte_sequence_analysis_expected_sn = -1;
152 static int hf_rlc_lte_sequence_analysis_framing_info_correct = -1;
154 static int hf_rlc_lte_sequence_analysis_mac_retx = -1;
155 static int hf_rlc_lte_sequence_analysis_retx = -1;
156 static int hf_rlc_lte_sequence_analysis_repeated = -1;
157 static int hf_rlc_lte_sequence_analysis_skipped = -1;
159 static int hf_rlc_lte_sequence_analysis_repeated_nack = -1;
162 static int ett_rlc_lte = -1;
163 static int ett_rlc_lte_context = -1;
164 static int ett_rlc_lte_um_header = -1;
165 static int ett_rlc_lte_am_header = -1;
166 static int ett_rlc_lte_extension_part = -1;
167 static int ett_rlc_lte_sequence_analysis = -1;
170 static const value_string direction_vals[] =
172 { DIRECTION_UPLINK, "Uplink"},
173 { DIRECTION_DOWNLINK, "Downlink"},
177 static const value_string rlc_mode_short_vals[] =
179 { RLC_TM_MODE, "TM"},
180 { RLC_UM_MODE, "UM"},
181 { RLC_AM_MODE, "AM"},
182 { RLC_PREDEF, "PREDEFINED"},
186 static const value_string rlc_mode_vals[] =
188 { RLC_TM_MODE, "Transparent Mode"},
189 { RLC_UM_MODE, "Unacknowledged Mode"},
190 { RLC_AM_MODE, "Acknowledged Mode"},
194 static const value_string rlc_channel_type_vals[] =
196 { CHANNEL_TYPE_CCCH, "CCCH"},
197 { CHANNEL_TYPE_BCCH, "BCCH"},
198 { CHANNEL_TYPE_PCCH, "PCCH"},
199 { CHANNEL_TYPE_SRB, "SRB"},
200 { CHANNEL_TYPE_DRB, "DRB"},
204 static const value_string framing_info_vals[] =
206 { 0, "First byte begins a RLC SDU and last byte ends a RLC SDU"},
207 { 1, "First byte begins a RLC SDU and last byte does not end a RLC SDU"},
208 { 2, "First byte does not begin a RLC SDU and last byte ends a RLC SDU"},
209 { 3, "First byte does not begin a RLC SDU and last byte does not end a RLC SDU"},
213 static const value_string fixed_extension_vals[] =
215 { 0, "Data field follows from the octet following the fixed part of the header"},
216 { 1, "A set of E field and LI field follows from the octet following the fixed part of the header"},
220 static const value_string extension_extension_vals[] =
222 { 0, "Data field follows from the octet following the LI field following this E field"},
223 { 1, "A set of E field and LI field follows from the bit following the LI field following this E field"},
227 static const value_string data_or_control_vals[] =
234 static const value_string resegmentation_flag_vals[] =
237 { 1, "AMD PDU segment"},
241 static const value_string polling_bit_vals[] =
243 { 0, "Status report not requested"},
244 { 1, "Status report is requested"},
248 static const value_string lsf_vals[] =
250 { 0, "Last byte of the AMD PDU segment does not correspond to the last byte of an AMD PDU"},
251 { 1, "Last byte of the AMD PDU segment corresponds to the last byte of an AMD PDU"},
255 static const value_string control_pdu_type_vals[] =
261 static const value_string am_e1_vals[] =
263 { 0, "A set of NACK_SN, E1 and E2 does not follow"},
264 { 1, "A set of NACK_SN, E1 and E2 follows"},
268 static const value_string am_e2_vals[] =
270 { 0, "A set of SOstart and SOend does not follow for this NACK_SN"},
271 { 1, "A set of SOstart and SOend follows for this NACK_SN"},
275 static const value_string header_only_vals[] =
277 { 0, "RLC PDU Headers and body present"},
278 { 1, "RLC PDU Headers only"},
284 /**********************************************************************************/
285 /* These are for keeping track of UM/AM extension headers, and the lengths found */
287 guint8 s_number_of_extensions = 0;
288 #define MAX_RLC_SDUS 64
289 guint16 s_lengths[MAX_RLC_SDUS];
292 /*********************************************************************/
293 /* UM/AM sequence analysis */
295 /* Types for RLC channel hash table */
296 /* This table is maintained during initial dissection of RLC */
297 /* frames, mapping from rlc_channel_hash_key -> rlc_channel_status */
306 } rlc_channel_hash_key;
308 /* Conversation-type status for sequence analysis on channel */
313 /* For UM, we always expect the SN to keep advancing, and these fields
315 For AM, these correspond to new data */
316 guint16 previousSequenceNumber;
317 guint32 previousFrameNum;
318 gboolean previousSegmentIncomplete;
319 } rlc_channel_sequence_analysis_status;
321 /* The sequence analysis channel hash table */
322 static GHashTable *rlc_lte_sequence_analysis_channel_hash = NULL;
325 /* Types for sequence analysis frame report hash table */
326 /* This is a table from framenum -> state_report_in_frame */
327 /* This is necessary because the per-packet info is already being used */
328 /* for context information before the dissector is called */
330 /* Info to attach to frame when first read, recording what to show about sequence */
333 gboolean sequenceExpectedCorrect;
334 guint16 sequenceExpected;
335 guint32 previousFrameNum;
336 gboolean previousSegmentIncomplete;
342 enum { SN_OK, SN_Repeated, SN_MAC_Retx, SN_Retx, SN_Missing} state;
343 } state_sequence_analysis_report_in_frame;
346 /* The sequence analysis frame report hash table instance itself */
347 static GHashTable *rlc_lte_frame_sequence_analysis_report_hash = NULL;
350 /******************************************************************/
351 /* Conversation-type status for repeated NACK checking on channel */
355 guint16 NACKs[MAX_NACKs];
356 } rlc_channel_repeated_nack_status;
358 static GHashTable *rlc_lte_repeated_nack_channel_hash = NULL;
361 guint16 noOfNACKsRepeated;
362 guint16 repeatedNACKs[MAX_NACKs];
363 } rlc_channel_repeated_nack_report_in_frame;
365 static GHashTable *rlc_lte_frame_repeated_nack_report_hash = NULL;
369 /********************************************************/
370 /* Forward declarations & functions */
371 void proto_reg_handoff_rlc_lte(void);
372 void dissect_rlc_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
375 /* Write the given formatted text to:
377 - the top-level RLC PDU item
378 - another subtree item (if supplied) */
379 static void write_pdu_label_and_info(proto_item *pdu_ti, proto_item *sub_ti,
380 packet_info *pinfo, const char *format, ...)
382 #define MAX_INFO_BUFFER 256
383 static char info_buffer[MAX_INFO_BUFFER];
387 va_start(ap, format);
388 g_vsnprintf(info_buffer, MAX_INFO_BUFFER, format, ap);
391 /* Add to indicated places */
392 col_append_str(pinfo->cinfo, COL_INFO, info_buffer);
393 proto_item_append_text(pdu_ti, "%s", info_buffer);
394 if (sub_ti != NULL) {
395 proto_item_append_text(sub_ti, "%s", info_buffer);
401 /* Dissect extension headers (common to both UM and AM) */
402 static int dissect_rlc_lte_extension_header(tvbuff_t *tvb, packet_info *pinfo _U_,
407 guint64 extension = 1;
410 /* Reset this count */
411 s_number_of_extensions = 0;
413 while (extension && (s_number_of_extensions < MAX_RLC_SDUS)) {
414 proto_tree *extension_part_tree;
415 proto_item *extension_part_ti;
417 isOdd = (s_number_of_extensions % 2);
419 /* Extension part subtree */
420 extension_part_ti = proto_tree_add_string_format(tree,
421 hf_rlc_lte_extension_part,
425 extension_part_tree = proto_item_add_subtree(extension_part_ti,
426 ett_rlc_lte_extension_part);
428 /* Read next extension */
429 proto_tree_add_bits_ret_val(extension_part_tree, hf_rlc_lte_extension_e, tvb,
430 (offset*8) + ((isOdd) ? 4 : 0),
434 /* Read length field */
435 proto_tree_add_bits_ret_val(extension_part_tree, hf_rlc_lte_extension_li, tvb,
436 (offset*8) + ((isOdd) ? 5 : 1),
440 proto_item_append_text(extension_part_tree, " (length=%u)", (guint16)length);
442 /* Move on to byte of next extension */
449 s_lengths[s_number_of_extensions++] = (guint16)length;
452 /* May need to skip padding after last extension part */
453 isOdd = (s_number_of_extensions % 2);
458 padding = tvb_get_guint8(tvb, offset) & 0x0f;
459 ti = proto_tree_add_item(tree, hf_rlc_lte_extension_padding,
460 tvb, offset, 1, FALSE);
468 /* Show in the info column how many bytes are in the UM/AM PDU, and indicate
469 whether or not the beginning and end are included in this packet */
470 static void show_PDU_in_info(packet_info *pinfo,
473 gboolean first_includes_start,
474 gboolean last_includes_end)
476 /* Reflect this PDU in the info column */
477 write_pdu_label_and_info(top_ti, NULL, pinfo,
479 (first_includes_start) ? "[" : "..",
481 (length > 1) ? "s" : "",
482 (last_includes_end) ? "]" : "..");
486 /* Show an AM PDU. If configured, pass to PDCP dissector */
487 static void show_AM_PDU_in_tree(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, gint offset, gint length,
488 rlc_lte_info *rlc_info, gboolean whole_pdu)
490 proto_item *data_ti = proto_tree_add_item(tree, hf_rlc_lte_am_data, tvb, offset, length, FALSE);
492 /* Decode signalling PDUs as PDCP */
494 (((global_rlc_lte_call_pdcp_for_srb) && (rlc_info->channelType == CHANNEL_TYPE_SRB)) ||
495 ((global_rlc_lte_call_pdcp_for_drb != PDCP_drb_off) && (rlc_info->channelType == CHANNEL_TYPE_DRB)))) {
497 /* Attempt to decode payload using LTE PDCP dissector */
498 tvbuff_t *pdcp_tvb = tvb_new_subset(tvb, offset, length, length);
499 volatile dissector_handle_t protocol_handle;
501 struct pdcp_lte_info *p_pdcp_lte_info;
503 /* Reuse or allocate struct */
504 p_pdcp_lte_info = p_get_proto_data(pinfo->fd, proto_pdcp_lte);
505 if (p_pdcp_lte_info == NULL) {
506 p_pdcp_lte_info = se_alloc0(sizeof(struct pdcp_lte_info));
507 /* Store info in packet */
508 p_add_proto_data(pinfo->fd, proto_pdcp_lte, p_pdcp_lte_info);
511 p_pdcp_lte_info->channelType = Channel_DCCH;
512 p_pdcp_lte_info->direction = rlc_info->direction;
513 p_pdcp_lte_info->no_header_pdu = FALSE;
514 if (rlc_info->channelType == CHANNEL_TYPE_SRB) {
515 p_pdcp_lte_info->plane = SIGNALING_PLANE;
518 p_pdcp_lte_info->plane = USER_PLANE;
520 /* Set sequence number field length */
521 switch (global_rlc_lte_call_pdcp_for_drb) {
523 p_pdcp_lte_info->seqnum_length = 7;
526 p_pdcp_lte_info->seqnum_length = 12;
529 DISSECTOR_ASSERT(FALSE);
533 p_pdcp_lte_info->rohc_compression = FALSE;
536 /* Get dissector handle */
537 protocol_handle = find_dissector("pdcp-lte");
540 call_dissector_only(protocol_handle, pdcp_tvb, pinfo, tree);
546 PROTO_ITEM_SET_HIDDEN(data_ti);
550 /* Hash table functions for RLC channels */
553 static gint rlc_channel_equal(gconstpointer v, gconstpointer v2)
555 const rlc_channel_hash_key* val1 = v;
556 const rlc_channel_hash_key* val2 = v2;
558 /* All fields must match */
559 return ((val1->ueId == val2->ueId) &&
560 (val1->channelType == val2->channelType) &&
561 (val1->channelId == val2->channelId) &&
562 (val1->direction == val2->direction));
565 /* Compute a hash value for a given key. */
566 static guint rlc_channel_hash_func(gconstpointer v)
568 const rlc_channel_hash_key* val1 = v;
570 /* TODO: check/reduce multipliers */
571 return ((val1->ueId * 1024) + (val1->channelType*64) + (val1->channelId*2) + val1->direction);
576 /* Hash table functions for frame reports */
579 static gint rlc_frame_equal(gconstpointer v, gconstpointer v2)
584 /* Compute a hash value for a given key. */
585 static guint rlc_frame_hash_func(gconstpointer v)
587 return GPOINTER_TO_UINT(v);
592 /* Add to the tree values associated with sequence analysis for this frame */
593 static void addChannelSequenceInfo(state_sequence_analysis_report_in_frame *p,
594 rlc_lte_info *p_rlc_lte_info,
595 guint16 sequenceNumber,
596 gboolean newSegmentStarted,
597 rlc_lte_tap_info *tap_info,
598 packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb)
600 proto_tree *seqnum_tree;
601 proto_item *seqnum_ti;
605 seqnum_ti = proto_tree_add_string_format(tree,
606 hf_rlc_lte_sequence_analysis,
608 "", "Sequence Analysis");
609 seqnum_tree = proto_item_add_subtree(seqnum_ti,
610 ett_rlc_lte_sequence_analysis);
611 PROTO_ITEM_SET_GENERATED(seqnum_ti);
613 switch (p_rlc_lte_info->rlcMode) {
616 /********************************************/
618 /********************************************/
622 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ok,
624 PROTO_ITEM_SET_GENERATED(ti);
625 proto_item_append_text(seqnum_ti, " - OK");
629 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ok,
631 PROTO_ITEM_SET_GENERATED(ti);
632 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_mac_retx,
634 PROTO_ITEM_SET_GENERATED(ti);
635 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
636 "AM Frame retransmitted for %s on UE %u - due to MAC retx!",
637 val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
638 p_rlc_lte_info->ueid);
642 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ok,
644 PROTO_ITEM_SET_GENERATED(ti);
645 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_retx,
647 PROTO_ITEM_SET_GENERATED(ti);
648 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
649 "AM Frame retransmitted for %s on UE %u - most likely in response to NACK",
650 val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
651 p_rlc_lte_info->ueid);
652 proto_item_append_text(seqnum_ti, " - SN %u retransmitted", p->firstSN);
656 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ok,
658 PROTO_ITEM_SET_GENERATED(ti);
659 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_repeated,
661 PROTO_ITEM_SET_GENERATED(ti);
662 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
663 "AM SN Repeated for %s for UE %u - probably because didn't receive Status PDU?",
664 val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
665 p_rlc_lte_info->ueid);
666 proto_item_append_text(seqnum_ti, "- SN %u Repeated",
667 p->sequenceExpected);
671 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ok,
673 PROTO_ITEM_SET_GENERATED(ti);
674 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_skipped,
676 PROTO_ITEM_SET_GENERATED(ti);
677 if (p->lastSN != p->firstSN) {
678 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
679 "AM SNs (%u to %u) missing for %s on UE %u",
680 p->firstSN, p->lastSN,
681 val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
682 p_rlc_lte_info->ueid);
683 proto_item_append_text(seqnum_ti, " - SNs missing (%u to %u)",
684 p->firstSN, p->lastSN);
685 tap_info->missingSNs = ((p->lastSN - p->firstSN) % 1024) + 1;
688 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
689 "AM SN (%u) missing for %s on UE %u",
691 val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
692 p_rlc_lte_info->ueid);
693 proto_item_append_text(seqnum_ti, " - SN missing (%u)",
695 tap_info->missingSNs = 1;
703 /********************************************/
705 /********************************************/
707 /* Previous channel frame */
708 if (p->previousFrameNum != 0) {
709 proto_tree_add_uint(seqnum_tree, hf_rlc_lte_sequence_analysis_previous_frame,
710 tvb, 0, 0, p->previousFrameNum);
713 /* Expected sequence number */
714 ti = proto_tree_add_uint(seqnum_tree, hf_rlc_lte_sequence_analysis_expected_sn,
715 tvb, 0, 0, p->sequenceExpected);
716 PROTO_ITEM_SET_GENERATED(ti);
718 if (!p->sequenceExpectedCorrect) {
719 /* Work out SN wrap (in case needed below) */
721 if (p_rlc_lte_info->UMSequenceNumberLength == 5) {
730 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ok,
732 PROTO_ITEM_SET_GENERATED(ti);
733 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_skipped,
735 PROTO_ITEM_SET_GENERATED(ti);
736 if (p->lastSN != p->firstSN) {
737 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
738 "UM SNs (%u to %u) missing for %s on UE %u",
739 p->firstSN, p->lastSN,
740 val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
741 p_rlc_lte_info->ueid);
742 proto_item_append_text(seqnum_ti, " - SNs missing (%u to %u)",
743 p->firstSN, p->lastSN);
744 tap_info->missingSNs = ((p->lastSN - p->firstSN) % snLimit) + 1;
747 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
748 "UM SN (%u) missing for %s on UE %u",
750 val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
751 p_rlc_lte_info->ueid);
752 proto_item_append_text(seqnum_ti, " - SN missing (%u)",
754 tap_info->missingSNs = 1;
759 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ok,
761 PROTO_ITEM_SET_GENERATED(ti);
762 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_repeated,
764 PROTO_ITEM_SET_GENERATED(ti);
765 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
766 "UM SN (%u) repeated for %s for UE %u",
768 val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
769 p_rlc_lte_info->ueid);
770 proto_item_append_text(seqnum_ti, "- SN %u Repeated",
771 p->sequenceExpected);
775 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ok,
777 PROTO_ITEM_SET_GENERATED(ti);
778 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_mac_retx,
780 PROTO_ITEM_SET_GENERATED(ti);
781 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
782 "UM Frame retransmitted for %s on UE %u - due to MAC retx!",
783 val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
784 p_rlc_lte_info->ueid);
788 /* Incorrect sequence number */
789 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
790 "Wrong Sequence Number for %s on UE %u - got %u, expected %u",
791 val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
792 p_rlc_lte_info->ueid, sequenceNumber, p->sequenceExpected);
798 /* Correct sequence number, so check frame indication bits consistent */
799 if (p->previousSegmentIncomplete) {
800 /* Previous segment was incomplete, so this PDU should continue it */
801 if (newSegmentStarted) {
802 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_framing_info_correct,
804 if (!p->sequenceExpectedCorrect) {
805 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
806 "Last segment of previous PDU was not continued for UE %u",
807 p_rlc_lte_info->ueid);
811 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_framing_info_correct,
816 /* Previous segment was complete, so this PDU should start a new one */
817 if (!newSegmentStarted) {
818 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_framing_info_correct,
820 if (!p->sequenceExpectedCorrect) {
821 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
822 "Last segment of previous PDU was complete, but new segment was not started");
826 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_framing_info_correct,
831 PROTO_ITEM_SET_GENERATED(ti);
836 /* Update the channel status and set report for this frame */
837 static void checkChannelSequenceInfo(packet_info *pinfo, tvbuff_t *tvb,
838 rlc_lte_info *p_rlc_lte_info,
839 guint16 sequenceNumber,
840 gboolean first_includes_start, gboolean last_includes_end,
841 gboolean is_resegmented _U_,
842 rlc_lte_tap_info *tap_info,
845 rlc_channel_hash_key channel_key;
846 rlc_channel_hash_key *p_channel_key;
847 rlc_channel_sequence_analysis_status *p_channel_status;
848 state_sequence_analysis_report_in_frame *p_report_in_frame = NULL;
849 gboolean createdChannel = FALSE;
850 guint16 expectedSequenceNumber = 0;
853 /* If find stat_report_in_frame already, use that and get out */
854 if (pinfo->fd->flags.visited) {
855 p_report_in_frame = (state_sequence_analysis_report_in_frame*)g_hash_table_lookup(rlc_lte_frame_sequence_analysis_report_hash,
857 if (p_report_in_frame != NULL) {
858 addChannelSequenceInfo(p_report_in_frame, p_rlc_lte_info,
859 sequenceNumber, first_includes_start,
860 tap_info, pinfo, tree, tvb);
864 /* Give up - we must have tried already... */
870 /**************************************************/
871 /* Create or find an entry for this channel state */
872 channel_key.ueId = p_rlc_lte_info->ueid;
873 channel_key.channelType = p_rlc_lte_info->channelType;
874 channel_key.channelId = p_rlc_lte_info->channelId;
875 channel_key.direction = p_rlc_lte_info->direction;
877 /* Do the table lookup */
878 p_channel_status = (rlc_channel_sequence_analysis_status*)g_hash_table_lookup(rlc_lte_sequence_analysis_channel_hash, &channel_key);
880 /* Create table entry if necessary */
881 if (p_channel_status == NULL) {
882 createdChannel = TRUE;
884 /* Allocate a new key and value */
885 p_channel_key = se_alloc(sizeof(rlc_channel_hash_key));
886 p_channel_status = se_alloc0(sizeof(rlc_channel_sequence_analysis_status));
888 /* Copy key contents */
889 memcpy(p_channel_key, &channel_key, sizeof(rlc_channel_hash_key));
892 p_channel_status->rlcMode = p_rlc_lte_info->rlcMode;
895 g_hash_table_insert(rlc_lte_sequence_analysis_channel_hash, p_channel_key, p_channel_status);
898 /* Create space for frame state_report */
899 p_report_in_frame = se_alloc(sizeof(state_sequence_analysis_report_in_frame));
901 switch (p_channel_status->rlcMode) {
904 if (p_rlc_lte_info->UMSequenceNumberLength == 5) {
911 /* Work out expected sequence number */
912 if (!createdChannel) {
913 expectedSequenceNumber = (p_channel_status->previousSequenceNumber + 1) % snLimit;
916 /* Set report for this frame */
917 /* For UM, sequence number is always expectedSequence number */
918 p_report_in_frame->sequenceExpectedCorrect = (sequenceNumber == expectedSequenceNumber);
920 /* For wrong sequence number... */
921 if (!p_report_in_frame->sequenceExpectedCorrect) {
923 p_report_in_frame->sequenceExpectedCorrect = FALSE;
925 /* Don't get confused by MAC (HARQ) retx */
926 if (is_mac_lte_frame_retx(pinfo, p_rlc_lte_info->direction)) {
927 p_report_in_frame->state = SN_MAC_Retx;
930 /* Frames are not missing if we get an earlier sequence number again */
931 else if (((snLimit + expectedSequenceNumber - sequenceNumber) % snLimit) > 40) {
932 p_report_in_frame->state = SN_Missing;
933 tap_info->missingSNs = (snLimit + sequenceNumber - expectedSequenceNumber) % snLimit;
934 p_report_in_frame->firstSN = expectedSequenceNumber;
935 p_report_in_frame->lastSN = (snLimit + sequenceNumber - 1) % snLimit;
937 p_report_in_frame->sequenceExpected = expectedSequenceNumber;
938 p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
939 p_report_in_frame->previousSegmentIncomplete = p_channel_status->previousSegmentIncomplete;
941 /* Update channel status to remember *this* frame */
942 p_channel_status->previousFrameNum = pinfo->fd->num;
943 p_channel_status->previousSequenceNumber = sequenceNumber;
944 p_channel_status->previousSegmentIncomplete = !last_includes_end;
947 /* An SN has been repeated */
948 p_report_in_frame->state = SN_Repeated;
949 p_report_in_frame->firstSN = sequenceNumber;
951 p_report_in_frame->sequenceExpected = expectedSequenceNumber;
952 p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
957 p_report_in_frame->sequenceExpected = expectedSequenceNumber;
958 p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
959 p_report_in_frame->previousSegmentIncomplete = p_channel_status->previousSegmentIncomplete;
961 /* Update channel status to remember *this* frame */
962 p_channel_status->previousFrameNum = pinfo->fd->num;
963 p_channel_status->previousSequenceNumber = sequenceNumber;
964 p_channel_status->previousSegmentIncomplete = !last_includes_end;
971 /* Work out expected sequence number */
972 if (!createdChannel) {
973 expectedSequenceNumber = (p_channel_status->previousSequenceNumber + 1) % 1024;
977 - expected Sequence number OR
978 - previous frame repeated
979 - old SN being sent (in response to NACK)
980 - new SN, but with frames missed out
981 Assume window whose front is at expectedSequenceNumber */
983 /* First of all, check to see whether frame is judged to be MAC Retx */
984 if (is_mac_lte_frame_retx(pinfo, p_rlc_lte_info->direction)) {
985 /* Just report that this is a MAC Retx */
986 p_report_in_frame->state = SN_MAC_Retx;
988 /* No channel state to update */
993 else if (sequenceNumber == expectedSequenceNumber) {
995 /* Set report for this frame */
996 p_report_in_frame->sequenceExpectedCorrect = TRUE;
997 p_report_in_frame->sequenceExpected = expectedSequenceNumber;
998 p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
999 p_report_in_frame->previousSegmentIncomplete = p_channel_status->previousSegmentIncomplete;
1000 p_report_in_frame->state = SN_OK;
1002 /* Update channel status */
1003 p_channel_status->previousSequenceNumber = sequenceNumber;
1004 p_channel_status->previousFrameNum = pinfo->fd->num;
1005 p_channel_status->previousSegmentIncomplete = !last_includes_end;
1008 /* Previous subframe repeated? */
1009 else if (((sequenceNumber+1) % 1024) == expectedSequenceNumber) {
1010 p_report_in_frame->state = SN_Repeated;
1012 /* Set report for this frame */
1013 p_report_in_frame->sequenceExpectedCorrect = FALSE;
1014 p_report_in_frame->sequenceExpected = sequenceNumber;
1015 p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
1016 p_report_in_frame->previousSegmentIncomplete = p_channel_status->previousSegmentIncomplete;
1019 /* Really should be nothing to update... */
1020 p_channel_status->previousSequenceNumber = sequenceNumber;
1021 p_channel_status->previousFrameNum = pinfo->fd->num;
1022 p_channel_status->previousSegmentIncomplete = !last_includes_end;
1026 /* Need to work out if new (with skips, or likely a retx (due to NACK)) */
1027 int delta = (1024 + expectedSequenceNumber - sequenceNumber) % 1024;
1029 /* Rx window is 512, so check to see if this is a retx */
1031 /* Probably a retx due to receiving NACK */
1032 p_report_in_frame->state = SN_Retx;
1034 p_report_in_frame->firstSN = sequenceNumber;
1035 /* Don't update anything in channel state */
1039 /* Ahead of expected SN. Assume frames have been missed */
1040 p_report_in_frame->state = SN_Missing;
1042 p_report_in_frame->firstSN = expectedSequenceNumber;
1043 p_report_in_frame->lastSN = (1024 + sequenceNumber-1) % 1024;
1045 /* Update channel state - forget about missed SNs */
1046 p_report_in_frame->sequenceExpected = expectedSequenceNumber;
1047 p_channel_status->previousSequenceNumber = sequenceNumber;
1048 p_channel_status->previousFrameNum = pinfo->fd->num;
1049 p_channel_status->previousSegmentIncomplete = !last_includes_end;
1055 /* Shouldn't get here! */
1059 /* Associate with this frame number */
1060 g_hash_table_insert(rlc_lte_frame_sequence_analysis_report_hash, &pinfo->fd->num, p_report_in_frame);
1062 /* Add state report for this frame into tree */
1063 addChannelSequenceInfo(p_report_in_frame, p_rlc_lte_info, sequenceNumber,
1064 first_includes_start, tap_info, pinfo, tree, tvb);
1068 /* Add to the tree values associated with sequence analysis for this frame */
1069 static void addChannelRepeatedNACKInfo(rlc_channel_repeated_nack_report_in_frame *p,
1070 rlc_lte_info *p_rlc_lte_info _U_,
1071 packet_info *pinfo, proto_tree *tree,
1074 proto_tree *seqnum_tree;
1075 proto_item *seqnum_ti;
1079 /* Create subtree */
1080 seqnum_ti = proto_tree_add_string_format(tree,
1081 hf_rlc_lte_sequence_analysis,
1083 "", "Sequence Analysis");
1084 seqnum_tree = proto_item_add_subtree(seqnum_ti,
1085 ett_rlc_lte_sequence_analysis);
1086 PROTO_ITEM_SET_GENERATED(seqnum_ti);
1089 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ok,
1091 PROTO_ITEM_SET_GENERATED(ti);
1093 /* Add each repeated NACK as item & expert info */
1094 for (n=0; n < p->noOfNACKsRepeated; n++) {
1096 ti = proto_tree_add_uint(seqnum_tree, hf_rlc_lte_sequence_analysis_repeated_nack,
1097 tvb, 0, 0, p->repeatedNACKs[n]);
1098 PROTO_ITEM_SET_GENERATED(ti);
1100 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_ERROR,
1101 "Same SN (%u) NACKd for %s on UE %u in successive Status PDUs",
1102 p->repeatedNACKs[n],
1103 val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
1104 p_rlc_lte_info->ueid);
1107 /* Append count to sequence analysis root */
1108 proto_item_append_text(seqnum_ti, " - %u SNs repeated from previous Status PDU",
1109 p->noOfNACKsRepeated);
1113 /* Update the channel repeated NACK status and set report for this frame */
1114 static void checkChannelRepeatedNACKInfo(packet_info *pinfo,
1115 rlc_lte_info *p_rlc_lte_info,
1116 rlc_lte_tap_info *tap_info,
1120 rlc_channel_hash_key channel_key;
1121 rlc_channel_hash_key *p_channel_key;
1122 rlc_channel_repeated_nack_status *p_channel_status;
1123 rlc_channel_repeated_nack_report_in_frame *p_report_in_frame = NULL;
1125 guint16 noOfNACKsRepeated = 0;
1126 guint16 repeatedNACKs[MAX_NACKs];
1129 /* If find state_report_in_frame already, use that and get out */
1130 if (pinfo->fd->flags.visited) {
1131 p_report_in_frame = (rlc_channel_repeated_nack_report_in_frame*)g_hash_table_lookup(rlc_lte_frame_repeated_nack_report_hash,
1133 if (p_report_in_frame != NULL) {
1134 addChannelRepeatedNACKInfo(p_report_in_frame, p_rlc_lte_info,
1139 /* Give up - we must have tried already... */
1145 /**************************************************/
1146 /* Create or find an entry for this channel state */
1147 channel_key.ueId = p_rlc_lte_info->ueid;
1148 channel_key.channelType = p_rlc_lte_info->channelType;
1149 channel_key.channelId = p_rlc_lte_info->channelId;
1150 channel_key.direction = p_rlc_lte_info->direction;
1152 /* Do the table lookup */
1153 p_channel_status = (rlc_channel_repeated_nack_status*)g_hash_table_lookup(rlc_lte_repeated_nack_channel_hash, &channel_key);
1155 /* Create table entry if necessary */
1156 if (p_channel_status == NULL) {
1158 /* Allocate a new key and value */
1159 p_channel_key = se_alloc(sizeof(rlc_channel_hash_key));
1160 p_channel_status = se_alloc0(sizeof(rlc_channel_repeated_nack_status));
1162 /* Copy key contents */
1163 memcpy(p_channel_key, &channel_key, sizeof(rlc_channel_hash_key));
1165 /* Add entry to table */
1166 g_hash_table_insert(rlc_lte_repeated_nack_channel_hash, p_channel_key, p_channel_status);
1169 /* Compare NACKs in channel status with NACKs in tap_info.
1170 Note any that are repeated */
1171 for (i=0; i < p_channel_status->noOfNACKs; i++) {
1172 for (j=0; j < MIN(tap_info->noOfNACKs, MAX_NACKs); j++) {
1173 if (tap_info->NACKs[j] == p_channel_status->NACKs[i]) {
1174 /* Don't add the same repeated NACK twice! */
1175 if ((noOfNACKsRepeated == 0) ||
1176 (repeatedNACKs[noOfNACKsRepeated-1] != p_channel_status->NACKs[i])) {
1178 repeatedNACKs[noOfNACKsRepeated++] = p_channel_status->NACKs[i];
1184 /* Copy NACKs from tap_info into channel status for next time! */
1185 p_channel_status->noOfNACKs = 0;
1186 for (n=0; n < MIN(tap_info->noOfNACKs, MAX_NACKs); n++) {
1187 p_channel_status->NACKs[p_channel_status->noOfNACKs++] = tap_info->NACKs[n];
1190 if (noOfNACKsRepeated >= 1) {
1191 /* Create space for frame state_report */
1192 p_report_in_frame = se_alloc(sizeof(rlc_channel_repeated_nack_report_in_frame));
1194 /* Copy in found duplicates */
1195 for (n=0; n < MIN(tap_info->noOfNACKs, MAX_NACKs); n++) {
1196 p_report_in_frame->repeatedNACKs[n] = repeatedNACKs[n];
1198 p_report_in_frame->noOfNACKsRepeated = noOfNACKsRepeated;
1200 /* Associate with this frame number */
1201 g_hash_table_insert(rlc_lte_frame_repeated_nack_report_hash, &pinfo->fd->num, p_report_in_frame);
1203 /* Add state report for this frame into tree */
1204 addChannelRepeatedNACKInfo(p_report_in_frame, p_rlc_lte_info,
1211 /***************************************************/
1212 /* Transparent mode PDU. Call RRC if configured to */
1213 static void dissect_rlc_lte_tm(tvbuff_t *tvb, packet_info *pinfo,
1216 rlc_lte_info *p_rlc_lte_info,
1217 proto_item *top_ti _U_)
1219 proto_item *raw_tm_ti;
1222 /* Create hidden TM root */
1223 tm_ti = proto_tree_add_string_format(tree, hf_rlc_lte_tm,
1224 tvb, offset, 0, "", "UM");
1225 PROTO_ITEM_SET_HIDDEN(tm_ti);
1227 /* Remaining bytes are all data */
1228 raw_tm_ti = proto_tree_add_item(tree, hf_rlc_lte_tm_data, tvb, offset, -1, FALSE);
1229 if (!global_rlc_lte_call_rrc) {
1230 write_pdu_label_and_info(top_ti, NULL, pinfo,
1231 " [%u-bytes]", tvb_length_remaining(tvb, offset));
1234 if (global_rlc_lte_call_rrc) {
1235 tvbuff_t *rrc_tvb = tvb_new_subset(tvb, offset, -1, tvb_length_remaining(tvb, offset));
1236 volatile dissector_handle_t protocol_handle = 0;
1238 switch (p_rlc_lte_info->channelType) {
1239 case CHANNEL_TYPE_CCCH:
1240 if (p_rlc_lte_info->direction == DIRECTION_UPLINK) {
1241 protocol_handle = find_dissector("lte_rrc.ul_ccch");
1244 protocol_handle = find_dissector("lte_rrc.dl_ccch");
1248 case CHANNEL_TYPE_BCCH:
1249 /* TODO: Problem is don't know which transport channel... */
1252 case CHANNEL_TYPE_PCCH:
1253 protocol_handle = find_dissector("lte-rrc.pcch");
1256 case CHANNEL_TYPE_SRB:
1257 case CHANNEL_TYPE_DRB:
1260 /* Shouldn't happen, just return... */
1264 /* Hide raw view of bytes */
1265 PROTO_ITEM_SET_HIDDEN(raw_tm_ti);
1267 /* Call it (catch exceptions) */
1269 call_dissector_only(protocol_handle, rrc_tvb, pinfo, tree);
1279 /***************************************************/
1280 /* Unacknowledged mode PDU */
1281 static void dissect_rlc_lte_um(tvbuff_t *tvb, packet_info *pinfo,
1284 rlc_lte_info *p_rlc_lte_info,
1286 rlc_lte_tap_info *tap_info)
1288 guint64 framing_info;
1289 gboolean first_includes_start;
1290 gboolean last_includes_end;
1291 guint64 fixed_extension;
1293 gint start_offset = offset;
1295 proto_tree *um_header_tree;
1296 proto_item *um_header_ti;
1297 gboolean is_truncated;
1298 proto_item *truncated_ti;
1300 /* Hidden UM root */
1301 um_ti = proto_tree_add_string_format(tree, hf_rlc_lte_um,
1302 tvb, offset, 0, "", "UM");
1303 PROTO_ITEM_SET_HIDDEN(um_ti);
1305 /* Add UM header subtree */
1306 um_header_ti = proto_tree_add_string_format(tree, hf_rlc_lte_um_header,
1309 um_header_tree = proto_item_add_subtree(um_header_ti,
1310 ett_rlc_lte_um_header);
1313 /*******************************/
1314 /* Fixed UM header */
1315 if (p_rlc_lte_info->UMSequenceNumberLength == UM_SN_LENGTH_5_BITS) {
1316 /* Framing info (2 bits) */
1317 proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_fi,
1319 &framing_info, FALSE);
1321 /* Extension (1 bit) */
1322 proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_fixed_e, tvb,
1324 &fixed_extension, FALSE);
1326 /* Sequence Number (5 bit) */
1327 proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_sn, tvb,
1332 else if (p_rlc_lte_info->UMSequenceNumberLength == UM_SN_LENGTH_10_BITS) {
1336 /* Check 3 Reserved bits */
1337 reserved = (tvb_get_guint8(tvb, offset) & 0xe0) >> 5;
1338 ti = proto_tree_add_item(um_header_tree, hf_rlc_lte_um_fixed_reserved, tvb, offset, 1, FALSE);
1339 if (reserved != 0) {
1340 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
1341 "RLC UM Fixed header Reserved bits not zero (found 0x%x)", reserved);
1344 /* Framing info (2 bits) */
1345 proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_fi,
1346 tvb, (offset*8)+3, 2,
1347 &framing_info, FALSE);
1349 /* Extension (1 bit) */
1350 proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_fixed_e, tvb,
1352 &fixed_extension, FALSE);
1354 /* Sequence Number (10 bits) */
1355 proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_sn, tvb,
1361 /* Invalid length of sequence number */
1363 ti = proto_tree_add_text(um_header_tree, tvb, 0, 0, "Invalid sequence number length (%u bits)",
1364 p_rlc_lte_info->UMSequenceNumberLength);
1365 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
1366 "Invalid sequence number length (%u bits)",
1367 p_rlc_lte_info->UMSequenceNumberLength);
1371 tap_info->sequenceNumber = (guint16)sn;
1373 /* Show SN in info column */
1374 write_pdu_label_and_info(top_ti, NULL, pinfo, " SN=%-4u", (guint16)sn);
1376 proto_item_set_len(um_header_ti, offset-start_offset);
1379 /*************************************/
1380 /* UM header extension */
1381 if (fixed_extension) {
1382 offset = dissect_rlc_lte_extension_header(tvb, pinfo, tree, offset);
1385 if (global_rlc_lte_headers_expected) {
1386 /* There might not be any data, if only headers (plus control data) were logged */
1387 is_truncated = (tvb_length_remaining(tvb, offset) == 0);
1388 truncated_ti = proto_tree_add_uint(tree, hf_rlc_lte_header_only, tvb, 0, 0,
1391 PROTO_ITEM_SET_GENERATED(truncated_ti);
1392 expert_add_info_format(pinfo, truncated_ti, PI_SEQUENCE, PI_NOTE,
1393 "RLC PDU SDUs have been omitted");
1397 PROTO_ITEM_SET_HIDDEN(truncated_ti);
1401 /* Extract these 2 flags from framing_info */
1402 first_includes_start = ((guint8)framing_info & 0x02) == 0;
1403 last_includes_end = ((guint8)framing_info & 0x01) == 0;
1406 /* Call sequence analysis function now */
1407 if (((global_rlc_lte_um_sequence_analysis == SEQUENCE_ANALYSIS_MAC_ONLY) &&
1408 (p_get_proto_data(pinfo->fd, proto_mac_lte) != NULL)) ||
1409 ((global_rlc_lte_um_sequence_analysis == SEQUENCE_ANALYSIS_RLC_ONLY) &&
1410 (p_get_proto_data(pinfo->fd, proto_mac_lte) == NULL))) {
1412 checkChannelSequenceInfo(pinfo, tvb, p_rlc_lte_info,
1413 (guint16)sn, first_includes_start, last_includes_end,
1414 FALSE, /* UM doesn't re-segment */
1415 tap_info, um_header_tree);
1419 /*************************************/
1421 if (s_number_of_extensions > 0) {
1422 /* Show each data segment separately */
1424 for (n=0; n < s_number_of_extensions; n++) {
1425 proto_tree_add_item(tree, hf_rlc_lte_um_data, tvb, offset, s_lengths[n], FALSE);
1426 show_PDU_in_info(pinfo, top_ti, s_lengths[n],
1427 (n==0) ? first_includes_start : TRUE,
1429 tvb_ensure_bytes_exist(tvb, offset, s_lengths[n]);
1430 offset += s_lengths[n];
1434 /* Final data element */
1435 proto_tree_add_item(tree, hf_rlc_lte_um_data, tvb, offset, -1, FALSE);
1436 show_PDU_in_info(pinfo, top_ti, (guint16)tvb_length_remaining(tvb, offset),
1437 (s_number_of_extensions == 0) ? first_includes_start : TRUE,
1443 /* Dissect an AM STATUS PDU */
1444 static void dissect_rlc_lte_am_status_pdu(tvbuff_t *tvb,
1447 proto_item *status_ti,
1450 rlc_lte_info *p_rlc_lte_info,
1451 rlc_lte_tap_info *tap_info)
1454 guint64 ack_sn, nack_sn;
1455 guint16 nack_count = 0;
1456 guint64 e1 = 0, e2 = 0;
1457 guint64 so_start, so_end;
1458 int bit_offset = offset * 8;
1461 /****************************************************************/
1462 /* Part of RLC control PDU header */
1464 /* Control PDU Type (CPT) */
1465 cpt = (tvb_get_guint8(tvb, offset) & 0xf0) >> 4;
1466 ti = proto_tree_add_item(tree, hf_rlc_lte_am_cpt, tvb, offset, 1, FALSE);
1468 /* Protest and stop - only know about STATUS PDUs */
1469 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
1470 "RLC Control frame type %u not handled", cpt);
1474 /* The Status PDU itself starts 4 bits into the byte */
1478 proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_ack_sn, tvb,
1479 bit_offset, 10, &ack_sn, FALSE);
1481 write_pdu_label_and_info(top_ti, status_ti, pinfo, " ACK_SN=%-4u", (guint16)ack_sn);
1483 tap_info->ACKNo = (guint16)ack_sn;
1486 proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_e1, tvb,
1487 bit_offset, 1, &e1, FALSE);
1489 /* Skip another bit to byte-align the next bit... */
1492 /* Optional, extra fields */
1495 proto_item *nack_ti;
1497 /****************************/
1498 /* Read NACK_SN, E1, E2 */
1501 nack_ti = proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_nack_sn, tvb,
1502 bit_offset, 10, &nack_sn, FALSE);
1504 write_pdu_label_and_info(top_ti, NULL, pinfo, " NACK_SN=%-4u", (guint16)nack_sn);
1506 /* Copy into struct, but don't exceed buffer */
1507 if (nack_count < MAX_NACKs) {
1508 tap_info->NACKs[nack_count++] = (guint16)nack_sn;
1511 /* Let it get bigger than the array for accurate stats... */
1516 proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_e1, tvb,
1517 bit_offset, 1, &e1, FALSE);
1521 proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_e2, tvb,
1522 bit_offset, 1, &e2, FALSE);
1524 /* Report as expert info */
1526 expert_add_info_format(pinfo, nack_ti, PI_SEQUENCE, PI_WARN,
1527 "Status PDU reports NACK (partial) on %s for UE %u",
1528 val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
1529 p_rlc_lte_info->ueid);
1532 expert_add_info_format(pinfo, nack_ti, PI_SEQUENCE, PI_WARN,
1533 "Status PDU reports NACK on %s for UE %u",
1534 val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
1535 p_rlc_lte_info->ueid);
1542 /* Read SOstart, SOend */
1543 proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_so_start, tvb,
1544 bit_offset, 15, &so_start, FALSE);
1547 proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_so_end, tvb,
1548 bit_offset, 15, &so_end, FALSE);
1552 if ((guint16)so_end == 0x7fff) {
1553 write_pdu_label_and_info(top_ti, NULL, pinfo,
1554 " (SOstart=%u SOend=<END-OF_PDU>)",
1558 write_pdu_label_and_info(top_ti, NULL, pinfo,
1559 " (SOstart=%u SOend=%u)",
1560 (guint16)so_start, (guint16)so_end);
1563 /* Reset this flag here */
1568 if (nack_count > 0) {
1569 proto_item_append_text(status_ti, " (%u NACKs)", nack_count);
1570 tap_info->noOfNACKs = nack_count;
1573 /* Check that we've reached the end of the PDU. If not, show malformed */
1574 offset = (bit_offset+7) / 8;
1575 if (tvb_length_remaining(tvb, offset) > 0) {
1576 expert_add_info_format(pinfo, status_ti, PI_MALFORMED, PI_ERROR,
1577 "%cL %u bytes remaining after Status PDU complete",
1578 (p_rlc_lte_info->direction == DIRECTION_UPLINK) ? 'U' : 'D',
1579 tvb_length_remaining(tvb, offset));
1582 /* Set selected length of control tree */
1583 proto_item_set_len(status_ti, offset);
1585 /* Repeated NACK analysis */
1586 if (((global_rlc_lte_am_sequence_analysis == SEQUENCE_ANALYSIS_MAC_ONLY) &&
1587 (p_get_proto_data(pinfo->fd, proto_mac_lte) != NULL)) ||
1588 ((global_rlc_lte_am_sequence_analysis == SEQUENCE_ANALYSIS_RLC_ONLY) &&
1589 (p_get_proto_data(pinfo->fd, proto_mac_lte) == NULL))) {
1591 if (!is_mac_lte_frame_retx(pinfo, p_rlc_lte_info->direction)) {
1592 checkChannelRepeatedNACKInfo(pinfo, p_rlc_lte_info, tap_info, tree, tvb);
1598 /***************************************************/
1599 /* Acknowledged mode PDU */
1600 static void dissect_rlc_lte_am(tvbuff_t *tvb, packet_info *pinfo,
1603 rlc_lte_info *p_rlc_lte_info,
1605 rlc_lte_tap_info *tap_info)
1608 guint8 is_resegmented;
1610 guint8 fixed_extension;
1611 guint8 framing_info;
1612 gboolean first_includes_start;
1613 gboolean last_includes_end;
1615 proto_tree *am_header_tree;
1616 proto_item *am_header_ti;
1617 gint start_offset = offset;
1619 gboolean is_truncated;
1620 proto_item *truncated_ti;
1622 /* Hidden AM root */
1623 am_ti = proto_tree_add_string_format(tree, hf_rlc_lte_am,
1624 tvb, offset, 0, "", "AM");
1625 PROTO_ITEM_SET_HIDDEN(am_ti);
1627 /* Add AM header subtree */
1628 am_header_ti = proto_tree_add_string_format(tree, hf_rlc_lte_am_header,
1631 am_header_tree = proto_item_add_subtree(am_header_ti,
1632 ett_rlc_lte_am_header);
1634 /* First bit is Data/Control flag */
1635 is_data = (tvb_get_guint8(tvb, offset) & 0x80) >> 7;
1636 proto_tree_add_item(am_header_tree, hf_rlc_lte_am_data_control, tvb, offset, 1, FALSE);
1637 tap_info->isControlPDU = !is_data;
1640 /**********************/
1642 write_pdu_label_and_info(top_ti, NULL, pinfo, " [CONTROL]");
1644 /* Control PDUs are a completely separate format */
1645 dissect_rlc_lte_am_status_pdu(tvb, pinfo, am_header_tree, am_header_ti,
1647 p_rlc_lte_info, tap_info);
1651 /******************************/
1652 /* Data PDU fixed header */
1654 /* Re-segmentation Flag (RF) field */
1655 is_resegmented = (tvb_get_guint8(tvb, offset) & 0x40) >> 6;
1656 proto_tree_add_item(am_header_tree, hf_rlc_lte_am_rf, tvb, offset, 1, FALSE);
1657 tap_info->isResegmented = is_resegmented;
1659 write_pdu_label_and_info(top_ti, NULL, pinfo,
1660 (is_resegmented) ? " [DATA-SEGMENT]" : " [DATA]");
1663 polling = (tvb_get_guint8(tvb, offset) & 0x20) >> 5;
1664 proto_tree_add_item(am_header_tree, hf_rlc_lte_am_p, tvb, offset, 1, FALSE);
1666 write_pdu_label_and_info(top_ti, NULL, pinfo, (polling) ? " (P) " : " ");
1668 proto_item_append_text(am_header_ti, " (P) ");
1672 framing_info = (tvb_get_guint8(tvb, offset) & 0x18) >> 3;
1673 proto_tree_add_item(am_header_tree, hf_rlc_lte_am_fi, tvb, offset, 1, FALSE);
1676 fixed_extension = (tvb_get_guint8(tvb, offset) & 0x04) >> 2;
1677 proto_tree_add_item(am_header_tree, hf_rlc_lte_am_fixed_e, tvb, offset, 1, FALSE);
1679 /* Sequence Number */
1680 sn = tvb_get_ntohs(tvb, offset) & 0x03ff;
1681 proto_tree_add_item(am_header_tree, hf_rlc_lte_am_fixed_sn, tvb, offset, 2, FALSE);
1683 tap_info->sequenceNumber = sn;
1685 write_pdu_label_and_info(top_ti, am_header_ti, pinfo, "sn=%-4u", sn);
1687 /***************************************/
1688 /* Dissect extra segment header fields */
1689 if (is_resegmented) {
1690 guint16 segmentOffset;
1692 /* Last Segment Field (LSF) */
1693 proto_tree_add_item(am_header_tree, hf_rlc_lte_am_segment_lsf, tvb, offset, 1, FALSE);
1696 segmentOffset = tvb_get_ntohs(tvb, offset) & 0x7fff;
1697 proto_tree_add_item(am_header_tree, hf_rlc_lte_am_segment_so, tvb, offset, 2, FALSE);
1698 write_pdu_label_and_info(top_ti, NULL, pinfo, " SO=%u ", segmentOffset);
1702 /*************************************/
1703 /* AM header extension */
1704 if (fixed_extension) {
1705 offset = dissect_rlc_lte_extension_header(tvb, pinfo, tree, offset);
1708 /* There might not be any data, if only headers (plus control data) were logged */
1709 if (global_rlc_lte_headers_expected) {
1710 is_truncated = (tvb_length_remaining(tvb, offset) == 0);
1711 truncated_ti = proto_tree_add_uint(tree, hf_rlc_lte_header_only, tvb, 0, 0,
1714 PROTO_ITEM_SET_GENERATED(truncated_ti);
1715 expert_add_info_format(pinfo, truncated_ti, PI_SEQUENCE, PI_NOTE,
1716 "RLC PDU SDUs have been omitted");
1720 PROTO_ITEM_SET_HIDDEN(truncated_ti);
1724 /* Head is now complete */
1725 proto_item_set_len(am_header_ti, offset-start_offset);
1727 /* Extract these 2 flags from framing_info */
1728 first_includes_start = (framing_info & 0x02) == 0;
1729 last_includes_end = (framing_info & 0x01) == 0;
1732 /* Call sequence analysis function now */
1733 if (((global_rlc_lte_am_sequence_analysis == SEQUENCE_ANALYSIS_MAC_ONLY) &&
1734 (p_get_proto_data(pinfo->fd, proto_mac_lte) != NULL)) ||
1735 ((global_rlc_lte_am_sequence_analysis == SEQUENCE_ANALYSIS_RLC_ONLY) &&
1736 (p_get_proto_data(pinfo->fd, proto_mac_lte) == NULL))) {
1738 checkChannelSequenceInfo(pinfo, tvb, p_rlc_lte_info, (guint16)sn,
1739 first_includes_start, last_includes_end,
1740 is_resegmented, tap_info, tree);
1744 /*************************************/
1746 if (s_number_of_extensions > 0) {
1747 /* Show each data segment separately */
1749 for (n=0; n < s_number_of_extensions; n++) {
1750 show_AM_PDU_in_tree(pinfo, tree, tvb, offset, s_lengths[n], p_rlc_lte_info,
1751 (n==0) ? first_includes_start : TRUE);
1752 show_PDU_in_info(pinfo, top_ti, s_lengths[n],
1753 (n==0) ? first_includes_start : TRUE,
1755 tvb_ensure_bytes_exist(tvb, offset, s_lengths[n]);
1756 offset += s_lengths[n];
1760 /* Final data element */
1761 if (tvb_length_remaining(tvb, offset) > 0) {
1762 show_AM_PDU_in_tree(pinfo, tree, tvb, offset, -1, p_rlc_lte_info,
1763 ((s_number_of_extensions == 0) ? first_includes_start : TRUE) && last_includes_end);
1764 show_PDU_in_info(pinfo, top_ti, (guint16)tvb_length_remaining(tvb, offset),
1765 (s_number_of_extensions == 0) ? first_includes_start : TRUE,
1769 /* Report that expected data was missing (unless we know it might happen) */
1770 if (!global_rlc_lte_headers_expected) {
1771 if (s_number_of_extensions > 0) {
1772 expert_add_info_format(pinfo, am_header_ti, PI_MALFORMED, PI_ERROR,
1773 "AM data PDU doesn't contain any data beyond extensions");
1776 expert_add_info_format(pinfo, am_header_ti, PI_MALFORMED, PI_ERROR,
1777 "AM data PDU doesn't contain any data");
1784 /* Heuristic dissector looks for supported framing protocol (see wiki page) */
1785 static gboolean dissect_rlc_lte_heur(tvbuff_t *tvb, packet_info *pinfo,
1789 struct rlc_lte_info *p_rlc_lte_info;
1792 gboolean infoAlreadySet = FALSE;
1793 gboolean umSeqNumLengthTagPresent = FALSE;
1795 /* This is a heuristic dissector, which means we get all the UDP
1796 * traffic not sent to a known dissector and not claimed by
1797 * a heuristic dissector called before us!
1800 if (!global_rlc_lte_heur) {
1804 /* If redissecting, use previous info struct (if available) */
1805 p_rlc_lte_info = p_get_proto_data(pinfo->fd, proto_rlc_lte);
1806 if (p_rlc_lte_info == NULL) {
1807 /* Allocate new info struct for this frame */
1808 p_rlc_lte_info = se_alloc0(sizeof(struct rlc_lte_info));
1809 infoAlreadySet = FALSE;
1812 infoAlreadySet = TRUE;
1815 /* Do this again on re-dissection to re-discover offset of actual PDU */
1817 /* Needs to be at least as long as:
1818 - the signature string
1819 - fixed header bytes
1821 - at least one byte of RLC PDU payload */
1822 if ((size_t)tvb_length_remaining(tvb, offset) < (strlen(RLC_LTE_START_STRING)+1+2)) {
1826 /* OK, compare with signature string */
1827 if (tvb_strneql(tvb, offset, RLC_LTE_START_STRING, (gint)strlen(RLC_LTE_START_STRING)) != 0) {
1830 offset += (gint)strlen(RLC_LTE_START_STRING);
1832 /* Read fixed fields */
1833 p_rlc_lte_info->rlcMode = tvb_get_guint8(tvb, offset++);
1835 /* Read optional fields */
1836 while (tag != RLC_LTE_PAYLOAD_TAG) {
1837 /* Process next tag */
1838 tag = tvb_get_guint8(tvb, offset++);
1840 case RLC_LTE_UM_SN_LENGTH_TAG:
1841 p_rlc_lte_info->UMSequenceNumberLength = tvb_get_guint8(tvb, offset);
1843 umSeqNumLengthTagPresent = TRUE;
1845 case RLC_LTE_DIRECTION_TAG:
1846 p_rlc_lte_info->direction = tvb_get_guint8(tvb, offset);
1849 case RLC_LTE_PRIORITY_TAG:
1850 p_rlc_lte_info->priority = tvb_get_guint8(tvb, offset);
1853 case RLC_LTE_UEID_TAG:
1854 p_rlc_lte_info->ueid = tvb_get_ntohs(tvb, offset);
1857 case RLC_LTE_CHANNEL_TYPE_TAG:
1858 p_rlc_lte_info->channelType = tvb_get_ntohs(tvb, offset);
1861 case RLC_LTE_CHANNEL_ID_TAG:
1862 p_rlc_lte_info->channelId = tvb_get_ntohs(tvb, offset);
1866 case RLC_LTE_PAYLOAD_TAG:
1867 /* Have reached data, so set payload length and get out of loop */
1868 p_rlc_lte_info->pduLength= tvb_length_remaining(tvb, offset);
1872 /* It must be a recognised tag */
1877 if ((p_rlc_lte_info->rlcMode == RLC_UM_MODE) && (umSeqNumLengthTagPresent == FALSE)) {
1878 /* Conditional field is not present */
1882 if (!infoAlreadySet) {
1883 /* Store info in packet */
1884 p_add_proto_data(pinfo->fd, proto_rlc_lte, p_rlc_lte_info);
1887 /**************************************/
1888 /* OK, now dissect as RLC LTE */
1890 /* Create tvb that starts at actual RLC PDU */
1891 rlc_tvb = tvb_new_subset(tvb, offset, -1, tvb_reported_length(tvb)-offset);
1892 dissect_rlc_lte(rlc_tvb, pinfo, tree);
1897 /*****************************/
1898 /* Main dissection function. */
1899 /*****************************/
1901 void dissect_rlc_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1903 proto_tree *rlc_lte_tree;
1904 proto_tree *context_tree;
1906 proto_item *context_ti;
1908 proto_item *mode_ti;
1910 struct rlc_lte_info *p_rlc_lte_info = NULL;
1912 /* Allocate and Zero tap struct */
1913 rlc_lte_tap_info *tap_info = ep_alloc0(sizeof(rlc_lte_tap_info));
1915 /* Set protocol name */
1916 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC-LTE");
1918 /* Create protocol tree. */
1919 top_ti = proto_tree_add_item(tree, proto_rlc_lte, tvb, offset, -1, FALSE);
1920 rlc_lte_tree = proto_item_add_subtree(top_ti, ett_rlc_lte);
1923 /* Look for packet info! */
1924 p_rlc_lte_info = p_get_proto_data(pinfo->fd, proto_rlc_lte);
1926 /* Can't dissect anything without it... */
1927 if (p_rlc_lte_info == NULL) {
1928 ti = proto_tree_add_text(rlc_lte_tree, tvb, offset, -1,
1929 "Can't dissect LTE RLC frame because no per-frame info was attached!");
1930 PROTO_ITEM_SET_GENERATED(ti);
1934 /*****************************************/
1935 /* Show context information */
1937 /* Create context root */
1938 context_ti = proto_tree_add_string_format(rlc_lte_tree, hf_rlc_lte_context,
1939 tvb, offset, 0, "", "Context");
1940 context_tree = proto_item_add_subtree(context_ti, ett_rlc_lte_context);
1941 PROTO_ITEM_SET_GENERATED(context_ti);
1943 ti = proto_tree_add_uint(context_tree, hf_rlc_lte_context_direction,
1944 tvb, 0, 0, p_rlc_lte_info->direction);
1945 PROTO_ITEM_SET_GENERATED(ti);
1947 mode_ti = proto_tree_add_uint(context_tree, hf_rlc_lte_context_mode,
1948 tvb, 0, 0, p_rlc_lte_info->rlcMode);
1949 PROTO_ITEM_SET_GENERATED(mode_ti);
1951 if (p_rlc_lte_info->ueid != 0) {
1952 ti = proto_tree_add_uint(context_tree, hf_rlc_lte_context_ueid,
1953 tvb, 0, 0, p_rlc_lte_info->ueid);
1954 PROTO_ITEM_SET_GENERATED(ti);
1957 ti = proto_tree_add_uint(context_tree, hf_rlc_lte_context_priority,
1958 tvb, 0, 0, p_rlc_lte_info->priority);
1959 PROTO_ITEM_SET_GENERATED(ti);
1961 ti = proto_tree_add_uint(context_tree, hf_rlc_lte_context_channel_type,
1962 tvb, 0, 0, p_rlc_lte_info->channelType);
1963 PROTO_ITEM_SET_GENERATED(ti);
1965 if ((p_rlc_lte_info->channelType == CHANNEL_TYPE_SRB) ||
1966 (p_rlc_lte_info->channelType == CHANNEL_TYPE_DRB)) {
1967 ti = proto_tree_add_uint(context_tree, hf_rlc_lte_context_channel_id,
1968 tvb, 0, 0, p_rlc_lte_info->channelId);
1969 PROTO_ITEM_SET_GENERATED(ti);
1972 ti = proto_tree_add_uint(context_tree, hf_rlc_lte_context_pdu_length,
1973 tvb, 0, 0, p_rlc_lte_info->pduLength);
1974 PROTO_ITEM_SET_GENERATED(ti);
1976 if (p_rlc_lte_info->rlcMode == RLC_UM_MODE) {
1977 ti = proto_tree_add_uint(context_tree, hf_rlc_lte_context_um_sn_length,
1978 tvb, 0, 0, p_rlc_lte_info->UMSequenceNumberLength);
1979 PROTO_ITEM_SET_GENERATED(ti);
1982 /* Append highlights to top-level item */
1983 if (p_rlc_lte_info->ueid != 0) {
1984 proto_item_append_text(top_ti, " UEId=%u", p_rlc_lte_info->ueid);
1987 if (p_rlc_lte_info->channelId == 0) {
1988 proto_item_append_text(top_ti, " (%s) ",
1989 val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"));
1992 proto_item_append_text(top_ti, " (%s:%u) ",
1993 val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
1994 p_rlc_lte_info->channelId);
1996 proto_item_append_text(top_ti, "[%s] ",
1997 val_to_str_const(p_rlc_lte_info->rlcMode, rlc_mode_short_vals, "Unknown"));
2000 /* Append context highlights to info column */
2001 write_pdu_label_and_info(top_ti, NULL, pinfo,
2003 (p_rlc_lte_info->direction == 0) ? "UL" : "DL",
2004 val_to_str_const(p_rlc_lte_info->rlcMode, rlc_mode_short_vals, "Unknown"));
2005 if (p_rlc_lte_info->ueid != 0) {
2006 col_append_fstr(pinfo->cinfo, COL_INFO, "UEId=%u ", p_rlc_lte_info->ueid);
2008 if (p_rlc_lte_info->channelId == 0) {
2009 write_pdu_label_and_info(top_ti, NULL, pinfo, "%s",
2010 val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"));
2013 write_pdu_label_and_info(top_ti, NULL, pinfo, "%s:%-2u",
2014 val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
2015 p_rlc_lte_info->channelId);
2018 /* Set context-info parts of tap struct */
2019 tap_info->rlcMode = p_rlc_lte_info->rlcMode;
2020 tap_info->direction = p_rlc_lte_info->direction;
2021 tap_info->priority = p_rlc_lte_info->priority;
2022 tap_info->ueid = p_rlc_lte_info->ueid;
2023 tap_info->channelType = p_rlc_lte_info->channelType;
2024 tap_info->channelId = p_rlc_lte_info->channelId;
2025 tap_info->pduLength = p_rlc_lte_info->pduLength;
2026 tap_info->UMSequenceNumberLength = p_rlc_lte_info->UMSequenceNumberLength;
2027 tap_info->loggedInMACFrame = (p_get_proto_data(pinfo->fd, proto_mac_lte) != NULL);
2029 /* Reset this count */
2030 s_number_of_extensions = 0;
2032 /* Dissect the RLC PDU itself. Format depends upon mode... */
2033 switch (p_rlc_lte_info->rlcMode) {
2036 dissect_rlc_lte_tm(tvb, pinfo, rlc_lte_tree, offset, p_rlc_lte_info, top_ti);
2040 dissect_rlc_lte_um(tvb, pinfo, rlc_lte_tree, offset, p_rlc_lte_info, top_ti,
2045 dissect_rlc_lte_am(tvb, pinfo, rlc_lte_tree, offset, p_rlc_lte_info, top_ti,
2050 /* Predefined data (i.e. not containing a valid RLC header */
2051 proto_tree_add_item(rlc_lte_tree, hf_rlc_lte_predefined_pdu, tvb, offset, -1, FALSE);
2052 write_pdu_label_and_info(top_ti, NULL, pinfo, " [%u-bytes]",
2053 tvb_length_remaining(tvb, offset));
2057 /* Error - unrecognised mode */
2058 expert_add_info_format(pinfo, mode_ti, PI_MALFORMED, PI_ERROR,
2059 "Unrecognised RLC Mode set (%u)", p_rlc_lte_info->rlcMode);
2063 /* Queue tap info */
2064 tap_queue_packet(rlc_lte_tap, pinfo, tap_info);
2069 /* Initializes the hash table and the mem_chunk area each time a new
2070 * file is loaded or re-loaded in wireshark */
2072 rlc_lte_init_protocol(void)
2074 /* Destroy any existing hashes. */
2075 if (rlc_lte_sequence_analysis_channel_hash) {
2076 g_hash_table_destroy(rlc_lte_sequence_analysis_channel_hash);
2078 if (rlc_lte_frame_sequence_analysis_report_hash) {
2079 g_hash_table_destroy(rlc_lte_frame_sequence_analysis_report_hash);
2081 if (rlc_lte_repeated_nack_channel_hash) {
2082 g_hash_table_destroy(rlc_lte_repeated_nack_channel_hash);
2084 if (rlc_lte_frame_repeated_nack_report_hash) {
2085 g_hash_table_destroy(rlc_lte_frame_repeated_nack_report_hash);
2089 /* Now create them over */
2090 rlc_lte_sequence_analysis_channel_hash = g_hash_table_new(rlc_channel_hash_func, rlc_channel_equal);
2091 rlc_lte_frame_sequence_analysis_report_hash = g_hash_table_new(rlc_frame_hash_func, rlc_frame_equal);
2093 rlc_lte_repeated_nack_channel_hash = g_hash_table_new(rlc_channel_hash_func, rlc_channel_equal);
2094 rlc_lte_frame_repeated_nack_report_hash = g_hash_table_new(rlc_frame_hash_func, rlc_frame_equal);
2100 void proto_register_rlc_lte(void)
2102 static hf_register_info hf[] =
2104 /**********************************/
2105 /* Items for decoding context */
2106 { &hf_rlc_lte_context,
2108 "rlc-lte.context", FT_STRING, BASE_NONE, NULL, 0x0,
2112 { &hf_rlc_lte_context_mode,
2114 "rlc-lte.mode", FT_UINT8, BASE_DEC, VALS(rlc_mode_vals), 0x0,
2118 { &hf_rlc_lte_context_direction,
2120 "rlc-lte.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
2121 "Direction of message", HFILL
2124 { &hf_rlc_lte_context_priority,
2126 "rlc-lte.priority", FT_UINT8, BASE_DEC, 0, 0x0,
2130 { &hf_rlc_lte_context_ueid,
2132 "rlc-lte.ueid", FT_UINT16, BASE_DEC, 0, 0x0,
2133 "User Equipment Identifier associated with message", HFILL
2136 { &hf_rlc_lte_context_channel_type,
2138 "rlc-lte.channel-type", FT_UINT16, BASE_DEC, VALS(rlc_channel_type_vals), 0x0,
2139 "Channel Type associated with message", HFILL
2142 { &hf_rlc_lte_context_channel_id,
2144 "rlc-lte.channel-id", FT_UINT16, BASE_DEC, 0, 0x0,
2145 "Channel ID associated with message", HFILL
2148 { &hf_rlc_lte_context_pdu_length,
2150 "rlc-lte.pdu_length", FT_UINT16, BASE_DEC, 0, 0x0,
2151 "Length of PDU (in bytes)", HFILL
2154 { &hf_rlc_lte_context_um_sn_length,
2155 { "UM Sequence number length",
2156 "rlc-lte.um-seqnum-length", FT_UINT8, BASE_DEC, 0, 0x0,
2157 "Length of UM sequence number in bits", HFILL
2162 /* Transparent mode fields */
2165 "rlc-lte.tm", FT_STRING, BASE_NONE, NULL, 0x0,
2166 "Transparent Mode", HFILL
2169 { &hf_rlc_lte_tm_data,
2171 "rlc-lte.tm.data", FT_BYTES, BASE_NONE, 0, 0x0,
2172 "Transparent Mode Data", HFILL
2176 /* Unacknowledged mode fields */
2179 "rlc-lte.um", FT_STRING, BASE_NONE, NULL, 0x0,
2180 "Unackowledged Mode", HFILL
2183 { &hf_rlc_lte_um_header,
2185 "rlc-lte.um.header", FT_STRING, BASE_NONE, NULL, 0x0,
2186 "Unackowledged Mode Header", HFILL
2189 { &hf_rlc_lte_um_fi,
2191 "rlc-lte.um.fi", FT_UINT8, BASE_HEX, VALS(framing_info_vals), 0x0,
2195 { &hf_rlc_lte_um_fixed_e,
2197 "rlc-lte.um.fixed.e", FT_UINT8, BASE_HEX, VALS(fixed_extension_vals), 0x0,
2198 "Extension in fixed part of UM header", HFILL
2201 { &hf_rlc_lte_um_sn,
2202 { "Sequence number",
2203 "rlc-lte.um.sn", FT_UINT8, BASE_DEC, 0, 0x0,
2204 "Unacknowledged Mode Sequence Number", HFILL
2207 { &hf_rlc_lte_um_fixed_reserved,
2209 "rlc-lte.um.reserved", FT_UINT8, BASE_DEC, 0, 0xe0,
2210 "Unacknowledged Mode Fixed header reserved bits", HFILL
2213 { &hf_rlc_lte_um_data,
2215 "rlc-lte.um.data", FT_BYTES, BASE_NONE, 0, 0x0,
2216 "Unacknowledged Mode Data", HFILL
2219 { &hf_rlc_lte_extension_part,
2221 "rlc-lte.extension-part", FT_STRING, BASE_NONE, 0, 0x0,
2227 { &hf_rlc_lte_extension_e,
2229 "rlc-lte.extension.e", FT_UINT8, BASE_HEX, VALS(extension_extension_vals), 0x0,
2230 "Extension in extended part of the header", HFILL
2233 { &hf_rlc_lte_extension_li,
2234 { "Length Indicator",
2235 "rlc-lte.extension.li", FT_UINT16, BASE_DEC, 0, 0x0,
2239 { &hf_rlc_lte_extension_padding,
2241 "rlc-lte.extension.padding", FT_UINT8, BASE_HEX, 0, 0x0f,
2242 "Extension header padding", HFILL
2248 "rlc-lte.am", FT_STRING, BASE_NONE, NULL, 0x0,
2249 "Ackowledged Mode", HFILL
2252 { &hf_rlc_lte_am_header,
2254 "rlc-lte.am.header", FT_STRING, BASE_NONE, NULL, 0x0,
2255 "Ackowledged Mode Header", HFILL
2258 { &hf_rlc_lte_am_data_control,
2260 "rlc-lte.am.frame_type", FT_UINT8, BASE_HEX, VALS(data_or_control_vals), 0x80,
2261 "AM Frame Type (Control or Data)", HFILL
2264 { &hf_rlc_lte_am_rf,
2265 { "Re-segmentation Flag",
2266 "rlc-lte.am.rf", FT_UINT8, BASE_HEX, VALS(resegmentation_flag_vals), 0x40,
2267 "AM Re-segmentation Flag", HFILL
2272 "rlc-lte.am.p", FT_UINT8, BASE_HEX, VALS(polling_bit_vals), 0x20,
2276 { &hf_rlc_lte_am_fi,
2278 "rlc-lte.am.fi", FT_UINT8, BASE_HEX, VALS(framing_info_vals), 0x18,
2279 "AM Framing Info", HFILL
2282 { &hf_rlc_lte_am_fixed_e,
2284 "rlc-lte.am.fixed.e", FT_UINT8, BASE_HEX, VALS(fixed_extension_vals), 0x04,
2285 "Fixed Extension Bit", HFILL
2288 { &hf_rlc_lte_am_fixed_sn,
2289 { "Sequence Number",
2290 "rlc-lte.am.fixed.sn", FT_UINT16, BASE_DEC, 0, 0x03ff,
2291 "AM Fixed Sequence Number", HFILL
2294 { &hf_rlc_lte_am_segment_lsf,
2295 { "Last Segment Flag",
2296 "rlc-lte.am.segment.lsf", FT_UINT8, BASE_HEX, VALS(lsf_vals), 0x80,
2300 { &hf_rlc_lte_am_segment_so,
2302 "rlc-lte.am.segment.offset", FT_UINT16, BASE_DEC, 0, 0x7fff,
2306 { &hf_rlc_lte_am_data,
2308 "rlc-lte.am.data", FT_BYTES, BASE_NONE, 0, 0x0,
2309 "Acknowledged Mode Data", HFILL
2314 { &hf_rlc_lte_am_cpt,
2315 { "Control PDU Type",
2316 "rlc-lte.am.cpt", FT_UINT8, BASE_HEX, VALS(control_pdu_type_vals), 0x70,
2317 "AM Control PDU Type", HFILL
2320 { &hf_rlc_lte_am_ack_sn,
2321 { "ACK Sequence Number",
2322 "rlc-lte.am.ack-sn", FT_UINT16, BASE_DEC, 0, 0x0,
2323 "Sequence Number we expect to receive next", HFILL
2326 { &hf_rlc_lte_am_e1,
2327 { "Extension bit 1",
2328 "rlc-lte.am.e1", FT_UINT8, BASE_HEX, VALS(am_e1_vals), 0x0,
2332 { &hf_rlc_lte_am_e2,
2333 { "Extension bit 2",
2334 "rlc-lte.am.e2", FT_UINT8, BASE_HEX, VALS(am_e2_vals), 0x0,
2338 { &hf_rlc_lte_am_nack_sn,
2339 { "NACK Sequence Number",
2340 "rlc-lte.am.nack-sn", FT_UINT16, BASE_DEC, 0, 0x0,
2341 "Negative Acknowledgement Sequence Number", HFILL
2344 { &hf_rlc_lte_am_so_start,
2346 "rlc-lte.am.so-start", FT_UINT16, BASE_DEC, 0, 0x0,
2350 { &hf_rlc_lte_am_so_end,
2352 "rlc-lte.am.so-end", FT_UINT16, BASE_DEC, 0, 0x0,
2357 { &hf_rlc_lte_predefined_pdu,
2358 { "Predefined data",
2359 "rlc-lte.predefined-data", FT_BYTES, BASE_NONE, 0, 0x0,
2360 "Predefined test data", HFILL
2364 { &hf_rlc_lte_sequence_analysis,
2365 { "Sequence Analysis",
2366 "rlc-lte.sequence-analysis", FT_STRING, BASE_NONE, 0, 0x0,
2370 { &hf_rlc_lte_sequence_analysis_ok,
2372 "rlc-lte.sequence-analysis.ok", FT_BOOLEAN, BASE_NONE, 0, 0x0,
2376 { &hf_rlc_lte_sequence_analysis_previous_frame,
2377 { "Previous frame for channel",
2378 "rlc-lte.sequence-analysis.previous-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
2382 { &hf_rlc_lte_sequence_analysis_expected_sn,
2384 "rlc-lte.sequence-analysis.expected-sn", FT_UINT16, BASE_DEC, 0, 0x0,
2388 { &hf_rlc_lte_sequence_analysis_framing_info_correct,
2389 { "Frame info continued correctly",
2390 "rlc-lte.sequence-analysis.framing-info-correct", FT_BOOLEAN, BASE_NONE, 0, 0x0,
2394 { &hf_rlc_lte_sequence_analysis_mac_retx,
2395 { "Frame retransmitted by MAC",
2396 "rlc-lte.sequence-analysis.mac-retx", FT_BOOLEAN, BASE_NONE, 0, 0x0,
2400 { &hf_rlc_lte_sequence_analysis_retx,
2401 { "Retransmitted frame",
2402 "rlc-lte.sequence-analysis.retx", FT_BOOLEAN, BASE_NONE, 0, 0x0,
2406 { &hf_rlc_lte_sequence_analysis_skipped,
2408 "rlc-lte.sequence-analysis.skipped-frames", FT_BOOLEAN, BASE_NONE, 0, 0x0,
2412 { &hf_rlc_lte_sequence_analysis_repeated,
2414 "rlc-lte.sequence-analysis.repeated-frame", FT_BOOLEAN, BASE_NONE, 0, 0x0,
2418 { &hf_rlc_lte_sequence_analysis_repeated_nack,
2420 "rlc-lte.sequence-analysis.repeated-nack", FT_UINT16, BASE_DEC, 0, 0x0,
2425 { &hf_rlc_lte_header_only,
2426 { "RLC PDU Header only",
2427 "rlc-lte.header-only", FT_UINT8, BASE_DEC, VALS(header_only_vals), 0x0,
2433 static gint *ett[] =
2436 &ett_rlc_lte_context,
2437 &ett_rlc_lte_um_header,
2438 &ett_rlc_lte_am_header,
2439 &ett_rlc_lte_extension_part,
2440 &ett_rlc_lte_sequence_analysis
2443 static enum_val_t sequence_analysis_vals[] = {
2444 {"no-analysis", "No-Analysis", FALSE},
2445 {"mac-only", "Only-MAC-frames", SEQUENCE_ANALYSIS_MAC_ONLY},
2446 {"rlc-only", "Only-RLC-frames", SEQUENCE_ANALYSIS_RLC_ONLY},
2450 module_t *rlc_lte_module;
2452 /* Register protocol. */
2453 proto_rlc_lte = proto_register_protocol("RLC-LTE", "RLC-LTE", "rlc-lte");
2454 proto_register_field_array(proto_rlc_lte, hf, array_length(hf));
2455 proto_register_subtree_array(ett, array_length(ett));
2457 /* Allow other dissectors to find this one by name. */
2458 register_dissector("rlc-lte", dissect_rlc_lte, proto_rlc_lte);
2460 /* Register the tap name */
2461 rlc_lte_tap = register_tap("rlc-lte");
2464 rlc_lte_module = prefs_register_protocol(proto_rlc_lte, NULL);
2466 prefs_register_enum_preference(rlc_lte_module, "do_sequence_analysis_am",
2467 "Do sequence analysis for AM channels",
2468 "Attempt to keep track of PDUs for AM channels, and point out problems",
2469 &global_rlc_lte_am_sequence_analysis, sequence_analysis_vals, FALSE);
2471 prefs_register_enum_preference(rlc_lte_module, "do_sequence_analysis",
2472 "Do sequence analysis for UM channels",
2473 "Attempt to keep track of PDUs for UM channels, and point out problems",
2474 &global_rlc_lte_um_sequence_analysis, sequence_analysis_vals, FALSE);
2476 prefs_register_bool_preference(rlc_lte_module, "call_pdcp_for_srb",
2477 "Call PDCP dissector for SRB PDUs",
2478 "Call PDCP dissector for signalling PDUs. Note that without reassembly, it can"
2479 "only be called for complete PDus (i.e. not segmented over RLC)",
2480 &global_rlc_lte_call_pdcp_for_srb);
2482 prefs_register_enum_preference(rlc_lte_module, "call_pdcp_for_drb",
2483 "Call PDCP dissector for DRB PDUs",
2484 "Call PDCP dissector for user-plane PDUs. Note that without reassembly, it can"
2485 "only be called for complete PDus (i.e. not segmented over RLC)",
2486 &global_rlc_lte_call_pdcp_for_drb, pdcp_drb_col_vals, FALSE);
2489 prefs_register_bool_preference(rlc_lte_module, "call_rrc_for_ccch",
2490 "Call RRC dissector for CCCH PDUs",
2491 "Call RRC dissector for CCCH PDUs",
2492 &global_rlc_lte_call_rrc);
2494 prefs_register_bool_preference(rlc_lte_module, "heuristic_rlc_lte_over_udp",
2495 "Try Heuristic LTE-RLC over UDP framing",
2496 "When enabled, use heuristic dissector to find RLC-LTE frames sent with "
2498 &global_rlc_lte_heur);
2500 prefs_register_bool_preference(rlc_lte_module, "header_only_mode",
2501 "May see RLC headers only",
2502 "When enabled, if data is not present, don't report as an error, but instead "
2503 "add expert info to indicate that headers were ommitted",
2504 &global_rlc_lte_headers_expected);
2506 register_init_routine(&rlc_lte_init_protocol);
2510 proto_reg_handoff_rlc_lte(void)
2512 static dissector_handle_t rlc_lte_handle;
2513 if (!rlc_lte_handle) {
2514 rlc_lte_handle = find_dissector("rlc-lte");
2516 /* Add as a heuristic UDP dissector */
2517 heur_dissector_add("udp", dissect_rlc_lte_heur, proto_rlc_lte);