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.
30 #include <epan/packet.h>
31 #include <epan/expert.h>
33 #include "packet-rlc-lte.h"
37 * 3GPP TS 36.322 Evolved Universal Terrestial Radio Access (E-UTRA)
38 * Radio Link Control (RLC) Protocol specification
41 /* Initialize the protocol and registered fields. */
42 int proto_rlc_lte = -1;
44 /* Decoding context */
45 static int hf_rlc_lte_context_mode = -1;
46 static int hf_rlc_lte_context_direction = -1;
47 static int hf_rlc_lte_context_priority = -1;
48 static int hf_rlc_lte_context_ueid = -1;
49 static int hf_rlc_lte_context_channel_type = -1;
50 static int hf_rlc_lte_context_channel_id = -1;
51 static int hf_rlc_lte_context_pdu_length = -1;
52 static int hf_rlc_lte_context_um_sn_length = -1;
54 /* Transparent mode fields */
55 static int hf_rlc_lte_tm_data = -1;
57 /* Unacknowledged mode fields */
58 static int hf_rlc_lte_um_header = -1;
59 static int hf_rlc_lte_um_fi = -1;
60 static int hf_rlc_lte_um_fixed_e = -1;
61 static int hf_rlc_lte_um_sn = -1;
62 static int hf_rlc_lte_um_fixed_reserved = -1;
63 static int hf_rlc_lte_um_data = -1;
64 static int hf_rlc_lte_extension_part = -1;
66 /* Extended header (common to UM and AM) */
67 static int hf_rlc_lte_extension_e = -1;
68 static int hf_rlc_lte_extension_li = -1;
69 static int hf_rlc_lte_extension_padding = -1;
72 /* Acknowledged mode fields */
73 static int hf_rlc_lte_am_header = -1;
74 static int hf_rlc_lte_am_data_control = -1;
75 static int hf_rlc_lte_am_rf = -1;
76 static int hf_rlc_lte_am_p = -1;
77 static int hf_rlc_lte_am_fi = -1;
78 static int hf_rlc_lte_am_fixed_e = -1;
79 static int hf_rlc_lte_am_fixed_sn = -1;
80 static int hf_rlc_lte_am_segment_lsf = -1;
81 static int hf_rlc_lte_am_segment_so = -1;
82 static int hf_rlc_lte_am_data = -1;
85 static int hf_rlc_lte_am_cpt = -1;
86 static int hf_rlc_lte_am_ack_sn = -1;
87 static int hf_rlc_lte_am_e1 = -1;
88 static int hf_rlc_lte_am_e2 = -1;
89 static int hf_rlc_lte_am_nack_sn = -1;
90 static int hf_rlc_lte_am_so_start = -1;
91 static int hf_rlc_lte_am_so_end = -1;
94 static int ett_rlc_lte = -1;
95 static int ett_rlc_lte_um_header = -1;
96 static int ett_rlc_lte_am_header = -1;
97 static int ett_rlc_lte_extension_part = -1;
100 static const value_string direction_vals[] =
108 #define RLC_TM_MODE 1
109 #define RLC_UM_MODE 2
110 #define RLC_AM_MODE 3
113 static const value_string rlc_mode_short_vals[] =
115 { RLC_TM_MODE, "TM"},
116 { RLC_UM_MODE, "UM"},
117 { RLC_AM_MODE, "AM"},
121 static const value_string rlc_mode_vals[] =
123 { RLC_TM_MODE, "Transparent Mode"},
124 { RLC_UM_MODE, "Unacknowledged Mode"},
125 { RLC_AM_MODE, "Acknowledged Mode"},
130 static const value_string rlc_channel_type_vals[] =
141 static const value_string framing_info_vals[] =
143 { 0, "First byte begins an RLC SDU and last byte ends an RLC SDU"},
144 { 1, "First byte begins an RLC SDU and last byte does not end an RLC SDU"},
145 { 2, "First byte does not begin an RLC SDU and last byte ends an RLC SDU"},
146 { 3, "First byte does not begin an RLC SDU and last byte does not end an RLC SDU"},
150 static const value_string fixed_extension_vals[] =
152 { 0, "Data field follows from the octet following the fixed part of the header"},
153 { 1, "A set of E field and LI field follows from the octet following the fixed part of the header"},
157 static const value_string extension_extension_vals[] =
159 { 0, "Data field follows from the octet following the LI field following this E field"},
160 { 1, "A set of E field and LI field follows from the bit following the LI field following this E field"},
164 static const value_string data_or_control_vals[] =
171 static const value_string resegmentation_flag_vals[] =
174 { 1, "AND PDU segment"},
178 static const value_string polling_bit_vals[] =
180 { 0, "Status report not requested"},
181 { 1, "Status report is requested"},
186 static const value_string lsf_vals[] =
188 { 0, "Last byte of the AMD PDU segment does not correspond to the last byte of an AMD PDU"},
189 { 1, "Last byte of the AMD PDU segment corresponds to the last byte of an AND PDU"},
194 static const value_string control_pdu_type_vals[] =
200 static const value_string am_e1_vals[] =
202 { 0, "A set of NACK_SN, E1 and E2 does not follow"},
203 { 1, "A set of NACK_SN, E1 and E2 follows"},
207 static const value_string am_e2_vals[] =
209 { 0, "A set of SOstart and SOend does not follow for this NACK_SN"},
210 { 1, "A set of SOstart and SOend follows for this NACK_SN"},
214 /* These are for keeping track of UM/AM extension headers, and the lengths found
216 guint8 s_number_of_extensions = 0;
217 #define MAX_RLC_SDUS 64
218 guint16 s_lengths[MAX_RLC_SDUS];
221 /* Dissect extension headers (common to both UM and AM) */
222 static int dissect_rlc_lte_extension_header(tvbuff_t *tvb, packet_info *pinfo,
227 guint64 extension = 1;
230 /* Reset this count */
231 s_number_of_extensions = 0;
233 while (extension && (s_number_of_extensions < MAX_RLC_SDUS)) {
234 proto_tree *extension_part_tree;
235 proto_item *extension_part_ti;
237 isOdd = (s_number_of_extensions % 2);
239 /* Extension part subtree */
240 extension_part_ti = proto_tree_add_string_format(tree,
241 hf_rlc_lte_extension_part,
245 extension_part_tree = proto_item_add_subtree(extension_part_ti,
246 ett_rlc_lte_extension_part);
248 /* Read next extension */
249 proto_tree_add_bits_ret_val(extension_part_tree, hf_rlc_lte_extension_e, tvb,
250 (offset*8) + ((isOdd) ? 4 : 0),
254 /* Read length field */
255 proto_tree_add_bits_ret_val(extension_part_tree, hf_rlc_lte_extension_li, tvb,
256 (offset*8) + ((isOdd) ? 5 : 1),
260 proto_item_append_text(extension_part_tree, " (length=%u)", (guint16)length);
262 /* Move on to byte of next extension */
269 s_lengths[s_number_of_extensions++] = (guint16)length;
272 /* May need to skip padding after last extension part */
273 isOdd = (s_number_of_extensions % 2);
278 padding = tvb_get_guint8(tvb, offset) & 0x0f;
279 ti = proto_tree_add_item(tree, hf_rlc_lte_extension_padding,
280 tvb, offset, 1, FALSE);
282 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
283 "Extension Header padding not zero (found 0x%x)", padding);
292 /* Show in the info column how many bytes are in the UM/AM PDU, and indicate
293 whether or not the beginning and end are included in this packet */
294 static void show_PDU_in_info(packet_info *pinfo,
296 guint8 first_includes_start,
297 guint8 last_includes_end)
299 /* Reflect this PDU in the info column */
300 if (check_col(pinfo->cinfo, COL_INFO)) {
301 col_append_fstr(pinfo->cinfo, COL_INFO, " %s%u-bytes%s",
302 (first_includes_start) ? "[" : "..",
304 (last_includes_end) ? "]" : "..");
309 /***************************************************/
310 /* Unacknowledged mode PDU */
311 static void dissect_rlc_lte_um(tvbuff_t *tvb, packet_info *pinfo,
314 rlc_lte_info *p_rlc_lte_info)
316 guint64 framing_info;
317 guint8 first_includes_start;
318 guint8 last_includes_end;
319 guint64 fixed_extension;
321 gint start_offset = offset;
322 proto_tree *um_header_tree;
323 proto_item *um_header_ti;
325 /* Add UM header subtree */
326 um_header_ti = proto_tree_add_string_format(tree,
327 hf_rlc_lte_um_header,
331 um_header_tree = proto_item_add_subtree(um_header_ti,
332 ett_rlc_lte_um_header);
335 /*******************************/
336 /* Fixed UM header */
337 if (p_rlc_lte_info->UMSequenceNumberLength == 5) {
338 /* Framing info (2 bits) */
339 proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_fi,
341 &framing_info, FALSE);
343 /* Extension (1 bit) */
344 proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_fixed_e, tvb,
346 &fixed_extension, FALSE);
348 /* Sequence Number (5 bit) */
349 proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_sn, tvb,
354 else if (p_rlc_lte_info->UMSequenceNumberLength == 10) {
358 /* Check 3 Reserved bits */
359 reserved = (tvb_get_guint8(tvb, offset) & 0xe0) >> 5;
360 ti = proto_tree_add_item(um_header_tree, hf_rlc_lte_um_fixed_reserved, tvb, offset, 1, FALSE);
362 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
363 "RLC UM Fixed header Reserved bits not zero (found 0x%x)", reserved);
366 /* Framing info (2 bits) */
367 proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_fi,
368 tvb, (offset*8)+3, 2,
369 &framing_info, FALSE);
371 /* Extension (1 bit) */
372 proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_fixed_e, tvb,
374 &fixed_extension, FALSE);
376 /* Sequence Number (10 bits) */
377 proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_sn, tvb,
383 /* Invalid length of sequence number */
385 ti = proto_tree_add_text(um_header_tree, tvb, 0, 0, "Invalid sequence number length (%u bits)",
386 p_rlc_lte_info->UMSequenceNumberLength);
387 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
388 "Invalid sequence number length (%u bits)",
389 p_rlc_lte_info->UMSequenceNumberLength);
393 /* Show SN in info column */
394 if (check_col(pinfo->cinfo, COL_INFO)) {
395 col_append_fstr(pinfo->cinfo, COL_INFO, " SN=%04u",
399 /* Show SN in UM header root */
400 proto_item_append_text(um_header_ti, " (SN=%u)", (guint16)sn);
401 proto_item_set_len(um_header_ti, offset-start_offset);
404 /*************************************/
405 /* UM header extension */
406 if (fixed_extension) {
407 offset = dissect_rlc_lte_extension_header(tvb, pinfo, tree, offset);
411 /* Extract these 2 flags from framing_info */
412 first_includes_start = ((guint8)framing_info & 0x02) == 0;
413 last_includes_end = ((guint8)framing_info & 0x01) == 0;
416 /*************************************/
418 if (s_number_of_extensions > 0) {
419 /* Show each data segment separately */
421 for (n=0; n < s_number_of_extensions; n++) {
422 proto_tree_add_item(tree, hf_rlc_lte_um_data, tvb, offset, s_lengths[n], FALSE);
423 show_PDU_in_info(pinfo, s_lengths[n],
424 (n==0) ? first_includes_start : TRUE,
426 offset += s_lengths[n];
430 /* Final data element */
431 proto_tree_add_item(tree, hf_rlc_lte_um_data, tvb, offset, -1, FALSE);
432 show_PDU_in_info(pinfo, tvb_length_remaining(tvb, offset),
433 (s_number_of_extensions == 0) ? first_includes_start : TRUE,
440 /* Dissect an AM STATUS PDU */
441 static void dissect_rlc_lte_am_status_pdu(tvbuff_t *tvb, packet_info *pinfo,
446 guint64 ack_sn, nack_sn;
447 guint64 e1 = 0, e2 = 0;
448 guint64 so_start, so_end;
449 int bit_offset = offset * 8;
452 /****************************************************************/
453 /* Part of RLC control PDU header */
455 /* Control PDU Type (CPT) */
456 cpt = (tvb_get_guint8(tvb, offset) & 0xf0) >> 4;
457 ti = proto_tree_add_item(tree, hf_rlc_lte_am_cpt, tvb, offset, 1, FALSE);
459 /* Protest and stop - only know about STATUS PDUs */
460 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
461 "RLC Control frame type %u not handled", cpt);
466 /*****************************************************************/
469 /* The PDU itself starts 4 bits into the byte */
473 proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_ack_sn, tvb,
474 bit_offset, 10, &ack_sn, FALSE);
478 proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_e1, tvb,
479 bit_offset, 1, &e1, FALSE);
481 /* Skip another bit to byte-align the next bit... */
484 /* Optional, extra fields */
487 /****************************/
488 /* Read NACK_SN, E1, E2 */
491 proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_nack_sn, tvb,
492 bit_offset, 10, &nack_sn, FALSE);
496 proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_e1, tvb,
497 bit_offset, 1, &e1, FALSE);
501 proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_e2, tvb,
502 bit_offset, 1, &e2, FALSE);
505 /* Reset this flag here */
509 /* Read SOstart, SOend */
510 proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_so_start, tvb,
511 bit_offset, 15, &so_start, FALSE);
514 proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_so_end, tvb,
515 bit_offset, 15, &so_end, FALSE);
518 /* Reset this flag here */
526 /***************************************************/
527 /* Acknowledged mode PDU */
528 static void dissect_rlc_lte_am(tvbuff_t *tvb, packet_info *pinfo,
534 guint8 fixed_extension;
536 guint8 first_includes_start;
537 guint8 last_includes_end;
538 proto_tree *am_header_tree;
539 proto_item *am_header_ti;
540 gint start_offset = offset;
543 /* Add UM header subtree */
544 am_header_ti = proto_tree_add_string_format(tree,
545 hf_rlc_lte_am_header,
549 am_header_tree = proto_item_add_subtree(am_header_ti,
550 ett_rlc_lte_am_header);
553 /*******************************************/
554 /* First bit is Data/Control flag */
555 is_data = (tvb_get_guint8(tvb, offset) & 0x80) >> 7;
556 proto_tree_add_item(am_header_tree, hf_rlc_lte_am_data_control, tvb, offset, 1, FALSE);
557 if (check_col(pinfo->cinfo, COL_INFO)) {
558 col_append_str(pinfo->cinfo, COL_INFO, (is_data) ? " [DATA]" : " [CONTROL]");
562 /**************************************************/
563 /* Control PDUs are a completely separate format */
565 dissect_rlc_lte_am_status_pdu(tvb, pinfo, am_header_tree, offset);
570 /******************************/
571 /* Data PDU fixed header */
573 /* Re-segmentation Flag (RF) field */
574 is_segment = (tvb_get_guint8(tvb, offset) & 0x40) >> 6;
575 proto_tree_add_item(am_header_tree, hf_rlc_lte_am_rf, tvb, offset, 1, FALSE);
578 proto_tree_add_item(am_header_tree, hf_rlc_lte_am_p, tvb, offset, 1, FALSE);
581 framing_info = (tvb_get_guint8(tvb, offset) & 0x18) >> 3;
582 proto_tree_add_item(am_header_tree, hf_rlc_lte_am_fi, tvb, offset, 1, FALSE);
585 fixed_extension = (tvb_get_guint8(tvb, offset) & 0x04) >> 2;
586 proto_tree_add_item(am_header_tree, hf_rlc_lte_am_fixed_e, tvb, offset, 1, FALSE);
588 /* Sequence Number */
589 sn = tvb_get_ntohs(tvb, offset) & 0x03ff;
590 proto_tree_add_item(am_header_tree, hf_rlc_lte_am_fixed_sn, tvb, offset, 2, FALSE);
594 /* Show SN in AM header root */
595 proto_item_append_text(am_header_ti, " (SN=%u)", sn);
596 proto_item_set_len(am_header_ti, offset-start_offset);
598 /***************************************/
599 /* Dissect extra segment header fields */
601 /* Last Segment Field (LSF) */
602 proto_tree_add_item(am_header_tree, hf_rlc_lte_am_segment_lsf, tvb, offset, 1, FALSE);
605 proto_tree_add_item(am_header_tree, hf_rlc_lte_am_segment_so, tvb, offset, 2, FALSE);
610 /*************************************/
611 /* AM header extension */
612 if (fixed_extension) {
613 offset = dissect_rlc_lte_extension_header(tvb, pinfo, tree, offset);
617 /* Extract these 2 flags from framing_info */
618 first_includes_start = (framing_info & 0x02) == 0;
619 last_includes_end = (framing_info & 0x01) == 0;
622 /*************************************/
624 if (s_number_of_extensions > 0) {
625 /* Show each data segment separately */
627 for (n=0; n < s_number_of_extensions; n++) {
628 proto_tree_add_item(tree, hf_rlc_lte_am_data, tvb, offset, s_lengths[n], FALSE);
629 show_PDU_in_info(pinfo, s_lengths[n],
630 (n==0) ? first_includes_start : TRUE,
632 offset += s_lengths[n];
636 /* Final data element */
637 proto_tree_add_item(tree, hf_rlc_lte_am_data, tvb, offset, -1, FALSE);
638 show_PDU_in_info(pinfo, tvb_length_remaining(tvb, offset),
639 (s_number_of_extensions == 0) ? first_includes_start : TRUE,
645 /*****************************/
646 /* Main dissection function. */
647 /*****************************/
649 void dissect_rlc_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
651 proto_tree *rlc_lte_tree;
655 struct rlc_lte_info *p_rlc_lte_info = NULL;
657 /* Set protocol name */
658 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
659 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC-LTE");
662 /* Create protocol tree. */
663 ti = proto_tree_add_item(tree, proto_rlc_lte, tvb, offset, -1, FALSE);
664 rlc_lte_tree = proto_item_add_subtree(ti, ett_rlc_lte);
667 /* Look for packet info! */
668 p_rlc_lte_info = p_get_proto_data(pinfo->fd, proto_rlc_lte);
670 /* Can't dissect anything without it... */
671 if (p_rlc_lte_info == NULL) {
673 proto_tree_add_text(rlc_lte_tree, tvb, offset, -1,
674 "Can't dissect LTE RLC frame because no per-frame info was attached!");
675 PROTO_ITEM_SET_GENERATED(ti);
679 /*****************************************/
680 /* Show context information */
681 /* TODO: hide inside own tree? */
683 ti = proto_tree_add_uint(rlc_lte_tree, hf_rlc_lte_context_direction,
684 tvb, 0, 0, p_rlc_lte_info->direction);
685 PROTO_ITEM_SET_GENERATED(ti);
687 mode_ti = proto_tree_add_uint(rlc_lte_tree, hf_rlc_lte_context_mode,
688 tvb, 0, 0, p_rlc_lte_info->rlcMode);
689 PROTO_ITEM_SET_GENERATED(mode_ti);
691 ti = proto_tree_add_uint(rlc_lte_tree, hf_rlc_lte_context_ueid,
692 tvb, 0, 0, p_rlc_lte_info->ueid);
693 PROTO_ITEM_SET_GENERATED(ti);
695 ti = proto_tree_add_uint(rlc_lte_tree, hf_rlc_lte_context_priority,
696 tvb, 0, 0, p_rlc_lte_info->priority);
697 PROTO_ITEM_SET_GENERATED(ti);
699 ti = proto_tree_add_uint(rlc_lte_tree, hf_rlc_lte_context_channel_type,
700 tvb, 0, 0, p_rlc_lte_info->channelType);
701 PROTO_ITEM_SET_GENERATED(ti);
703 ti = proto_tree_add_uint(rlc_lte_tree, hf_rlc_lte_context_channel_id,
704 tvb, 0, 0, p_rlc_lte_info->channelId);
705 PROTO_ITEM_SET_GENERATED(ti);
707 ti = proto_tree_add_uint(rlc_lte_tree, hf_rlc_lte_context_pdu_length,
708 tvb, 0, 0, p_rlc_lte_info->pduLength);
709 PROTO_ITEM_SET_GENERATED(ti);
711 if (p_rlc_lte_info->rlcMode == RLC_UM_MODE) {
712 ti = proto_tree_add_uint(rlc_lte_tree, hf_rlc_lte_context_um_sn_length,
713 tvb, 0, 0, p_rlc_lte_info->UMSequenceNumberLength);
714 PROTO_ITEM_SET_GENERATED(ti);
718 /* Append context highlights to info column */
719 if (check_col(pinfo->cinfo, COL_INFO)) {
720 col_add_fstr(pinfo->cinfo, COL_INFO,
721 "[%s] [%s] UEId=%u %s:%u",
722 (p_rlc_lte_info->direction == 0) ? "UL" : "DL",
723 val_to_str(p_rlc_lte_info->rlcMode, rlc_mode_short_vals, "Unknown"),
724 p_rlc_lte_info->ueid,
725 val_to_str(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
726 p_rlc_lte_info->channelId);
729 /* Reset this count */
730 s_number_of_extensions = 0;
732 /* Dissect the RLC PDU itself. Format depends upon mode... */
733 switch (p_rlc_lte_info->rlcMode) {
736 /* Remaining bytes are all data */
737 proto_tree_add_item(rlc_lte_tree, hf_rlc_lte_tm_data, tvb, offset, -1, FALSE);
738 if (check_col(pinfo->cinfo, COL_INFO)) {
739 col_append_fstr(pinfo->cinfo, COL_INFO, " [%u-bytes]",
740 tvb_length_remaining(tvb, offset));
745 dissect_rlc_lte_um(tvb, pinfo, rlc_lte_tree, offset, p_rlc_lte_info);
749 dissect_rlc_lte_am(tvb, pinfo, rlc_lte_tree, offset);
753 /* Error - unrecognised mode */
754 expert_add_info_format(pinfo, mode_ti, PI_MALFORMED, PI_ERROR,
755 "Unrecognised RLC Mode set (%u)", p_rlc_lte_info->rlcMode);
761 void proto_register_rlc_lte(void)
763 static hf_register_info hf[] =
765 /**********************************/
766 /* Items for decoding context */
767 { &hf_rlc_lte_context_mode,
769 "rlc-lte.mode", FT_UINT8, BASE_DEC, VALS(rlc_mode_vals), 0x0,
773 { &hf_rlc_lte_context_direction,
775 "rlc-lte.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
776 "Direction of message", HFILL
779 { &hf_rlc_lte_context_priority,
781 "rlc-lte.priority", FT_UINT8, BASE_DEC, 0, 0x0,
785 { &hf_rlc_lte_context_ueid,
787 "rlc-lte.ueid", FT_UINT16, BASE_DEC, 0, 0x0,
788 "User Equipment Identifier associated with message", HFILL
791 { &hf_rlc_lte_context_channel_type,
793 "rlc-lte.channel-type", FT_UINT16, BASE_DEC, VALS(rlc_channel_type_vals), 0x0,
794 "Channel Type associated with message", HFILL
797 { &hf_rlc_lte_context_channel_id,
799 "rlc-lte.channel-id", FT_UINT16, BASE_DEC, 0, 0x0,
800 "Channel ID associated with message", HFILL
803 { &hf_rlc_lte_context_pdu_length,
805 "rlc-lte.pdu_length", FT_UINT16, BASE_DEC, 0, 0x0,
806 "Length of PDU (in bytes)", HFILL
809 { &hf_rlc_lte_context_um_sn_length,
810 { "UM Sequence number length",
811 "rlc-lte.um-seqnum-length", FT_UINT8, BASE_DEC, 0, 0x0,
812 "Length of UM sequence number in bits", HFILL
817 /* Transparent mode fields */
818 { &hf_rlc_lte_tm_data,
820 "rlc-lte.tm.data", FT_BYTES, BASE_HEX, 0, 0x0,
821 "Transparent Mode Data", HFILL
825 /* Unacknowledged mode fields */
826 { &hf_rlc_lte_um_header,
828 "rlc-lte.um.header", FT_STRING, BASE_NONE, NULL, 0x0,
829 "Unackowledged Mode Header", HFILL
834 "rlc-lte.um.fi", FT_UINT8, BASE_HEX, VALS(framing_info_vals), 0x0,
835 "Framing Info", HFILL
838 { &hf_rlc_lte_um_fixed_e,
840 "rlc-lte.um.fixed.e", FT_UINT8, BASE_HEX, VALS(fixed_extension_vals), 0x0,
841 "Extension in fixed part of UM header", HFILL
846 "rlc-lte.um.sn", FT_UINT8, BASE_DEC, 0, 0x0,
847 "Unacknowledged Mode Sequence Number", HFILL
850 { &hf_rlc_lte_um_fixed_reserved,
852 "rlc-lte.um.reserved", FT_UINT8, BASE_DEC, 0, 0xe0,
853 "Unacknowledged Mode Fixed header reserved bits", HFILL
856 { &hf_rlc_lte_um_data,
858 "rlc-lte.um.data", FT_BYTES, BASE_HEX, 0, 0x0,
859 "Unacknowledged Mode Data", HFILL
862 { &hf_rlc_lte_extension_part,
864 "rlc-lte.extension-part", FT_STRING, BASE_NONE, 0, 0x0,
865 "Extension Part", HFILL
870 { &hf_rlc_lte_extension_e,
872 "rlc-lte.extension.e", FT_UINT8, BASE_HEX, VALS(extension_extension_vals), 0x0,
873 "Extension in extended part of the header", HFILL
876 { &hf_rlc_lte_extension_li,
877 { "Length Indicator",
878 "rlc-lte.extension.li", FT_UINT16, BASE_DEC, 0, 0x0,
879 "Length Indicator", HFILL
882 { &hf_rlc_lte_extension_padding,
884 "rlc-lte.extension.padding", FT_UINT8, BASE_HEX, 0, 0x0f,
885 "Extension header padding", HFILL
890 { &hf_rlc_lte_am_header,
892 "rlc-lte.am.header", FT_STRING, BASE_NONE, NULL, 0x0,
893 "Ackowledged Mode Header", HFILL
896 { &hf_rlc_lte_am_data_control,
898 "rlc-lte.am.frame_type", FT_UINT8, BASE_HEX, VALS(data_or_control_vals), 0x80,
899 "AM Frame Type (Control or Data)", HFILL
903 { "Re-segmentation Flag",
904 "rlc-lte.am.rf", FT_UINT8, BASE_HEX, VALS(resegmentation_flag_vals), 0x40,
905 "AM Re-segmentation Flag", HFILL
910 "rlc-lte.am.p", FT_UINT8, BASE_HEX, VALS(polling_bit_vals), 0x20,
916 "rlc-lte.am.fi", FT_UINT8, BASE_HEX, VALS(framing_info_vals), 0x18,
917 "AM Framing Info", HFILL
920 { &hf_rlc_lte_am_fixed_e,
922 "rlc-lte.am.fixed.e", FT_UINT8, BASE_HEX, VALS(fixed_extension_vals), 0x04,
923 "Fixed Extension Bit", HFILL
926 { &hf_rlc_lte_am_fixed_sn,
928 "rlc-lte.am.fixed.sn", FT_UINT16, BASE_HEX, 0, 0x03ff,
929 "AM Fixed Sequence Number", HFILL
932 { &hf_rlc_lte_am_segment_lsf,
933 { "Last Segment Flag",
934 "rlc-lte.am.segment.lsf", FT_UINT8, BASE_HEX, VALS(lsf_vals), 0x80,
935 "Last Segment Flag", HFILL
938 { &hf_rlc_lte_am_segment_so,
940 "rlc-lte.am.segment.so", FT_UINT16, BASE_HEX, 0, 0x7fff,
941 "Segment Offset", HFILL
944 { &hf_rlc_lte_am_data,
946 "rlc-lte.am.data", FT_BYTES, BASE_HEX, 0, 0x0,
947 "Acknowledged Mode Data", HFILL
952 { &hf_rlc_lte_am_cpt,
953 { "Control PDU Type",
954 "rlc-lte.am.cpt", FT_UINT8, BASE_HEX, VALS(control_pdu_type_vals), 0x70,
955 "AM Control PDU Type", HFILL
958 { &hf_rlc_lte_am_ack_sn,
959 { "ACK Sequence Number",
960 "rlc-lte.am.ack-sn", FT_UINT16, BASE_DEC, 0, 0x0ffc,
961 "Sequence Number we're next expecting to receive", HFILL
966 "rlc-lte.am.e1", FT_UINT8, BASE_HEX, VALS(am_e1_vals), 0x0,
967 "Extension bit 1", HFILL
972 "rlc-lte.am.e2", FT_UINT8, BASE_HEX, VALS(am_e2_vals), 0x0,
973 "Extension bit 2", HFILL
976 { &hf_rlc_lte_am_nack_sn,
977 { "NACK Sequence Number",
978 "rlc-lte.am.nack-sn", FT_UINT16, BASE_DEC, 0, 0x0,
979 "Negative Acknowledgement Sequence Number", HFILL
982 { &hf_rlc_lte_am_so_start,
984 "rlc-lte.am.so-start", FT_UINT16, BASE_DEC, 0, 0x0,
988 { &hf_rlc_lte_am_so_end,
990 "rlc-lte.am.so-end", FT_UINT16, BASE_DEC, 0, 0x0,
1000 &ett_rlc_lte_um_header,
1001 &ett_rlc_lte_am_header,
1002 &ett_rlc_lte_extension_part,
1005 /* Register protocol. */
1006 proto_rlc_lte = proto_register_protocol("RLC-LTE", "RLC-LTE", "rlc-lte");
1007 proto_register_field_array(proto_rlc_lte, hf, array_length(hf));
1008 proto_register_subtree_array(ett, array_length(ett));
1010 /* Allow other dissectors to find this one by name. */
1011 register_dissector("rlc-lte", dissect_rlc_lte, proto_rlc_lte);