2009-01-05 23:18:00 +00:00
/* Routines for LTE RLC disassembly
*
* Martin Mathieson
*
* Wireshark - Network traffic analyzer
* By Gerald Combs < gerald @ wireshark . org >
* Copyright 1998 Gerald Combs
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
2012-06-28 22:56:06 +00:00
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
2009-01-05 23:18:00 +00:00
*/
2012-09-20 02:03:38 +00:00
# include "config.h"
2009-04-14 14:38:20 +00:00
2009-01-05 23:18:00 +00:00
# include <epan/packet.h>
2013-11-10 15:59:37 +00:00
# include <epan/exceptions.h>
2009-01-05 23:18:00 +00:00
# include <epan/expert.h>
2009-04-14 14:38:20 +00:00
# include <epan/prefs.h>
2010-01-04 14:07:24 +00:00
# include <epan/tap.h>
2010-03-01 22:52:34 +00:00
# include "packet-mac-lte.h"
2009-01-05 23:18:00 +00:00
# include "packet-rlc-lte.h"
2009-11-16 15:35:56 +00:00
# include "packet-pdcp-lte.h"
2009-01-05 23:18:00 +00:00
/* Described in:
* 3 GPP TS 36.322 Evolved Universal Terrestial Radio Access ( E - UTRA )
2014-12-07 19:54:05 +00:00
* Radio Link Control ( RLC ) Protocol specification v12 .1 .0
2009-01-05 23:18:00 +00:00
*/
2009-03-11 11:17:16 +00:00
/* TODO:
2011-09-10 23:46:49 +00:00
- add intermediate results to segments leading to final reassembly
- use multiple active rlc_channel_reassembly_info ' s per channel
2012-01-24 03:05:21 +00:00
- sequence analysis gets confused when we change cells and skip back
to SN 0. Maybe add cell - id to context and add to channel / result key ?
2009-03-11 11:17:16 +00:00
*/
2009-04-14 14:38:20 +00:00
2013-12-12 17:45:22 +00:00
void proto_register_rlc_lte ( void ) ;
void proto_reg_handoff_rlc_lte ( void ) ;
2010-03-01 23:56:35 +00:00
/********************************/
/* Preference settings */
2010-02-28 02:18:35 +00:00
# define SEQUENCE_ANALYSIS_MAC_ONLY 1
# define SEQUENCE_ANALYSIS_RLC_ONLY 2
2009-04-14 14:38:20 +00:00
2013-02-16 00:11:28 +00:00
/* By default do try to analyse the sequence of messages for AM/UM channels
using MAC PDUs */
static gint global_rlc_lte_am_sequence_analysis = SEQUENCE_ANALYSIS_MAC_ONLY ;
static gint global_rlc_lte_um_sequence_analysis = SEQUENCE_ANALYSIS_MAC_ONLY ;
2009-04-14 14:38:20 +00:00
2013-02-16 00:11:28 +00:00
/* By default do call PDCP/RRC dissectors for SDU data */
static gboolean global_rlc_lte_call_pdcp_for_srb = TRUE ;
2010-07-28 16:58:13 +00:00
2012-09-21 20:12:32 +00:00
enum pdcp_for_drb { PDCP_drb_off , PDCP_drb_SN_7 , PDCP_drb_SN_12 , PDCP_drb_SN_signalled , PDCP_drb_SN_15 } ;
2012-11-29 20:15:37 +00:00
static const enum_val_t pdcp_drb_col_vals [ ] = {
2011-09-10 23:46:49 +00:00
{ " pdcp-drb-off " , " Off " , PDCP_drb_off } ,
{ " pdcp-drb-sn-7 " , " 7-bit SN " , PDCP_drb_SN_7 } ,
{ " pdcp-drb-sn-12 " , " 12-bit SN " , PDCP_drb_SN_12 } ,
2012-09-21 20:12:32 +00:00
{ " pdcp-drb-sn-15 " , " 15-bit SN " , PDCP_drb_SN_15 } ,
2011-04-17 21:34:47 +00:00
{ " pdcp-drb-sn-signalling " , " Use signalled value " , PDCP_drb_SN_signalled } ,
2010-07-28 16:58:13 +00:00
{ NULL , NULL , - 1 }
} ;
2014-04-27 22:11:51 +00:00
static gint global_rlc_lte_call_pdcp_for_drb = ( gint ) PDCP_drb_SN_signalled ;
2010-07-28 16:58:13 +00:00
2013-02-16 00:11:28 +00:00
static gboolean global_rlc_lte_call_rrc_for_ccch = TRUE ;
2012-10-01 19:51:07 +00:00
static gboolean global_rlc_lte_call_rrc_for_mcch = FALSE ;
2012-12-11 23:20:22 +00:00
static gboolean global_rlc_lte_call_ip_for_mtch = FALSE ;
2009-04-14 14:38:20 +00:00
2010-02-01 11:00:08 +00:00
/* Preference to expect RLC headers without payloads */
static gboolean global_rlc_lte_headers_expected = FALSE ;
2010-03-01 23:56:35 +00:00
/* Heuristic dissection */
static gboolean global_rlc_lte_heur = FALSE ;
2009-04-14 14:38:20 +00:00
2011-09-06 12:01:28 +00:00
/* Re-assembly of segments */
2013-02-16 00:11:28 +00:00
static gboolean global_rlc_lte_reassembly = TRUE ;
2010-03-01 23:56:35 +00:00
2014-12-07 19:54:05 +00:00
/* Tree storing UE related parameters */
# define NO_EXT_LI 0x0
# define UL_EXT_LI 0x1
# define DL_EXT_LI 0x2
typedef struct rlc_ue_parameters {
guint32 id ;
guint8 ext_li_field ;
guint8 pdcp_sn_bits ;
} rlc_ue_parameters ;
static wmem_tree_t * ue_parameters_tree ;
2010-03-01 23:56:35 +00:00
/**************************************************/
2009-01-05 23:18:00 +00:00
/* Initialize the protocol and registered fields. */
int proto_rlc_lte = - 1 ;
2010-01-20 12:37:26 +00:00
extern int proto_mac_lte ;
2010-03-01 23:56:35 +00:00
extern int proto_pdcp_lte ;
2010-01-20 12:37:26 +00:00
2012-10-06 14:59:51 +00:00
static dissector_handle_t pdcp_lte_handle ;
2012-12-11 23:20:22 +00:00
static dissector_handle_t ip_handle ;
2012-10-06 14:59:51 +00:00
2010-01-04 14:07:24 +00:00
static int rlc_lte_tap = - 1 ;
2009-01-05 23:18:00 +00:00
/* Decoding context */
2010-03-09 01:39:08 +00:00
static int hf_rlc_lte_context = - 1 ;
2009-01-05 23:18:00 +00:00
static int hf_rlc_lte_context_mode = - 1 ;
static int hf_rlc_lte_context_direction = - 1 ;
static int hf_rlc_lte_context_priority = - 1 ;
static int hf_rlc_lte_context_ueid = - 1 ;
static int hf_rlc_lte_context_channel_type = - 1 ;
static int hf_rlc_lte_context_channel_id = - 1 ;
static int hf_rlc_lte_context_pdu_length = - 1 ;
static int hf_rlc_lte_context_um_sn_length = - 1 ;
/* Transparent mode fields */
2010-03-06 19:35:40 +00:00
static int hf_rlc_lte_tm = - 1 ;
2009-01-05 23:18:00 +00:00
static int hf_rlc_lte_tm_data = - 1 ;
/* Unacknowledged mode fields */
2010-03-06 19:35:40 +00:00
static int hf_rlc_lte_um = - 1 ;
2009-01-05 23:18:00 +00:00
static int hf_rlc_lte_um_header = - 1 ;
static int hf_rlc_lte_um_fi = - 1 ;
static int hf_rlc_lte_um_fixed_e = - 1 ;
static int hf_rlc_lte_um_sn = - 1 ;
static int hf_rlc_lte_um_fixed_reserved = - 1 ;
static int hf_rlc_lte_um_data = - 1 ;
static int hf_rlc_lte_extension_part = - 1 ;
/* Extended header (common to UM and AM) */
static int hf_rlc_lte_extension_e = - 1 ;
static int hf_rlc_lte_extension_li = - 1 ;
static int hf_rlc_lte_extension_padding = - 1 ;
/* Acknowledged mode fields */
2010-03-06 19:35:40 +00:00
static int hf_rlc_lte_am = - 1 ;
2009-01-05 23:18:00 +00:00
static int hf_rlc_lte_am_header = - 1 ;
static int hf_rlc_lte_am_data_control = - 1 ;
static int hf_rlc_lte_am_rf = - 1 ;
static int hf_rlc_lte_am_p = - 1 ;
static int hf_rlc_lte_am_fi = - 1 ;
static int hf_rlc_lte_am_fixed_e = - 1 ;
static int hf_rlc_lte_am_fixed_sn = - 1 ;
static int hf_rlc_lte_am_segment_lsf = - 1 ;
static int hf_rlc_lte_am_segment_so = - 1 ;
static int hf_rlc_lte_am_data = - 1 ;
/* Control fields */
static int hf_rlc_lte_am_cpt = - 1 ;
static int hf_rlc_lte_am_ack_sn = - 1 ;
static int hf_rlc_lte_am_e1 = - 1 ;
static int hf_rlc_lte_am_e2 = - 1 ;
static int hf_rlc_lte_am_nack_sn = - 1 ;
2011-07-18 10:40:57 +00:00
static int hf_rlc_lte_am_nacks = - 1 ;
2009-01-05 23:18:00 +00:00
static int hf_rlc_lte_am_so_start = - 1 ;
static int hf_rlc_lte_am_so_end = - 1 ;
2009-01-21 15:44:22 +00:00
static int hf_rlc_lte_predefined_pdu = - 1 ;
2010-02-01 11:00:08 +00:00
static int hf_rlc_lte_header_only = - 1 ;
2009-01-21 15:44:22 +00:00
2009-04-14 14:38:20 +00:00
/* Sequence Analysis */
static int hf_rlc_lte_sequence_analysis = - 1 ;
2010-02-28 20:43:04 +00:00
static int hf_rlc_lte_sequence_analysis_ok = - 1 ;
2009-04-14 14:38:20 +00:00
static int hf_rlc_lte_sequence_analysis_previous_frame = - 1 ;
2012-01-23 02:36:46 +00:00
static int hf_rlc_lte_sequence_analysis_next_frame = - 1 ;
2009-04-14 14:38:20 +00:00
static int hf_rlc_lte_sequence_analysis_expected_sn = - 1 ;
static int hf_rlc_lte_sequence_analysis_framing_info_correct = - 1 ;
2010-03-01 22:52:34 +00:00
static int hf_rlc_lte_sequence_analysis_mac_retx = - 1 ;
2010-02-28 02:18:35 +00:00
static int hf_rlc_lte_sequence_analysis_retx = - 1 ;
static int hf_rlc_lte_sequence_analysis_repeated = - 1 ;
static int hf_rlc_lte_sequence_analysis_skipped = - 1 ;
2009-04-14 14:38:20 +00:00
2010-03-02 18:40:34 +00:00
static int hf_rlc_lte_sequence_analysis_repeated_nack = - 1 ;
2010-10-15 21:07:45 +00:00
static int hf_rlc_lte_sequence_analysis_repeated_nack_original_frame = - 1 ;
2009-04-14 14:38:20 +00:00
2011-05-19 01:05:26 +00:00
static int hf_rlc_lte_sequence_analysis_ack_out_of_range = - 1 ;
static int hf_rlc_lte_sequence_analysis_ack_out_of_range_opposite_frame = - 1 ;
2011-09-06 12:01:28 +00:00
/* Reassembly */
static int hf_rlc_lte_reassembly_source = - 1 ;
static int hf_rlc_lte_reassembly_source_number_of_segments = - 1 ;
static int hf_rlc_lte_reassembly_source_total_length = - 1 ;
static int hf_rlc_lte_reassembly_source_segment = - 1 ;
static int hf_rlc_lte_reassembly_source_segment_sn = - 1 ;
static int hf_rlc_lte_reassembly_source_segment_framenum = - 1 ;
static int hf_rlc_lte_reassembly_source_segment_length = - 1 ;
2009-01-05 23:18:00 +00:00
/* Subtrees. */
static int ett_rlc_lte = - 1 ;
2010-03-09 01:39:08 +00:00
static int ett_rlc_lte_context = - 1 ;
2009-01-05 23:18:00 +00:00
static int ett_rlc_lte_um_header = - 1 ;
static int ett_rlc_lte_am_header = - 1 ;
static int ett_rlc_lte_extension_part = - 1 ;
2009-04-14 14:38:20 +00:00
static int ett_rlc_lte_sequence_analysis = - 1 ;
2011-09-06 12:01:28 +00:00
static int ett_rlc_lte_reassembly_source = - 1 ;
static int ett_rlc_lte_reassembly_source_segment = - 1 ;
2009-01-05 23:18:00 +00:00
2013-09-05 01:05:16 +00:00
static expert_field ei_rlc_lte_context_mode = EI_INIT ;
static expert_field ei_rlc_lte_am_nack_sn = EI_INIT ;
static expert_field ei_rlc_lte_am_nack_sn_ahead_ack = EI_INIT ;
static expert_field ei_rlc_lte_um_sn_repeated = EI_INIT ;
static expert_field ei_rlc_lte_am_nack_sn_ack_same = EI_INIT ;
static expert_field ei_rlc_lte_am_cpt = EI_INIT ;
static expert_field ei_rlc_lte_am_data_no_data = EI_INIT ;
static expert_field ei_rlc_lte_sequence_analysis_last_segment_complete = EI_INIT ;
static expert_field ei_rlc_lte_sequence_analysis_mac_retx = EI_INIT ;
static expert_field ei_rlc_lte_am_nack_sn_partial = EI_INIT ;
static expert_field ei_rlc_lte_sequence_analysis_repeated_nack = EI_INIT ;
static expert_field ei_rlc_lte_bytes_after_status_pdu_complete = EI_INIT ;
static expert_field ei_rlc_lte_sequence_analysis_repeated = EI_INIT ;
static expert_field ei_rlc_lte_wrong_sequence_number = EI_INIT ;
static expert_field ei_rlc_lte_sequence_analysis_retx = EI_INIT ;
static expert_field ei_rlc_lte_am_sn_missing = EI_INIT ;
static expert_field ei_rlc_lte_um_sn = EI_INIT ;
static expert_field ei_rlc_lte_header_only = EI_INIT ;
static expert_field ei_rlc_lte_am_data_no_data_beyond_extensions = EI_INIT ;
static expert_field ei_rlc_lte_um_sn_missing = EI_INIT ;
static expert_field ei_rlc_lte_sequence_analysis_ack_out_of_range_opposite_frame = EI_INIT ;
static expert_field ei_rlc_lte_sequence_analysis_last_segment_not_continued = EI_INIT ;
static expert_field ei_rlc_lte_reserved_bits_not_zero = EI_INIT ;
2014-09-06 12:44:23 +00:00
static expert_field ei_rlc_lte_no_per_frame_info = EI_INIT ;
2013-09-05 01:05:16 +00:00
2010-03-01 23:56:35 +00:00
/* Value-strings */
2009-01-05 23:18:00 +00:00
static const value_string direction_vals [ ] =
{
2009-02-19 22:25:36 +00:00
{ DIRECTION_UPLINK , " Uplink " } ,
{ DIRECTION_DOWNLINK , " Downlink " } ,
2009-01-05 23:18:00 +00:00
{ 0 , NULL }
} ;
static const value_string rlc_mode_short_vals [ ] =
{
{ RLC_TM_MODE , " TM " } ,
{ RLC_UM_MODE , " UM " } ,
{ RLC_AM_MODE , " AM " } ,
2012-02-03 10:42:01 +00:00
{ RLC_PREDEF , " PREDEFINED " } , /* For data testing */
2009-01-05 23:18:00 +00:00
{ 0 , NULL }
} ;
static const value_string rlc_mode_vals [ ] =
{
{ RLC_TM_MODE , " Transparent Mode " } ,
{ RLC_UM_MODE , " Unacknowledged Mode " } ,
{ RLC_AM_MODE , " Acknowledged Mode " } ,
{ 0 , NULL }
} ;
static const value_string rlc_channel_type_vals [ ] =
{
2011-07-19 16:41:56 +00:00
{ CHANNEL_TYPE_CCCH , " CCCH " } ,
{ CHANNEL_TYPE_BCCH_BCH , " BCCH_BCH " } ,
{ CHANNEL_TYPE_PCCH , " PCCH " } ,
{ CHANNEL_TYPE_SRB , " SRB " } ,
{ CHANNEL_TYPE_DRB , " DRB " } ,
{ CHANNEL_TYPE_BCCH_DL_SCH , " BCCH_DL_SCH " } ,
2012-10-01 19:51:07 +00:00
{ CHANNEL_TYPE_MCCH , " MCCH " } ,
2012-12-11 23:20:22 +00:00
{ CHANNEL_TYPE_MTCH , " MTCH " } ,
2009-01-05 23:18:00 +00:00
{ 0 , NULL }
} ;
static const value_string framing_info_vals [ ] =
{
2010-01-06 17:07:37 +00:00
{ 0 , " First byte begins a RLC SDU and last byte ends a RLC SDU " } ,
{ 1 , " First byte begins a RLC SDU and last byte does not end a RLC SDU " } ,
{ 2 , " First byte does not begin a RLC SDU and last byte ends a RLC SDU " } ,
{ 3 , " First byte does not begin a RLC SDU and last byte does not end a RLC SDU " } ,
2009-01-05 23:18:00 +00:00
{ 0 , NULL }
} ;
static const value_string fixed_extension_vals [ ] =
{
{ 0 , " Data field follows from the octet following the fixed part of the header " } ,
{ 1 , " A set of E field and LI field follows from the octet following the fixed part of the header " } ,
{ 0 , NULL }
} ;
static const value_string extension_extension_vals [ ] =
{
{ 0 , " Data field follows from the octet following the LI field following this E field " } ,
{ 1 , " A set of E field and LI field follows from the bit following the LI field following this E field " } ,
{ 0 , NULL }
} ;
static const value_string data_or_control_vals [ ] =
{
{ 0 , " Control PDU " } ,
{ 1 , " Data PDU " } ,
{ 0 , NULL }
} ;
static const value_string resegmentation_flag_vals [ ] =
{
{ 0 , " AMD PDU " } ,
2010-01-06 17:07:37 +00:00
{ 1 , " AMD PDU segment " } ,
2009-01-05 23:18:00 +00:00
{ 0 , NULL }
} ;
static const value_string polling_bit_vals [ ] =
{
{ 0 , " Status report not requested " } ,
{ 1 , " Status report is requested " } ,
{ 0 , NULL }
} ;
static const value_string lsf_vals [ ] =
{
{ 0 , " Last byte of the AMD PDU segment does not correspond to the last byte of an AMD PDU " } ,
2010-01-06 17:07:37 +00:00
{ 1 , " Last byte of the AMD PDU segment corresponds to the last byte of an AMD PDU " } ,
2009-01-05 23:18:00 +00:00
{ 0 , NULL }
} ;
static const value_string control_pdu_type_vals [ ] =
{
{ 0 , " STATUS PDU " } ,
{ 0 , NULL }
} ;
static const value_string am_e1_vals [ ] =
{
{ 0 , " A set of NACK_SN, E1 and E2 does not follow " } ,
{ 1 , " A set of NACK_SN, E1 and E2 follows " } ,
{ 0 , NULL }
} ;
static const value_string am_e2_vals [ ] =
{
{ 0 , " A set of SOstart and SOend does not follow for this NACK_SN " } ,
{ 1 , " A set of SOstart and SOend follows for this NACK_SN " } ,
{ 0 , NULL }
} ;
2010-02-01 11:00:08 +00:00
static const value_string header_only_vals [ ] =
{
{ 0 , " RLC PDU Headers and body present " } ,
{ 1 , " RLC PDU Headers only " } ,
{ 0 , NULL }
} ;
2009-04-14 14:38:20 +00:00
2009-11-16 15:35:56 +00:00
2009-04-14 14:38:20 +00:00
/**********************************************************************************/
/* These are for keeping track of UM/AM extension headers, and the lengths found */
/* in them */
2010-10-10 20:39:00 +00:00
static guint8 s_number_of_extensions = 0 ;
2014-12-07 19:54:05 +00:00
# define MAX_RLC_SDUS 192
2010-10-10 20:39:00 +00:00
static guint16 s_lengths [ MAX_RLC_SDUS ] ;
2009-01-05 23:18:00 +00:00
2010-03-01 23:56:35 +00:00
/*********************************************************************/
/* UM/AM sequence analysis */
/* Types for RLC channel hash table */
/* This table is maintained during initial dissection of RLC */
2012-01-23 02:36:46 +00:00
/* frames, mapping from channel_hash_key -> sequence_analysis_report */
2010-03-01 23:56:35 +00:00
/* Channel key */
typedef struct
{
2013-01-04 05:22:43 +00:00
guint ueId : 16 ;
guint channelType : 3 ;
guint channelId : 5 ;
guint direction : 1 ;
2012-01-23 02:36:46 +00:00
} channel_hash_key ;
2010-03-01 23:56:35 +00:00
2011-09-06 12:01:28 +00:00
/******************************************************************/
/* State maintained for AM/UM reassembly */
typedef struct rlc_segment {
guint32 frameNum ;
guint16 SN ;
guint8 * data ;
guint16 length ;
} rlc_segment ;
typedef struct rlc_channel_reassembly_info
{
guint16 number_of_segments ;
# define RLC_MAX_SEGMENTS 100
rlc_segment segments [ RLC_MAX_SEGMENTS ] ;
} rlc_channel_reassembly_info ;
/*******************************************************************/
/* Conversation-type status for sequence analysis on channel */
2010-03-01 23:56:35 +00:00
typedef struct
{
guint8 rlcMode ;
/* For UM, we always expect the SN to keep advancing, and these fields
keep track of this .
For AM , these correspond to new data */
guint16 previousSequenceNumber ;
guint32 previousFrameNum ;
gboolean previousSegmentIncomplete ;
2011-09-06 12:01:28 +00:00
/* Accumulate info about current segmented SDU */
struct rlc_channel_reassembly_info * reassembly_info ;
2012-01-23 02:36:46 +00:00
} channel_sequence_analysis_status ;
2010-03-01 23:56:35 +00:00
2010-03-02 18:40:34 +00:00
/* The sequence analysis channel hash table */
2012-01-23 02:36:46 +00:00
static GHashTable * sequence_analysis_channel_hash = NULL ;
2010-03-01 23:56:35 +00:00
/* Types for sequence analysis frame report hash table */
/* This is a table from framenum -> state_report_in_frame */
/* This is necessary because the per-packet info is already being used */
2010-04-20 15:41:03 +00:00
/* for context information before the dissector is called */
2010-03-01 23:56:35 +00:00
/* Info to attach to frame when first read, recording what to show about sequence */
2012-11-29 20:15:37 +00:00
typedef enum {
2012-01-23 02:36:46 +00:00
SN_OK , SN_Repeated , SN_MAC_Retx , SN_Retx , SN_Missing , ACK_Out_of_Window , SN_Error
} sequence_analysis_state ;
2010-03-01 23:56:35 +00:00
typedef struct
{
gboolean sequenceExpectedCorrect ;
guint16 sequenceExpected ;
guint32 previousFrameNum ;
gboolean previousSegmentIncomplete ;
2012-01-23 02:36:46 +00:00
guint32 nextFrameNum ;
2010-03-01 23:56:35 +00:00
guint16 firstSN ;
guint16 lastSN ;
2010-06-25 23:04:16 +00:00
/* AM/UM */
2012-01-23 02:36:46 +00:00
sequence_analysis_state state ;
} sequence_analysis_report ;
2010-03-01 23:56:35 +00:00
/* The sequence analysis frame report hash table instance itself */
2012-01-23 02:36:46 +00:00
static GHashTable * sequence_analysis_report_hash = NULL ;
static gpointer get_report_hash_key ( guint16 SN , guint32 frameNumber ,
rlc_lte_info * p_rlc_lte_info ,
gboolean do_persist ) ;
2010-03-01 23:56:35 +00:00
2011-09-06 12:01:28 +00:00
/* The reassembly result hash table */
2012-01-23 02:36:46 +00:00
static GHashTable * reassembly_report_hash = NULL ;
2011-09-06 12:01:28 +00:00
/* Create a new struct for reassembly */
2012-01-23 02:36:46 +00:00
static void reassembly_reset ( channel_sequence_analysis_status * status )
2011-09-06 12:01:28 +00:00
{
2013-08-30 14:49:55 +00:00
status - > reassembly_info = wmem_new0 ( wmem_file_scope ( ) , rlc_channel_reassembly_info ) ;
2011-09-06 12:01:28 +00:00
}
/* Hide previous one */
2012-01-23 02:36:46 +00:00
static void reassembly_destroy ( channel_sequence_analysis_status * status )
2011-09-06 12:01:28 +00:00
{
2011-09-10 23:46:49 +00:00
/* Just "leak" it. There seems to be no way to free this memory... */
2011-09-06 12:01:28 +00:00
status - > reassembly_info = NULL ;
}
/* Add a new segment to the accumulating segmented SDU */
2012-01-23 02:36:46 +00:00
static void reassembly_add_segment ( channel_sequence_analysis_status * status ,
2011-09-06 12:01:28 +00:00
guint16 SN , guint32 frame ,
tvbuff_t * tvb , gint offset , gint length )
{
int segment_number = status - > reassembly_info - > number_of_segments ;
guint8 * segment_data ;
/* Give up if reach segment limit */
if ( segment_number > = ( RLC_MAX_SEGMENTS - 1 ) ) {
reassembly_destroy ( status ) ;
return ;
}
2015-03-02 04:03:27 +00:00
segment_data = ( guint8 * ) tvb_memdup ( wmem_file_scope ( ) , tvb , offset , length ) ;
2011-09-06 12:01:28 +00:00
/* Add new segment */
status - > reassembly_info - > segments [ segment_number ] . frameNum = frame ;
status - > reassembly_info - > segments [ segment_number ] . SN = SN ;
status - > reassembly_info - > segments [ segment_number ] . data = segment_data ;
status - > reassembly_info - > segments [ segment_number ] . length = length ;
status - > reassembly_info - > number_of_segments + + ;
}
/* Record the current & complete segmented SDU by mapping from this frame number to
2012-01-23 02:36:46 +00:00
struct with segment info . */
static void reassembly_record ( channel_sequence_analysis_status * status , packet_info * pinfo ,
guint16 SN , rlc_lte_info * p_rlc_lte_info )
2011-09-06 12:01:28 +00:00
{
/* Just store existing info in hash table */
2012-01-23 02:36:46 +00:00
g_hash_table_insert ( reassembly_report_hash ,
get_report_hash_key ( SN , pinfo - > fd - > num , p_rlc_lte_info , TRUE ) ,
status - > reassembly_info ) ;
2011-09-06 12:01:28 +00:00
}
/* Create and return a tvb based upon contents of reassembly info */
static tvbuff_t * reassembly_get_reassembled_tvb ( rlc_channel_reassembly_info * reassembly_info ,
2011-12-16 17:33:09 +00:00
tvbuff_t * parent_tvb , packet_info * pinfo )
2011-09-06 12:01:28 +00:00
{
gint n ;
guint combined_length = 0 ;
guint8 * combined_data ;
guint combined_offset = 0 ;
2011-12-16 17:33:09 +00:00
tvbuff_t * reassembled_tvb ;
2011-09-06 12:01:28 +00:00
/* Allocate buffer big enough to hold re-assembled data */
for ( n = 0 ; n < reassembly_info - > number_of_segments ; n + + ) {
combined_length + = reassembly_info - > segments [ n ] . length ;
}
2013-08-19 10:39:43 +00:00
combined_data = ( guint8 * ) g_malloc ( combined_length ) ;
2011-09-06 12:01:28 +00:00
/* Copy data into contiguous buffer */
for ( n = 0 ; n < reassembly_info - > number_of_segments ; n + + ) {
guint8 * data = reassembly_info - > segments [ n ] . data ;
int length = reassembly_info - > segments [ n ] . length ;
memcpy ( combined_data + combined_offset , data , length ) ;
combined_offset + = length ;
}
/* Create and return tvb with this data */
2011-12-16 17:33:09 +00:00
reassembled_tvb = tvb_new_child_real_data ( parent_tvb , combined_data , combined_offset , combined_offset ) ;
2013-08-19 10:39:43 +00:00
tvb_set_free_cb ( reassembled_tvb , g_free ) ;
2011-12-16 17:33:09 +00:00
add_new_data_source ( pinfo , reassembled_tvb , " Reassembled SDU " ) ;
return reassembled_tvb ;
2011-09-06 12:01:28 +00:00
}
/* Show where the segments came from for a reassembled SDU */
static void reassembly_show_source ( rlc_channel_reassembly_info * reassembly_info ,
proto_tree * tree , tvbuff_t * tvb , gint offset )
{
int n ;
proto_item * source_ti , * ti ;
proto_tree * source_tree ;
proto_item * segment_ti ;
proto_tree * segment_tree ;
guint total_length = 0 ;
/* Create root of source info */
source_ti = proto_tree_add_item ( tree ,
hf_rlc_lte_reassembly_source ,
2011-10-15 18:46:26 +00:00
tvb , 0 , 0 , ENC_ASCII | ENC_NA ) ;
2011-09-06 12:01:28 +00:00
source_tree = proto_item_add_subtree ( source_ti , ett_rlc_lte_reassembly_source ) ;
PROTO_ITEM_SET_GENERATED ( source_ti ) ;
2011-09-06 13:18:26 +00:00
for ( n = 0 ; n < reassembly_info - > number_of_segments ; n + + ) {
total_length + = reassembly_info - > segments [ n ] . length ;
}
proto_item_append_text ( source_ti , " %u segments, %u bytes " , reassembly_info - > number_of_segments ,
total_length ) ;
2011-09-06 12:01:28 +00:00
/* Number of segments */
ti = proto_tree_add_uint ( source_tree ,
hf_rlc_lte_reassembly_source_number_of_segments ,
tvb , 0 , 0 , reassembly_info - > number_of_segments ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
/* Total length */
ti = proto_tree_add_uint ( source_tree ,
2011-09-06 13:18:26 +00:00
hf_rlc_lte_reassembly_source_total_length ,
2011-09-06 12:01:28 +00:00
tvb , 0 , 0 , total_length ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
/* Now add info about each segment in turn */
for ( n = 0 ; n < reassembly_info - > number_of_segments ; n + + ) {
/* Add next segment as a subtree */
rlc_segment * segment = & ( reassembly_info - > segments [ n ] ) ;
proto_item_append_text ( source_ti , " (SN=%u frame=%u len=%u) " ,
segment - > SN , segment - > frameNum , segment - > length ) ;
/* N.B. assume last segment from passed-in tvb! */
segment_ti = proto_tree_add_item ( source_tree ,
hf_rlc_lte_reassembly_source_segment ,
tvb ,
( n = = reassembly_info - > number_of_segments - 1 ) ? offset : 0 ,
( n = = reassembly_info - > number_of_segments - 1 ) ? segment - > length : 0 ,
2011-10-04 22:44:31 +00:00
ENC_NA ) ;
2011-09-06 12:01:28 +00:00
segment_tree = proto_item_add_subtree ( segment_ti , ett_rlc_lte_reassembly_source_segment ) ;
2011-09-06 13:18:26 +00:00
proto_item_append_text ( segment_ti , " (SN=%u frame=%u length=%u) " ,
2011-09-06 12:01:28 +00:00
segment - > SN , segment - > frameNum , segment - > length ) ;
PROTO_ITEM_SET_GENERATED ( segment_ti ) ;
/* Add details to segment tree */
ti = proto_tree_add_uint ( segment_tree , hf_rlc_lte_reassembly_source_segment_sn ,
tvb , 0 , 0 , segment - > SN ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
ti = proto_tree_add_uint ( segment_tree , hf_rlc_lte_reassembly_source_segment_framenum ,
tvb , 0 , 0 , segment - > frameNum ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
ti = proto_tree_add_uint ( segment_tree , hf_rlc_lte_reassembly_source_segment_length ,
tvb , 0 , 0 , segment - > length ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
}
}
2010-03-02 18:40:34 +00:00
/******************************************************************/
/* Conversation-type status for repeated NACK checking on channel */
typedef struct
{
2010-03-04 20:58:54 +00:00
guint16 noOfNACKs ;
2010-03-02 18:40:34 +00:00
guint16 NACKs [ MAX_NACKs ] ;
2010-10-15 21:07:45 +00:00
guint32 frameNum ;
2012-01-23 02:36:46 +00:00
} channel_repeated_nack_status ;
2010-03-01 23:56:35 +00:00
2012-01-23 02:36:46 +00:00
static GHashTable * repeated_nack_channel_hash = NULL ;
2010-03-01 23:56:35 +00:00
2010-03-02 18:40:34 +00:00
typedef struct {
2010-03-04 20:58:54 +00:00
guint16 noOfNACKsRepeated ;
2010-03-02 18:40:34 +00:00
guint16 repeatedNACKs [ MAX_NACKs ] ;
2010-10-15 21:07:45 +00:00
guint32 previousFrameNum ;
2012-01-23 02:36:46 +00:00
} channel_repeated_nack_report ;
2010-03-01 23:56:35 +00:00
2012-01-23 02:36:46 +00:00
static GHashTable * repeated_nack_report_hash = NULL ;
2010-03-01 23:56:35 +00:00
2010-03-02 18:40:34 +00:00
/********************************************************/
/* Forward declarations & functions */
2013-07-03 20:03:52 +00:00
static void dissect_rlc_lte_common ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree , gboolean is_udp_framing ) ;
2010-03-01 23:56:35 +00:00
2010-03-09 01:39:08 +00:00
/* Write the given formatted text to:
- the info column
- the top - level RLC PDU item
- another subtree item ( if supplied ) */
static void write_pdu_label_and_info ( proto_item * pdu_ti , proto_item * sub_ti ,
packet_info * pinfo , const char * format , . . . )
{
# define MAX_INFO_BUFFER 256
static char info_buffer [ MAX_INFO_BUFFER ] ;
2010-10-10 20:39:00 +00:00
2010-03-09 01:39:08 +00:00
va_list ap ;
va_start ( ap , format ) ;
g_vsnprintf ( info_buffer , MAX_INFO_BUFFER , format , ap ) ;
va_end ( ap ) ;
/* Add to indicated places */
col_append_str ( pinfo - > cinfo , COL_INFO , info_buffer ) ;
2012-09-19 16:56:59 +00:00
proto_item_append_text ( pdu_ti , " %s " , info_buffer ) ;
2010-03-09 01:39:08 +00:00
if ( sub_ti ! = NULL ) {
2012-09-19 16:56:59 +00:00
proto_item_append_text ( sub_ti , " %s " , info_buffer ) ;
2010-03-09 01:39:08 +00:00
}
}
2012-11-29 22:25:18 +00:00
/* Version of function above, where no g_vsnprintf() call needed
- the info column
- the top - level RLC PDU item
- another subtree item ( if supplied ) */
static void write_pdu_label_and_info_literal ( proto_item * pdu_ti , proto_item * sub_ti ,
packet_info * pinfo , const char * info_buffer )
{
/* Add to indicated places */
col_append_str ( pinfo - > cinfo , COL_INFO , info_buffer ) ;
proto_item_append_text ( pdu_ti , " %s " , info_buffer ) ;
if ( sub_ti ! = NULL ) {
proto_item_append_text ( sub_ti , " %s " , info_buffer ) ;
}
}
2010-03-09 01:39:08 +00:00
2009-01-05 23:18:00 +00:00
/* Dissect extension headers (common to both UM and AM) */
2010-04-20 15:41:03 +00:00
static int dissect_rlc_lte_extension_header ( tvbuff_t * tvb , packet_info * pinfo _U_ ,
2009-01-05 23:18:00 +00:00
proto_tree * tree ,
2014-12-07 19:54:05 +00:00
int offset ,
rlc_lte_info * p_rlc_lte_info )
2009-01-05 23:18:00 +00:00
{
guint8 isOdd ;
guint64 extension = 1 ;
guint64 length ;
/* Reset this count */
s_number_of_extensions = 0 ;
while ( extension & & ( s_number_of_extensions < MAX_RLC_SDUS ) ) {
proto_tree * extension_part_tree ;
proto_item * extension_part_ti ;
/* Extension part subtree */
extension_part_ti = proto_tree_add_string_format ( tree ,
hf_rlc_lte_extension_part ,
tvb , offset , 2 ,
" " ,
" Extension Part " ) ;
extension_part_tree = proto_item_add_subtree ( extension_part_ti ,
ett_rlc_lte_extension_part ) ;
2014-12-07 19:54:05 +00:00
if ( p_rlc_lte_info - > extendedLiField = = FALSE ) {
isOdd = ( s_number_of_extensions % 2 ) ;
2009-01-05 23:18:00 +00:00
2014-12-07 19:54:05 +00:00
/* Read next extension */
proto_tree_add_bits_ret_val ( extension_part_tree , hf_rlc_lte_extension_e , tvb ,
( offset * 8 ) + ( ( isOdd ) ? 4 : 0 ) ,
1 ,
& extension , ENC_BIG_ENDIAN ) ;
2009-01-05 23:18:00 +00:00
2014-12-07 19:54:05 +00:00
/* Read length field */
proto_tree_add_bits_ret_val ( extension_part_tree , hf_rlc_lte_extension_li , tvb ,
( offset * 8 ) + ( ( isOdd ) ? 5 : 1 ) ,
11 ,
& length , ENC_BIG_ENDIAN ) ;
2009-01-05 23:18:00 +00:00
2014-12-07 19:54:05 +00:00
/* Move on to byte of next extension */
if ( isOdd ) {
offset + = 2 ;
} else {
offset + + ;
}
2009-01-05 23:18:00 +00:00
} else {
2014-12-07 19:54:05 +00:00
/* Read next extension */
proto_tree_add_bits_ret_val ( extension_part_tree , hf_rlc_lte_extension_e , tvb ,
( offset * 8 ) ,
1 ,
& extension , ENC_BIG_ENDIAN ) ;
/* Read length field */
proto_tree_add_bits_ret_val ( extension_part_tree , hf_rlc_lte_extension_li , tvb ,
( offset * 8 ) + 1 ,
15 ,
& length , ENC_BIG_ENDIAN ) ;
/* Move on to byte of next extension */
offset + = 2 ;
2009-01-05 23:18:00 +00:00
}
2010-03-01 22:52:34 +00:00
2014-12-07 19:54:05 +00:00
proto_item_append_text ( extension_part_tree , " (length=%u) " , ( guint16 ) length ) ;
2009-01-05 23:18:00 +00:00
s_lengths [ s_number_of_extensions + + ] = ( guint16 ) length ;
}
/* May need to skip padding after last extension part */
isOdd = ( s_number_of_extensions % 2 ) ;
if ( isOdd ) {
2011-03-16 23:18:59 +00:00
proto_tree_add_item ( tree , hf_rlc_lte_extension_padding ,
2011-10-06 03:35:44 +00:00
tvb , offset + + , 1 , ENC_BIG_ENDIAN ) ;
2009-01-05 23:18:00 +00:00
}
return offset ;
}
/* Show in the info column how many bytes are in the UM/AM PDU, and indicate
whether or not the beginning and end are included in this packet */
static void show_PDU_in_info ( packet_info * pinfo ,
2009-09-15 17:49:58 +00:00
proto_item * top_ti ,
2011-12-01 23:17:17 +00:00
gint32 length ,
2009-01-08 13:28:30 +00:00
gboolean first_includes_start ,
gboolean last_includes_end )
2009-01-05 23:18:00 +00:00
{
/* Reflect this PDU in the info column */
2011-12-01 23:17:17 +00:00
if ( length > 0 ) {
write_pdu_label_and_info ( top_ti , NULL , pinfo ,
" %s%u-byte%s%s " ,
( first_includes_start ) ? " [ " : " .. " ,
length ,
( length > 1 ) ? " s " : " " ,
( last_includes_end ) ? " ] " : " .. " ) ;
}
else {
write_pdu_label_and_info ( top_ti , NULL , pinfo ,
" %sunknown-bytes%s " ,
( first_includes_start ) ? " [ " : " .. " ,
( last_includes_end ) ? " ] " : " .. " ) ;
}
2009-01-05 23:18:00 +00:00
}
2012-12-11 23:20:22 +00:00
/* Show an SDU. If configured, pass to PDCP/RRC/IP dissector */
2011-02-02 23:23:07 +00:00
static void show_PDU_in_tree ( packet_info * pinfo , proto_tree * tree , tvbuff_t * tvb , gint offset , gint length ,
2012-01-23 02:36:46 +00:00
rlc_lte_info * rlc_info , gboolean whole_pdu , rlc_channel_reassembly_info * reassembly_info ,
sequence_analysis_state state )
2009-11-16 15:35:56 +00:00
{
2014-12-07 19:54:05 +00:00
wmem_tree_key_t key [ 3 ] ;
guint32 id ;
rlc_ue_parameters * params ;
2011-02-02 23:23:07 +00:00
/* Add raw data (according to mode) */
proto_item * data_ti = proto_tree_add_item ( tree ,
( rlc_info - > rlcMode = = RLC_AM_MODE ) ?
hf_rlc_lte_am_data :
hf_rlc_lte_um_data ,
2011-11-09 17:33:18 +00:00
tvb , offset , length , ENC_NA ) ;
2009-11-16 15:35:56 +00:00
2012-10-01 19:51:07 +00:00
if ( whole_pdu | | ( reassembly_info ! = NULL ) ) {
if ( ( ( global_rlc_lte_call_pdcp_for_srb ) & & ( rlc_info - > channelType = = CHANNEL_TYPE_SRB ) ) | |
( ( global_rlc_lte_call_pdcp_for_drb ! = PDCP_drb_off ) & & ( rlc_info - > channelType = = CHANNEL_TYPE_DRB ) ) ) {
/* Send whole PDU to PDCP */
2010-07-28 16:58:13 +00:00
2012-10-01 19:51:07 +00:00
/* TODO: made static to avoid compiler warning... */
static tvbuff_t * pdcp_tvb = NULL ;
struct pdcp_lte_info * p_pdcp_lte_info ;
2010-07-28 16:58:13 +00:00
2012-10-01 19:51:07 +00:00
/* Get tvb for passing to LTE PDCP dissector */
if ( reassembly_info = = NULL ) {
2014-06-06 14:35:50 +00:00
pdcp_tvb = tvb_new_subset_length ( tvb , offset , length ) ;
2012-10-01 19:51:07 +00:00
}
else {
/* Get combined tvb. */
pdcp_tvb = reassembly_get_reassembled_tvb ( reassembly_info , tvb , pinfo ) ;
reassembly_show_source ( reassembly_info , tree , tvb , offset ) ;
}
2011-09-06 12:01:28 +00:00
2012-10-01 19:51:07 +00:00
/* Reuse or allocate struct */
2013-11-23 02:20:13 +00:00
p_pdcp_lte_info = ( pdcp_lte_info * ) p_get_proto_data ( wmem_file_scope ( ) , pinfo , proto_pdcp_lte , 0 ) ;
2012-10-01 19:51:07 +00:00
if ( p_pdcp_lte_info = = NULL ) {
2013-08-30 14:49:55 +00:00
p_pdcp_lte_info = wmem_new0 ( wmem_file_scope ( ) , pdcp_lte_info ) ;
2012-10-01 19:51:07 +00:00
/* Store info in packet */
2013-11-23 02:20:13 +00:00
p_add_proto_data ( wmem_file_scope ( ) , pinfo , proto_pdcp_lte , 0 , p_pdcp_lte_info ) ;
2012-10-01 19:51:07 +00:00
}
2009-11-16 15:35:56 +00:00
2012-10-01 19:51:07 +00:00
p_pdcp_lte_info - > ueid = rlc_info - > ueid ;
p_pdcp_lte_info - > channelType = Channel_DCCH ;
p_pdcp_lte_info - > channelId = rlc_info - > channelId ;
p_pdcp_lte_info - > direction = rlc_info - > direction ;
p_pdcp_lte_info - > is_retx = ( state ! = SN_OK ) ;
2011-04-17 21:34:47 +00:00
2012-10-01 19:51:07 +00:00
/* Set plane and sequence number length */
p_pdcp_lte_info - > no_header_pdu = FALSE ;
if ( rlc_info - > channelType = = CHANNEL_TYPE_SRB ) {
p_pdcp_lte_info - > plane = SIGNALING_PLANE ;
p_pdcp_lte_info - > seqnum_length = 5 ;
2010-11-15 23:32:34 +00:00
}
2012-10-01 19:51:07 +00:00
else {
p_pdcp_lte_info - > plane = USER_PLANE ;
switch ( global_rlc_lte_call_pdcp_for_drb ) {
case PDCP_drb_SN_7 :
p_pdcp_lte_info - > seqnum_length = 7 ;
break ;
case PDCP_drb_SN_12 :
p_pdcp_lte_info - > seqnum_length = 12 ;
break ;
case PDCP_drb_SN_15 :
p_pdcp_lte_info - > seqnum_length = 15 ;
break ;
case PDCP_drb_SN_signalled :
/* Use whatever was signalled (e.g. in RRC) */
2014-12-07 19:54:05 +00:00
id = ( rlc_info - > channelId < < 16 ) | rlc_info - > ueid ;
key [ 0 ] . length = 1 ;
key [ 0 ] . key = & id ;
key [ 1 ] . length = 1 ;
key [ 1 ] . key = & PINFO_FD_NUM ( pinfo ) ;
key [ 2 ] . length = 0 ;
key [ 2 ] . key = NULL ;
params = ( rlc_ue_parameters * ) wmem_tree_lookup32_array_le ( ue_parameters_tree , key ) ;
if ( params & & ( params - > id ! = id ) ) {
params = NULL ;
}
p_pdcp_lte_info - > seqnum_length = params ? params - > pdcp_sn_bits : 12 ;
2012-10-01 19:51:07 +00:00
break ;
2009-11-16 15:35:56 +00:00
2012-10-01 19:51:07 +00:00
default :
DISSECTOR_ASSERT ( FALSE ) ;
break ;
}
}
2009-11-16 15:35:56 +00:00
2012-10-01 19:51:07 +00:00
TRY {
2012-10-06 14:59:51 +00:00
call_dissector_only ( pdcp_lte_handle , pdcp_tvb , pinfo , tree , NULL ) ;
2012-10-01 19:51:07 +00:00
}
CATCH_ALL {
}
ENDTRY
PROTO_ITEM_SET_HIDDEN ( data_ti ) ;
2010-07-28 16:58:13 +00:00
}
2012-10-01 19:51:07 +00:00
else if ( global_rlc_lte_call_rrc_for_mcch & & ( rlc_info - > channelType = = CHANNEL_TYPE_MCCH ) ) {
/* Send whole PDU to RRC */
static tvbuff_t * rrc_tvb = NULL ;
volatile dissector_handle_t protocol_handle ;
/* Get tvb for passing to LTE RRC dissector */
if ( reassembly_info = = NULL ) {
2014-06-06 14:35:50 +00:00
rrc_tvb = tvb_new_subset_length ( tvb , offset , length ) ;
2012-10-01 19:51:07 +00:00
}
else {
/* Get combined tvb. */
rrc_tvb = reassembly_get_reassembled_tvb ( reassembly_info , tvb , pinfo ) ;
reassembly_show_source ( reassembly_info , tree , tvb , offset ) ;
}
/* Get dissector handle */
protocol_handle = find_dissector ( " lte_rrc.mcch " ) ;
2010-07-28 16:58:13 +00:00
2012-10-01 19:51:07 +00:00
TRY {
call_dissector_only ( protocol_handle , rrc_tvb , pinfo , tree , NULL ) ;
}
CATCH_ALL {
}
ENDTRY
2012-12-11 23:20:22 +00:00
PROTO_ITEM_SET_HIDDEN ( data_ti ) ;
}
else if ( global_rlc_lte_call_ip_for_mtch & & ( rlc_info - > channelType = = CHANNEL_TYPE_MTCH ) ) {
/* Send whole PDU to IP */
static tvbuff_t * ip_tvb = NULL ;
/* Get tvb for passing to IP dissector */
if ( reassembly_info = = NULL ) {
2014-06-06 14:35:50 +00:00
ip_tvb = tvb_new_subset_length ( tvb , offset , length ) ;
2012-12-11 23:20:22 +00:00
}
else {
/* Get combined tvb. */
ip_tvb = reassembly_get_reassembled_tvb ( reassembly_info , tvb , pinfo ) ;
reassembly_show_source ( reassembly_info , tree , tvb , offset ) ;
}
TRY {
call_dissector_only ( ip_handle , ip_tvb , pinfo , tree , NULL ) ;
}
CATCH_ALL {
}
ENDTRY
2012-10-01 19:51:07 +00:00
PROTO_ITEM_SET_HIDDEN ( data_ti ) ;
}
2009-11-16 15:35:56 +00:00
}
}
2009-04-14 14:38:20 +00:00
/* Hash table functions for RLC channels */
/* Equal keys */
static gint rlc_channel_equal ( gconstpointer v , gconstpointer v2 )
{
2013-03-16 08:12:29 +00:00
const channel_hash_key * val1 = ( const channel_hash_key * ) v ;
const channel_hash_key * val2 = ( const channel_hash_key * ) v2 ;
2009-04-14 14:38:20 +00:00
/* All fields must match */
2012-01-24 03:05:21 +00:00
/* N.B. Currently fits into one word, so could return (*v == *v2)
if we ' re sure they ' re initialised to 0. . . */
2009-04-14 14:38:20 +00:00
return ( ( val1 - > ueId = = val2 - > ueId ) & &
( val1 - > channelType = = val2 - > channelType ) & &
( val1 - > channelId = = val2 - > channelId ) & &
( val1 - > direction = = val2 - > direction ) ) ;
}
/* Compute a hash value for a given key. */
static guint rlc_channel_hash_func ( gconstpointer v )
{
2013-03-16 08:12:29 +00:00
const channel_hash_key * val1 = ( const channel_hash_key * ) v ;
2009-04-14 14:38:20 +00:00
/* TODO: check/reduce multipliers */
return ( ( val1 - > ueId * 1024 ) + ( val1 - > channelType * 64 ) + ( val1 - > channelId * 2 ) + val1 - > direction ) ;
}
2012-01-23 02:36:46 +00:00
/*************************************************************************/
/* Result hash */
typedef struct {
2013-01-04 05:22:43 +00:00
guint32 frameNumber ;
guint32 SN : 10 ;
guint32 channelType : 2 ;
guint32 channelId : 5 ;
guint32 direction : 1 ;
2012-01-23 02:36:46 +00:00
} rlc_result_hash_key ;
2012-11-17 23:41:07 +00:00
/* Compare 2 rlc_result_hash_key structs */
2012-01-23 02:36:46 +00:00
static gint rlc_result_hash_equal ( gconstpointer v , gconstpointer v2 )
2009-04-14 14:38:20 +00:00
{
2012-12-16 00:15:26 +00:00
const rlc_result_hash_key * val1 = ( const rlc_result_hash_key * ) v ;
const rlc_result_hash_key * val2 = ( const rlc_result_hash_key * ) v2 ;
2012-01-23 02:36:46 +00:00
2012-11-17 23:41:07 +00:00
/* All fields (and any padding...) must match */
2012-01-23 02:36:46 +00:00
return ( memcmp ( val1 , val2 , sizeof ( rlc_result_hash_key ) ) = = 0 ) ;
2009-04-14 14:38:20 +00:00
}
/* Compute a hash value for a given key. */
2012-01-23 02:36:46 +00:00
static guint rlc_result_hash_func ( gconstpointer v )
{
2012-12-16 00:15:26 +00:00
const rlc_result_hash_key * val1 = ( const rlc_result_hash_key * ) v ;
2012-01-23 02:36:46 +00:00
2012-12-16 00:15:26 +00:00
/* Got rid of multipliers - no evidence that they reduced collisions */
2012-11-17 23:41:07 +00:00
return val1 - > frameNumber + val1 - > SN +
val1 - > channelType +
val1 - > channelId +
val1 - > direction ;
2012-01-23 02:36:46 +00:00
}
/* Convenience function to get a pointer for the hash_func to work with */
static gpointer get_report_hash_key ( guint16 SN , guint32 frameNumber ,
rlc_lte_info * p_rlc_lte_info ,
gboolean do_persist )
2009-04-14 14:38:20 +00:00
{
2012-01-23 02:36:46 +00:00
static rlc_result_hash_key key ;
rlc_result_hash_key * p_key ;
/* Only allocate a struct when will be adding entry */
if ( do_persist ) {
2013-08-30 14:49:55 +00:00
p_key = wmem_new0 ( wmem_file_scope ( ) , rlc_result_hash_key ) ;
2012-01-23 02:36:46 +00:00
}
else {
memset ( & key , 0 , sizeof ( rlc_result_hash_key ) ) ;
p_key = & key ;
}
/* Fill in details, and return pointer */
p_key - > frameNumber = frameNumber ;
p_key - > SN = SN ;
p_key - > channelType = p_rlc_lte_info - > channelType ;
p_key - > channelId = p_rlc_lte_info - > channelId ;
p_key - > direction = p_rlc_lte_info - > direction ;
return p_key ;
2009-04-14 14:38:20 +00:00
}
2013-07-26 17:07:57 +00:00
static void checkFIconsistency ( sequence_analysis_report * p ,
rlc_lte_info * p_rlc_lte_info ,
gboolean newSegmentStarted ,
proto_tree * seqnum_tree ,
packet_info * pinfo , tvbuff_t * tvb )
{
proto_item * ti ;
2009-04-14 14:38:20 +00:00
2013-07-26 17:07:57 +00:00
if ( p - > previousSegmentIncomplete ) {
/* Previous segment was incomplete, so this PDU should continue it */
if ( newSegmentStarted ) {
ti = proto_tree_add_boolean ( seqnum_tree , hf_rlc_lte_sequence_analysis_framing_info_correct ,
tvb , 0 , 0 , FALSE ) ;
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , ti , & ei_rlc_lte_sequence_analysis_last_segment_not_continued ,
2013-07-26 17:07:57 +00:00
" Last segment of previous PDU was not continued for UE %u (%s-%u) " ,
p_rlc_lte_info - > ueid ,
val_to_str_const ( p_rlc_lte_info - > channelType , rlc_channel_type_vals , " Unknown " ) ,
p_rlc_lte_info - > channelId ) ;
}
else {
ti = proto_tree_add_boolean ( seqnum_tree , hf_rlc_lte_sequence_analysis_framing_info_correct ,
tvb , 0 , 0 , TRUE ) ;
PROTO_ITEM_SET_HIDDEN ( ti ) ;
}
}
else {
/* Previous segment was complete, so this PDU should start a new one */
if ( ! newSegmentStarted ) {
ti = proto_tree_add_boolean ( seqnum_tree , hf_rlc_lte_sequence_analysis_framing_info_correct ,
tvb , 0 , 0 , FALSE ) ;
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , ti , & ei_rlc_lte_sequence_analysis_last_segment_complete ,
2013-07-26 17:07:57 +00:00
" Last segment of previous PDU was complete, but new segment was not started on UE %u (%s-%u) " ,
p_rlc_lte_info - > ueid ,
val_to_str_const ( p_rlc_lte_info - > channelType , rlc_channel_type_vals , " Unknown " ) ,
p_rlc_lte_info - > channelId ) ;
}
else {
ti = proto_tree_add_boolean ( seqnum_tree , hf_rlc_lte_sequence_analysis_framing_info_correct ,
tvb , 0 , 0 , TRUE ) ;
PROTO_ITEM_SET_HIDDEN ( ti ) ;
}
}
PROTO_ITEM_SET_GENERATED ( ti ) ;
}
2012-01-23 02:36:46 +00:00
2009-04-14 14:38:20 +00:00
/* Add to the tree values associated with sequence analysis for this frame */
2012-01-23 02:36:46 +00:00
static void addChannelSequenceInfo ( sequence_analysis_report * p ,
2011-07-26 10:16:02 +00:00
gboolean isControlFrame ,
2010-03-01 22:52:34 +00:00
rlc_lte_info * p_rlc_lte_info ,
2010-02-28 02:18:35 +00:00
guint16 sequenceNumber ,
2009-04-15 02:28:55 +00:00
gboolean newSegmentStarted ,
2010-02-28 18:42:41 +00:00
rlc_lte_tap_info * tap_info ,
2009-04-14 14:38:20 +00:00
packet_info * pinfo , proto_tree * tree , tvbuff_t * tvb )
{
proto_tree * seqnum_tree ;
proto_item * seqnum_ti ;
proto_item * ti ;
/* Create subtree */
seqnum_ti = proto_tree_add_string_format ( tree ,
hf_rlc_lte_sequence_analysis ,
tvb , 0 , 0 ,
2010-03-02 18:40:34 +00:00
" " , " Sequence Analysis " ) ;
2009-04-14 14:38:20 +00:00
seqnum_tree = proto_item_add_subtree ( seqnum_ti ,
ett_rlc_lte_sequence_analysis ) ;
PROTO_ITEM_SET_GENERATED ( seqnum_ti ) ;
2012-01-23 02:36:46 +00:00
if ( p - > previousFrameNum ! = 0 ) {
ti = proto_tree_add_uint ( seqnum_tree , hf_rlc_lte_sequence_analysis_previous_frame ,
tvb , 0 , 0 , p - > previousFrameNum ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
}
2010-03-01 22:52:34 +00:00
switch ( p_rlc_lte_info - > rlcMode ) {
2010-02-28 02:18:35 +00:00
case RLC_AM_MODE :
2009-04-14 14:38:20 +00:00
2010-02-28 02:18:35 +00:00
/********************************************/
/* AM */
/********************************************/
2010-03-04 17:49:51 +00:00
2010-06-25 23:04:16 +00:00
switch ( p - > state ) {
2010-02-28 02:18:35 +00:00
case SN_OK :
2011-07-26 10:16:02 +00:00
if ( isControlFrame ) {
return ;
}
2010-02-28 20:43:04 +00:00
ti = proto_tree_add_boolean ( seqnum_tree , hf_rlc_lte_sequence_analysis_ok ,
tvb , 0 , 0 , TRUE ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
2012-09-19 16:56:59 +00:00
proto_item_append_text ( seqnum_ti , " - OK " ) ;
2012-01-23 02:36:46 +00:00
/* Link to next SN in channel (if known) */
if ( p - > nextFrameNum ! = 0 ) {
proto_tree_add_uint ( seqnum_tree , hf_rlc_lte_sequence_analysis_next_frame ,
tvb , 0 , 0 , p - > nextFrameNum ) ;
}
2013-07-26 17:07:57 +00:00
/* Correct sequence number, so check frame indication bits consistent */
/* Deactivated for now as it gets confused by resegmentation */
/* checkFIconsistency(p, p_rlc_lte_info, newSegmentStarted, seqnum_tree, pinfo, tvb); */
2010-02-28 02:18:35 +00:00
break ;
2010-03-01 22:52:34 +00:00
case SN_MAC_Retx :
2011-07-26 10:16:02 +00:00
if ( isControlFrame ) {
return ;
}
2010-03-01 22:52:34 +00:00
ti = proto_tree_add_boolean ( seqnum_tree , hf_rlc_lte_sequence_analysis_ok ,
tvb , 0 , 0 , FALSE ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
ti = proto_tree_add_boolean ( seqnum_tree , hf_rlc_lte_sequence_analysis_mac_retx ,
tvb , 0 , 0 , TRUE ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , ti , & ei_rlc_lte_sequence_analysis_mac_retx ,
2012-11-17 23:41:07 +00:00
" AM Frame retransmitted for %s on UE %u - due to MAC retx! (%s-%u) " ,
2010-03-14 16:36:41 +00:00
val_to_str_const ( p_rlc_lte_info - > direction , direction_vals , " Unknown " ) ,
2012-11-17 23:41:07 +00:00
p_rlc_lte_info - > ueid ,
val_to_str_const ( p_rlc_lte_info - > channelType , rlc_channel_type_vals , " Unknown " ) ,
p_rlc_lte_info - > channelId ) ;
2012-01-22 02:55:47 +00:00
proto_item_append_text ( seqnum_ti , " - MAC retx of SN %u " , p - > firstSN ) ;
2010-03-01 22:52:34 +00:00
break ;
2010-02-28 02:18:35 +00:00
case SN_Retx :
2011-07-26 10:16:02 +00:00
if ( isControlFrame ) {
return ;
}
2010-02-28 20:43:04 +00:00
ti = proto_tree_add_boolean ( seqnum_tree , hf_rlc_lte_sequence_analysis_ok ,
tvb , 0 , 0 , FALSE ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
2010-02-28 02:18:35 +00:00
ti = proto_tree_add_boolean ( seqnum_tree , hf_rlc_lte_sequence_analysis_retx ,
2010-02-28 18:42:41 +00:00
tvb , 0 , 0 , TRUE ) ;
2010-02-28 02:18:35 +00:00
PROTO_ITEM_SET_GENERATED ( ti ) ;
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , ti , & ei_rlc_lte_sequence_analysis_retx ,
2012-11-17 23:41:07 +00:00
" AM Frame retransmitted for %s on UE %u - most likely in response to NACK (%s-%u) " ,
2010-03-14 16:36:41 +00:00
val_to_str_const ( p_rlc_lte_info - > direction , direction_vals , " Unknown " ) ,
2012-11-17 23:41:07 +00:00
p_rlc_lte_info - > ueid ,
val_to_str_const ( p_rlc_lte_info - > channelType , rlc_channel_type_vals , " Unknown " ) ,
p_rlc_lte_info - > channelId ) ;
2010-02-28 02:18:35 +00:00
proto_item_append_text ( seqnum_ti , " - SN %u retransmitted " , p - > firstSN ) ;
break ;
2010-02-28 18:42:41 +00:00
2010-02-28 02:18:35 +00:00
case SN_Repeated :
2011-07-26 10:16:02 +00:00
if ( isControlFrame ) {
return ;
}
2010-02-28 20:43:04 +00:00
ti = proto_tree_add_boolean ( seqnum_tree , hf_rlc_lte_sequence_analysis_ok ,
tvb , 0 , 0 , FALSE ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
2010-02-28 02:18:35 +00:00
ti = proto_tree_add_boolean ( seqnum_tree , hf_rlc_lte_sequence_analysis_repeated ,
tvb , 0 , 0 , TRUE ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , ti , & ei_rlc_lte_sequence_analysis_repeated ,
2012-11-17 23:41:07 +00:00
" AM SN Repeated for %s for UE %u - probably because didn't receive Status PDU? (%s-%u) " ,
2010-03-14 16:36:41 +00:00
val_to_str_const ( p_rlc_lte_info - > direction , direction_vals , " Unknown " ) ,
2012-11-17 23:41:07 +00:00
p_rlc_lte_info - > ueid ,
val_to_str_const ( p_rlc_lte_info - > channelType , rlc_channel_type_vals , " Unknown " ) ,
p_rlc_lte_info - > channelId ) ;
2012-01-22 02:55:47 +00:00
proto_item_append_text ( seqnum_ti , " - SN %u Repeated " , p - > firstSN ) ;
2010-02-28 02:18:35 +00:00
break ;
2010-02-28 18:42:41 +00:00
2010-02-28 02:18:35 +00:00
case SN_Missing :
2011-07-26 10:16:02 +00:00
if ( isControlFrame ) {
return ;
}
2010-02-28 20:43:04 +00:00
ti = proto_tree_add_boolean ( seqnum_tree , hf_rlc_lte_sequence_analysis_ok ,
tvb , 0 , 0 , FALSE ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
2010-02-28 02:18:35 +00:00
ti = proto_tree_add_boolean ( seqnum_tree , hf_rlc_lte_sequence_analysis_skipped ,
tvb , 0 , 0 , TRUE ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
if ( p - > lastSN ! = p - > firstSN ) {
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , ti , & ei_rlc_lte_am_sn_missing ,
2012-11-17 23:41:07 +00:00
" AM SNs (%u to %u) missing for %s on UE %u (%s-%u) " ,
2010-03-04 17:49:51 +00:00
p - > firstSN , p - > lastSN ,
2010-03-14 16:36:41 +00:00
val_to_str_const ( p_rlc_lte_info - > direction , direction_vals , " Unknown " ) ,
2012-11-17 23:41:07 +00:00
p_rlc_lte_info - > ueid ,
val_to_str_const ( p_rlc_lte_info - > channelType , rlc_channel_type_vals , " Unknown " ) ,
p_rlc_lte_info - > channelId ) ;
2010-02-28 02:18:35 +00:00
proto_item_append_text ( seqnum_ti , " - SNs missing (%u to %u) " ,
p - > firstSN , p - > lastSN ) ;
2011-09-22 15:28:46 +00:00
tap_info - > missingSNs = ( ( 1024 + p - > lastSN - p - > firstSN ) % 1024 ) + 1 ;
2010-02-28 02:18:35 +00:00
}
else {
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , ti , & ei_rlc_lte_am_sn_missing ,
2012-11-17 23:41:07 +00:00
" AM SN (%u) missing for %s on UE %u (%s-%u) " ,
2010-03-04 17:49:51 +00:00
p - > firstSN ,
2010-03-14 16:36:41 +00:00
val_to_str_const ( p_rlc_lte_info - > direction , direction_vals , " Unknown " ) ,
2012-11-17 23:41:07 +00:00
p_rlc_lte_info - > ueid ,
val_to_str_const ( p_rlc_lte_info - > channelType , rlc_channel_type_vals , " Unknown " ) ,
p_rlc_lte_info - > channelId ) ;
2012-01-22 02:55:47 +00:00
proto_item_append_text ( seqnum_ti , " - SN missing (%u) " , p - > firstSN ) ;
2010-02-28 18:42:41 +00:00
tap_info - > missingSNs = 1 ;
2010-02-28 02:18:35 +00:00
}
break ;
2011-05-19 01:05:26 +00:00
case ACK_Out_of_Window :
2011-07-26 10:16:02 +00:00
if ( ! isControlFrame ) {
return ;
}
2011-05-19 01:05:26 +00:00
/* Not OK */
ti = proto_tree_add_boolean ( seqnum_tree , hf_rlc_lte_sequence_analysis_ok ,
tvb , 0 , 0 , FALSE ) ;
/* Out of range */
PROTO_ITEM_SET_GENERATED ( ti ) ;
ti = proto_tree_add_boolean ( seqnum_tree , hf_rlc_lte_sequence_analysis_ack_out_of_range ,
tvb , 0 , 0 , TRUE ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
2011-07-26 10:16:02 +00:00
2011-05-19 01:05:26 +00:00
/* Link back to last seen SN in other direction */
ti = proto_tree_add_uint ( seqnum_tree , hf_rlc_lte_sequence_analysis_ack_out_of_range_opposite_frame ,
tvb , 0 , 0 , p - > previousFrameNum ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
/* Expert error */
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , ti , & ei_rlc_lte_sequence_analysis_ack_out_of_range_opposite_frame ,
2012-11-17 23:41:07 +00:00
" AM ACK for SN %u - but last received SN in other direction is %u for UE %u (%s-%u) " ,
2011-05-19 01:05:26 +00:00
p - > firstSN , p - > sequenceExpected ,
2012-11-17 23:41:07 +00:00
p_rlc_lte_info - > ueid ,
val_to_str_const ( p_rlc_lte_info - > channelType , rlc_channel_type_vals , " Unknown " ) ,
p_rlc_lte_info - > channelId ) ;
2011-05-19 01:05:26 +00:00
proto_item_append_text ( seqnum_ti , " - ACK SN %u Outside Rx Window - last received SN is %u " ,
p - > firstSN , p - > sequenceExpected ) ;
break ;
2012-01-23 02:36:46 +00:00
default :
return ;
2009-04-14 14:38:20 +00:00
}
2010-02-28 02:18:35 +00:00
break ;
case RLC_UM_MODE :
/********************************************/
/* UM */
/********************************************/
/* Expected sequence number */
ti = proto_tree_add_uint ( seqnum_tree , hf_rlc_lte_sequence_analysis_expected_sn ,
tvb , 0 , 0 , p - > sequenceExpected ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
2012-10-17 04:01:01 +00:00
if ( p - > sequenceExpectedCorrect ) {
PROTO_ITEM_SET_HIDDEN ( ti ) ;
}
2010-03-01 22:52:34 +00:00
2010-02-28 02:18:35 +00:00
if ( ! p - > sequenceExpectedCorrect ) {
2010-06-25 23:04:16 +00:00
/* Work out SN wrap (in case needed below) */
guint16 snLimit ;
if ( p_rlc_lte_info - > UMSequenceNumberLength = = 5 ) {
snLimit = 32 ;
}
else {
snLimit = 1024 ;
}
2010-06-28 10:50:03 +00:00
2010-06-25 23:04:16 +00:00
switch ( p - > state ) {
case SN_Missing :
ti = proto_tree_add_boolean ( seqnum_tree , hf_rlc_lte_sequence_analysis_ok ,
tvb , 0 , 0 , FALSE ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
ti = proto_tree_add_boolean ( seqnum_tree , hf_rlc_lte_sequence_analysis_skipped ,
tvb , 0 , 0 , TRUE ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
if ( p - > lastSN ! = p - > firstSN ) {
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , ti , & ei_rlc_lte_um_sn_missing ,
2013-09-05 01:05:16 +00:00
" UM SNs (%u to %u) missing for %s on UE %u (%s-%u) " ,
2010-06-25 23:04:16 +00:00
p - > firstSN , p - > lastSN ,
val_to_str_const ( p_rlc_lte_info - > direction , direction_vals , " Unknown " ) ,
2012-11-17 23:41:07 +00:00
p_rlc_lte_info - > ueid ,
val_to_str_const ( p_rlc_lte_info - > channelType , rlc_channel_type_vals , " Unknown " ) ,
p_rlc_lte_info - > channelId ) ;
2010-06-25 23:04:16 +00:00
proto_item_append_text ( seqnum_ti , " - SNs missing (%u to %u) " ,
p - > firstSN , p - > lastSN ) ;
2011-09-22 15:28:46 +00:00
tap_info - > missingSNs = ( ( snLimit + p - > lastSN - p - > firstSN ) % snLimit ) + 1 ;
2010-06-25 23:04:16 +00:00
}
else {
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , ti , & ei_rlc_lte_um_sn_missing ,
2012-11-17 23:41:07 +00:00
" UM SN (%u) missing for %s on UE %u (%s-%u) " ,
2010-06-25 23:04:16 +00:00
p - > firstSN ,
val_to_str_const ( p_rlc_lte_info - > direction , direction_vals , " Unknown " ) ,
2012-11-17 23:41:07 +00:00
p_rlc_lte_info - > ueid ,
val_to_str_const ( p_rlc_lte_info - > channelType , rlc_channel_type_vals , " Unknown " ) ,
p_rlc_lte_info - > channelId ) ;
2010-06-25 23:04:16 +00:00
proto_item_append_text ( seqnum_ti , " - SN missing (%u) " ,
p - > firstSN ) ;
tap_info - > missingSNs = 1 ;
}
break ;
2010-06-28 10:50:03 +00:00
2010-06-25 23:04:16 +00:00
case SN_Repeated :
ti = proto_tree_add_boolean ( seqnum_tree , hf_rlc_lte_sequence_analysis_ok ,
tvb , 0 , 0 , FALSE ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
ti = proto_tree_add_boolean ( seqnum_tree , hf_rlc_lte_sequence_analysis_repeated ,
tvb , 0 , 0 , TRUE ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , ti , & ei_rlc_lte_um_sn_repeated ,
2012-11-17 23:41:07 +00:00
" UM SN (%u) repeated for %s for UE %u (%s-%u) " ,
2010-06-25 23:04:16 +00:00
p - > firstSN ,
val_to_str_const ( p_rlc_lte_info - > direction , direction_vals , " Unknown " ) ,
2012-11-17 23:41:07 +00:00
p_rlc_lte_info - > ueid ,
val_to_str_const ( p_rlc_lte_info - > channelType , rlc_channel_type_vals , " Unknown " ) ,
p_rlc_lte_info - > channelId ) ;
2010-06-25 23:04:16 +00:00
proto_item_append_text ( seqnum_ti , " - SN %u Repeated " ,
2010-09-20 17:01:22 +00:00
p - > firstSN ) ;
2010-06-25 23:04:16 +00:00
break ;
2010-06-28 10:50:03 +00:00
case SN_MAC_Retx :
ti = proto_tree_add_boolean ( seqnum_tree , hf_rlc_lte_sequence_analysis_ok ,
tvb , 0 , 0 , FALSE ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
ti = proto_tree_add_boolean ( seqnum_tree , hf_rlc_lte_sequence_analysis_mac_retx ,
tvb , 0 , 0 , TRUE ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , ti , & ei_rlc_lte_sequence_analysis_mac_retx ,
2012-11-17 23:41:07 +00:00
" UM Frame retransmitted for %s on UE %u - due to MAC retx! (%s-%u) " ,
2010-06-28 10:50:03 +00:00
val_to_str_const ( p_rlc_lte_info - > direction , direction_vals , " Unknown " ) ,
2012-11-17 23:41:07 +00:00
p_rlc_lte_info - > ueid ,
val_to_str_const ( p_rlc_lte_info - > channelType , rlc_channel_type_vals , " Unknown " ) ,
p_rlc_lte_info - > channelId ) ;
2010-06-28 10:50:03 +00:00
break ;
2010-06-25 23:04:16 +00:00
default :
/* Incorrect sequence number */
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , ti , & ei_rlc_lte_wrong_sequence_number ,
2012-11-17 23:41:07 +00:00
" Wrong Sequence Number for %s on UE %u - got %u, expected %u (%s-%u) " ,
2010-06-25 23:04:16 +00:00
val_to_str_const ( p_rlc_lte_info - > direction , direction_vals , " Unknown " ) ,
2012-11-17 23:41:07 +00:00
p_rlc_lte_info - > ueid , sequenceNumber , p - > sequenceExpected ,
val_to_str_const ( p_rlc_lte_info - > channelType , rlc_channel_type_vals , " Unknown " ) ,
p_rlc_lte_info - > channelId ) ;
2010-06-25 23:04:16 +00:00
break ;
}
2009-04-14 14:38:20 +00:00
}
else {
2010-02-28 02:18:35 +00:00
/* Correct sequence number, so check frame indication bits consistent */
2013-07-26 17:07:57 +00:00
checkFIconsistency ( p , p_rlc_lte_info , newSegmentStarted , seqnum_tree , pinfo , tvb ) ;
2012-10-17 04:01:01 +00:00
/* Set OK here! */
ti = proto_tree_add_boolean ( seqnum_tree , hf_rlc_lte_sequence_analysis_ok ,
tvb , 0 , 0 , TRUE ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
proto_item_append_text ( seqnum_ti , " - OK " ) ;
}
/* Next channel frame */
if ( p - > nextFrameNum ! = 0 ) {
ti = proto_tree_add_uint ( seqnum_tree , hf_rlc_lte_sequence_analysis_next_frame ,
tvb , 0 , 0 , p - > nextFrameNum ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
2009-04-14 14:38:20 +00:00
}
}
}
/* Update the channel status and set report for this frame */
2012-01-23 02:36:46 +00:00
static sequence_analysis_state checkChannelSequenceInfo ( packet_info * pinfo , tvbuff_t * tvb ,
rlc_lte_info * p_rlc_lte_info ,
gboolean isControlFrame ,
guint8 number_of_segments ,
guint16 firstSegmentOffset ,
guint16 firstSegmentLength ,
guint16 lastSegmentOffset ,
guint16 sequenceNumber ,
gboolean first_includes_start , gboolean last_includes_end ,
gboolean is_resegmented _U_ ,
rlc_lte_tap_info * tap_info ,
proto_tree * tree )
2009-04-14 14:38:20 +00:00
{
2012-01-23 02:36:46 +00:00
channel_hash_key channel_key ;
channel_hash_key * p_channel_key ;
channel_sequence_analysis_status * p_channel_status ;
sequence_analysis_report * p_report_in_frame = NULL ;
2010-03-02 18:40:34 +00:00
gboolean createdChannel = FALSE ;
2010-02-28 02:18:35 +00:00
guint16 expectedSequenceNumber = 0 ;
2010-06-25 23:04:16 +00:00
guint16 snLimit = 0 ;
2009-04-14 14:38:20 +00:00
/* If find stat_report_in_frame already, use that and get out */
if ( pinfo - > fd - > flags . visited ) {
2012-01-23 02:36:46 +00:00
p_report_in_frame = ( sequence_analysis_report * ) g_hash_table_lookup ( sequence_analysis_report_hash ,
get_report_hash_key ( sequenceNumber ,
pinfo - > fd - > num ,
p_rlc_lte_info ,
FALSE ) ) ;
2009-04-14 14:38:20 +00:00
if ( p_report_in_frame ! = NULL ) {
2011-07-26 10:16:02 +00:00
addChannelSequenceInfo ( p_report_in_frame , isControlFrame , p_rlc_lte_info ,
2010-02-28 02:18:35 +00:00
sequenceNumber , first_includes_start ,
2010-02-28 18:42:41 +00:00
tap_info , pinfo , tree , tvb ) ;
2012-01-23 02:36:46 +00:00
return p_report_in_frame - > state ;
2009-04-14 14:38:20 +00:00
}
2012-01-22 02:55:47 +00:00
/* Don't just give up here... */
2009-04-14 14:38:20 +00:00
}
/**************************************************/
/* Create or find an entry for this channel state */
channel_key . ueId = p_rlc_lte_info - > ueid ;
channel_key . channelType = p_rlc_lte_info - > channelType ;
channel_key . channelId = p_rlc_lte_info - > channelId ;
channel_key . direction = p_rlc_lte_info - > direction ;
/* Do the table lookup */
2012-01-23 02:36:46 +00:00
p_channel_status = ( channel_sequence_analysis_status * ) g_hash_table_lookup ( sequence_analysis_channel_hash , & channel_key ) ;
2009-04-14 14:38:20 +00:00
/* Create table entry if necessary */
if ( p_channel_status = = NULL ) {
createdChannel = TRUE ;
2011-05-05 06:55:12 +00:00
/* Allocate a new value and duplicate key contents */
2013-08-30 14:49:55 +00:00
p_channel_status = wmem_new0 ( wmem_file_scope ( ) , channel_sequence_analysis_status ) ;
p_channel_key = ( channel_hash_key * ) wmem_memdup ( wmem_file_scope ( ) , & channel_key , sizeof ( channel_hash_key ) ) ;
2009-04-14 14:38:20 +00:00
2010-02-28 02:18:35 +00:00
/* Set mode */
p_channel_status - > rlcMode = p_rlc_lte_info - > rlcMode ;
2009-04-14 14:38:20 +00:00
/* Add entry */
2012-01-23 02:36:46 +00:00
g_hash_table_insert ( sequence_analysis_channel_hash , p_channel_key , p_channel_status ) ;
2009-04-14 14:38:20 +00:00
}
/* Create space for frame state_report */
2013-08-30 14:49:55 +00:00
p_report_in_frame = wmem_new0 ( wmem_file_scope ( ) , sequence_analysis_report ) ;
2009-04-14 14:38:20 +00:00
2012-01-22 02:55:47 +00:00
/* Deal with according to channel mode */
2010-02-28 02:18:35 +00:00
switch ( p_channel_status - > rlcMode ) {
case RLC_UM_MODE :
2010-06-28 10:50:03 +00:00
if ( p_rlc_lte_info - > UMSequenceNumberLength = = 5 ) {
snLimit = 32 ;
}
else {
snLimit = 1024 ;
}
2010-02-28 02:18:35 +00:00
/* Work out expected sequence number */
if ( ! createdChannel ) {
expectedSequenceNumber = ( p_channel_status - > previousSequenceNumber + 1 ) % snLimit ;
}
2011-06-20 08:55:51 +00:00
else {
/* Whatever we got is fine.. */
expectedSequenceNumber = sequenceNumber ;
}
2010-02-28 02:18:35 +00:00
2013-07-25 17:33:57 +00:00
if ( ( sequenceNumber = = 0 ) & &
( ( p_rlc_lte_info - > channelType = = CHANNEL_TYPE_MCCH ) | | ( p_rlc_lte_info - > channelType = = CHANNEL_TYPE_MTCH ) ) ) {
/* With eMBMS, SN restarts to 0 at each MCH Scheduling Period so we cannot deduce easily whether
there was a PDU loss or not without analysing the Frame Indicator ; assume no loss when seeing 0 */
expectedSequenceNumber = 0 ;
}
2010-02-28 02:18:35 +00:00
/* Set report for this frame */
/* For UM, sequence number is always expectedSequence number */
p_report_in_frame - > sequenceExpectedCorrect = ( sequenceNumber = = expectedSequenceNumber ) ;
2010-06-25 23:04:16 +00:00
/* For wrong sequence number... */
if ( ! p_report_in_frame - > sequenceExpectedCorrect ) {
2010-06-28 10:50:03 +00:00
/* Don't get confused by MAC (HARQ) retx */
if ( is_mac_lte_frame_retx ( pinfo , p_rlc_lte_info - > direction ) ) {
p_report_in_frame - > state = SN_MAC_Retx ;
2011-05-19 01:05:26 +00:00
p_report_in_frame - > firstSN = sequenceNumber ;
2013-05-06 21:52:49 +00:00
/* No channel state to update */
break ;
2010-06-28 10:50:03 +00:00
}
2010-06-25 23:04:16 +00:00
/* Frames are not missing if we get an earlier sequence number again */
2011-06-20 08:55:51 +00:00
/* TODO: taking time into account would give better idea of whether missing or repeated... */
2013-07-25 17:33:57 +00:00
else if ( ( p_rlc_lte_info - > channelType = = CHANNEL_TYPE_MCCH ) | | ( p_rlc_lte_info - > channelType = = CHANNEL_TYPE_MTCH ) | |
( ( ( snLimit + sequenceNumber - expectedSequenceNumber ) % snLimit ) < 10 ) ) {
2013-05-06 21:52:49 +00:00
reassembly_destroy ( p_channel_status ) ;
2011-06-20 08:55:51 +00:00
p_report_in_frame - > state = SN_Missing ;
tap_info - > missingSNs = ( snLimit + sequenceNumber - expectedSequenceNumber ) % snLimit ;
p_report_in_frame - > firstSN = expectedSequenceNumber ;
p_report_in_frame - > lastSN = ( snLimit + sequenceNumber - 1 ) % snLimit ;
2011-02-28 12:26:26 +00:00
2011-06-20 08:55:51 +00:00
p_report_in_frame - > sequenceExpected = expectedSequenceNumber ;
p_report_in_frame - > previousFrameNum = p_channel_status - > previousFrameNum ;
p_report_in_frame - > previousSegmentIncomplete = p_channel_status - > previousSegmentIncomplete ;
2010-10-10 20:39:00 +00:00
2010-06-28 10:50:03 +00:00
/* Update channel status to remember *this* frame */
p_channel_status - > previousFrameNum = pinfo - > fd - > num ;
p_channel_status - > previousSequenceNumber = sequenceNumber ;
p_channel_status - > previousSegmentIncomplete = ! last_includes_end ;
2010-06-25 23:04:16 +00:00
}
else {
/* An SN has been repeated */
p_report_in_frame - > state = SN_Repeated ;
p_report_in_frame - > firstSN = sequenceNumber ;
2010-06-28 10:50:03 +00:00
p_report_in_frame - > sequenceExpected = expectedSequenceNumber ;
p_report_in_frame - > previousFrameNum = p_channel_status - > previousFrameNum ;
2010-06-25 23:04:16 +00:00
}
}
2010-06-28 10:50:03 +00:00
else {
/* SN was OK */
p_report_in_frame - > sequenceExpected = expectedSequenceNumber ;
p_report_in_frame - > previousFrameNum = p_channel_status - > previousFrameNum ;
p_report_in_frame - > previousSegmentIncomplete = p_channel_status - > previousSegmentIncomplete ;
/* Update channel status to remember *this* frame */
p_channel_status - > previousFrameNum = pinfo - > fd - > num ;
p_channel_status - > previousSequenceNumber = sequenceNumber ;
p_channel_status - > previousSegmentIncomplete = ! last_includes_end ;
2011-09-06 12:01:28 +00:00
if ( p_channel_status - > reassembly_info ) {
/* Add next segment to reassembly info */
reassembly_add_segment ( p_channel_status , sequenceNumber , pinfo - > fd - > num ,
tvb , firstSegmentOffset , firstSegmentLength ) ;
/* The end of existing reassembly? */
if ( ! first_includes_start & &
( ( number_of_segments > 1 ) | | last_includes_end ) ) {
2012-01-23 02:36:46 +00:00
reassembly_record ( p_channel_status , pinfo , sequenceNumber , p_rlc_lte_info ) ;
2011-09-06 12:01:28 +00:00
reassembly_destroy ( p_channel_status ) ;
}
}
/* The start of a new reassembly? */
if ( ! last_includes_end & &
( ( number_of_segments > 1 ) | | first_includes_start ) ) {
2014-05-05 20:32:33 +00:00
guint16 lastSegmentLength = tvb_reported_length ( tvb ) - lastSegmentOffset ;
2011-09-06 12:01:28 +00:00
if ( global_rlc_lte_reassembly ) {
reassembly_reset ( p_channel_status ) ;
reassembly_add_segment ( p_channel_status , sequenceNumber ,
pinfo - > fd - > num ,
tvb , lastSegmentOffset , lastSegmentLength ) ;
}
}
2012-02-03 10:42:01 +00:00
if ( p_report_in_frame - > previousFrameNum ! = 0 ) {
/* Get report for previous frame */
sequence_analysis_report * p_previous_report ;
if ( p_rlc_lte_info - > UMSequenceNumberLength = = 5 ) {
snLimit = 32 ;
}
else {
snLimit = 1024 ;
}
2012-11-17 23:41:07 +00:00
/* Look up report for previous SN */
2012-02-03 10:42:01 +00:00
p_previous_report = ( sequence_analysis_report * ) g_hash_table_lookup ( sequence_analysis_report_hash ,
get_report_hash_key ( ( sequenceNumber + snLimit - 1 ) % snLimit ,
p_report_in_frame - > previousFrameNum ,
p_rlc_lte_info ,
FALSE ) ) ;
/* It really shouldn't be NULL... */
if ( p_previous_report ! = NULL ) {
/* Point it forward to this one */
p_previous_report - > nextFrameNum = pinfo - > fd - > num ;
}
}
2010-06-28 10:50:03 +00:00
}
2010-02-28 02:18:35 +00:00
break ;
case RLC_AM_MODE :
/* Work out expected sequence number */
if ( ! createdChannel ) {
expectedSequenceNumber = ( p_channel_status - > previousSequenceNumber + 1 ) % 1024 ;
}
2012-01-22 02:55:47 +00:00
else {
/* Whatever we got is fine.. */
expectedSequenceNumber = sequenceNumber ;
}
2010-02-28 02:18:35 +00:00
/* For AM, may be:
- expected Sequence number OR
- previous frame repeated
- old SN being sent ( in response to NACK )
- new SN , but with frames missed out
Assume window whose front is at expectedSequenceNumber */
2010-03-01 22:52:34 +00:00
/* First of all, check to see whether frame is judged to be MAC Retx */
if ( is_mac_lte_frame_retx ( pinfo , p_rlc_lte_info - > direction ) ) {
/* Just report that this is a MAC Retx */
2010-06-25 23:04:16 +00:00
p_report_in_frame - > state = SN_MAC_Retx ;
2011-05-19 01:05:26 +00:00
p_report_in_frame - > firstSN = sequenceNumber ;
2010-03-01 22:52:34 +00:00
/* No channel state to update */
2011-09-06 12:01:28 +00:00
break ;
2010-03-01 22:52:34 +00:00
}
2011-09-06 12:01:28 +00:00
if ( sequenceNumber ! = expectedSequenceNumber ) {
2012-01-22 02:55:47 +00:00
/* Don't trash reassembly info if this looks like a close retx... */
if ( ( ( 1024 + sequenceNumber - expectedSequenceNumber ) % 1024 ) < 50 ) {
reassembly_destroy ( p_channel_status ) ;
}
2011-09-06 12:01:28 +00:00
}
2010-02-28 02:18:35 +00:00
2011-09-06 12:01:28 +00:00
/* Expected? */
if ( sequenceNumber = = expectedSequenceNumber ) {
2010-02-28 02:18:35 +00:00
/* Set report for this frame */
p_report_in_frame - > sequenceExpectedCorrect = TRUE ;
p_report_in_frame - > sequenceExpected = expectedSequenceNumber ;
p_report_in_frame - > previousFrameNum = p_channel_status - > previousFrameNum ;
p_report_in_frame - > previousSegmentIncomplete = p_channel_status - > previousSegmentIncomplete ;
2010-06-25 23:04:16 +00:00
p_report_in_frame - > state = SN_OK ;
2010-02-28 02:18:35 +00:00
/* Update channel status */
p_channel_status - > previousSequenceNumber = sequenceNumber ;
p_channel_status - > previousFrameNum = pinfo - > fd - > num ;
p_channel_status - > previousSegmentIncomplete = ! last_includes_end ;
2011-09-06 12:01:28 +00:00
if ( p_channel_status - > reassembly_info ) {
/* Add next segment to reassembly info */
reassembly_add_segment ( p_channel_status , sequenceNumber , pinfo - > fd - > num ,
tvb , firstSegmentOffset , firstSegmentLength ) ;
/* The end of existing reassembly? */
if ( ! first_includes_start & &
( ( number_of_segments > 1 ) | | last_includes_end ) ) {
2012-01-23 02:36:46 +00:00
reassembly_record ( p_channel_status , pinfo ,
sequenceNumber , p_rlc_lte_info ) ;
2011-09-06 12:01:28 +00:00
reassembly_destroy ( p_channel_status ) ;
}
}
/* The start of a new reassembly? */
if ( ! last_includes_end & &
( ( number_of_segments > 1 ) | | first_includes_start ) ) {
2014-05-05 20:32:33 +00:00
guint16 lastSegmentLength = tvb_reported_length ( tvb ) - lastSegmentOffset ;
2011-09-06 12:01:28 +00:00
if ( global_rlc_lte_reassembly ) {
reassembly_reset ( p_channel_status ) ;
reassembly_add_segment ( p_channel_status , sequenceNumber ,
pinfo - > fd - > num ,
tvb , lastSegmentOffset , lastSegmentLength ) ;
}
}
2012-01-23 02:36:46 +00:00
if ( p_report_in_frame - > previousFrameNum ! = 0 ) {
/* Get report for previous frame */
sequence_analysis_report * p_previous_report ;
p_previous_report = ( sequence_analysis_report * ) g_hash_table_lookup ( sequence_analysis_report_hash ,
get_report_hash_key ( ( sequenceNumber + 1023 ) % 1024 ,
p_report_in_frame - > previousFrameNum ,
p_rlc_lte_info ,
FALSE ) ) ;
/* It really shouldn't be NULL... */
if ( p_previous_report ! = NULL ) {
/* Point it forward to this one */
p_previous_report - > nextFrameNum = pinfo - > fd - > num ;
}
}
2009-04-14 14:38:20 +00:00
}
2010-02-28 02:18:35 +00:00
/* Previous subframe repeated? */
else if ( ( ( sequenceNumber + 1 ) % 1024 ) = = expectedSequenceNumber ) {
2010-06-25 23:04:16 +00:00
p_report_in_frame - > state = SN_Repeated ;
2010-02-28 02:18:35 +00:00
/* Set report for this frame */
p_report_in_frame - > sequenceExpectedCorrect = FALSE ;
2010-09-20 17:01:22 +00:00
p_report_in_frame - > sequenceExpected = expectedSequenceNumber ;
p_report_in_frame - > firstSN = sequenceNumber ;
2010-02-28 02:18:35 +00:00
p_report_in_frame - > previousFrameNum = p_channel_status - > previousFrameNum ;
p_report_in_frame - > previousSegmentIncomplete = p_channel_status - > previousSegmentIncomplete ;
/* Really should be nothing to update... */
p_channel_status - > previousSequenceNumber = sequenceNumber ;
p_channel_status - > previousFrameNum = pinfo - > fd - > num ;
p_channel_status - > previousSegmentIncomplete = ! last_includes_end ;
}
2009-04-14 14:38:20 +00:00
else {
2010-02-28 20:43:04 +00:00
/* Need to work out if new (with skips, or likely a retx (due to NACK)) */
int delta = ( 1024 + expectedSequenceNumber - sequenceNumber ) % 1024 ;
/* Rx window is 512, so check to see if this is a retx */
if ( delta < 512 ) {
/* Probably a retx due to receiving NACK */
2010-06-25 23:04:16 +00:00
p_report_in_frame - > state = SN_Retx ;
2010-02-28 20:43:04 +00:00
p_report_in_frame - > firstSN = sequenceNumber ;
/* Don't update anything in channel state */
}
else {
2012-01-22 02:55:47 +00:00
/* Ahead of expected SN. Assume frames have been missed */
p_report_in_frame - > state = SN_Missing ;
2011-10-21 02:10:19 +00:00
2012-01-22 02:55:47 +00:00
p_report_in_frame - > firstSN = expectedSequenceNumber ;
p_report_in_frame - > lastSN = ( 1024 + sequenceNumber - 1 ) % 1024 ;
2010-02-28 02:18:35 +00:00
/* Update channel state - forget about missed SNs */
p_report_in_frame - > sequenceExpected = expectedSequenceNumber ;
p_channel_status - > previousSequenceNumber = sequenceNumber ;
p_channel_status - > previousFrameNum = pinfo - > fd - > num ;
p_channel_status - > previousSegmentIncomplete = ! last_includes_end ;
}
2009-04-14 14:38:20 +00:00
}
2010-02-28 02:18:35 +00:00
break ;
2009-04-14 14:38:20 +00:00
2010-02-28 02:18:35 +00:00
default :
/* Shouldn't get here! */
2012-01-23 02:36:46 +00:00
return SN_Error ;
2009-04-14 14:38:20 +00:00
}
/* Associate with this frame number */
2012-01-23 02:36:46 +00:00
g_hash_table_insert ( sequence_analysis_report_hash ,
get_report_hash_key ( sequenceNumber , pinfo - > fd - > num , p_rlc_lte_info , TRUE ) ,
p_report_in_frame ) ;
2009-04-14 14:38:20 +00:00
/* Add state report for this frame into tree */
2011-07-26 10:16:02 +00:00
addChannelSequenceInfo ( p_report_in_frame , isControlFrame , p_rlc_lte_info , sequenceNumber ,
2010-02-28 18:42:41 +00:00
first_includes_start , tap_info , pinfo , tree , tvb ) ;
2012-01-23 02:36:46 +00:00
return p_report_in_frame - > state ;
2009-04-14 14:38:20 +00:00
}
2010-03-02 18:40:34 +00:00
/* Add to the tree values associated with sequence analysis for this frame */
2012-01-23 02:36:46 +00:00
static void addChannelRepeatedNACKInfo ( channel_repeated_nack_report * p ,
2011-03-06 23:10:28 +00:00
rlc_lte_info * p_rlc_lte_info ,
2010-03-02 18:40:34 +00:00
packet_info * pinfo , proto_tree * tree ,
tvbuff_t * tvb )
{
proto_tree * seqnum_tree ;
proto_item * seqnum_ti ;
proto_item * ti ;
gint n ;
/* Create subtree */
seqnum_ti = proto_tree_add_string_format ( tree ,
hf_rlc_lte_sequence_analysis ,
tvb , 0 , 0 ,
" " , " Sequence Analysis " ) ;
seqnum_tree = proto_item_add_subtree ( seqnum_ti ,
ett_rlc_lte_sequence_analysis ) ;
PROTO_ITEM_SET_GENERATED ( seqnum_ti ) ;
/* OK = FALSE */
ti = proto_tree_add_boolean ( seqnum_tree , hf_rlc_lte_sequence_analysis_ok ,
tvb , 0 , 0 , FALSE ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
/* Add each repeated NACK as item & expert info */
for ( n = 0 ; n < p - > noOfNACKsRepeated ; n + + ) {
ti = proto_tree_add_uint ( seqnum_tree , hf_rlc_lte_sequence_analysis_repeated_nack ,
tvb , 0 , 0 , p - > repeatedNACKs [ n ] ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , ti , & ei_rlc_lte_sequence_analysis_repeated_nack ,
2010-03-02 18:40:34 +00:00
" Same SN (%u) NACKd for %s on UE %u in successive Status PDUs " ,
p - > repeatedNACKs [ n ] ,
2010-03-14 16:36:41 +00:00
val_to_str_const ( p_rlc_lte_info - > direction , direction_vals , " Unknown " ) ,
2010-03-02 18:40:34 +00:00
p_rlc_lte_info - > ueid ) ;
}
2010-10-15 21:07:45 +00:00
/* Link back to previous status report */
ti = proto_tree_add_uint ( seqnum_tree , hf_rlc_lte_sequence_analysis_repeated_nack_original_frame ,
tvb , 0 , 0 , p - > previousFrameNum ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
2010-03-02 18:40:34 +00:00
/* Append count to sequence analysis root */
proto_item_append_text ( seqnum_ti , " - %u SNs repeated from previous Status PDU " ,
2010-10-10 20:39:00 +00:00
p - > noOfNACKsRepeated ) ;
2010-03-02 18:40:34 +00:00
}
/* Update the channel repeated NACK status and set report for this frame */
static void checkChannelRepeatedNACKInfo ( packet_info * pinfo ,
rlc_lte_info * p_rlc_lte_info ,
rlc_lte_tap_info * tap_info ,
proto_tree * tree ,
tvbuff_t * tvb )
{
2012-01-23 02:36:46 +00:00
channel_hash_key channel_key ;
channel_hash_key * p_channel_key ;
channel_repeated_nack_status * p_channel_status ;
channel_repeated_nack_report * p_report_in_frame = NULL ;
2010-03-02 18:40:34 +00:00
2010-03-04 20:58:54 +00:00
guint16 noOfNACKsRepeated = 0 ;
2010-03-02 18:40:34 +00:00
guint16 repeatedNACKs [ MAX_NACKs ] ;
gint n , i , j ;
/* If find state_report_in_frame already, use that and get out */
if ( pinfo - > fd - > flags . visited ) {
2012-01-23 02:36:46 +00:00
p_report_in_frame = ( channel_repeated_nack_report * ) g_hash_table_lookup ( repeated_nack_report_hash ,
get_report_hash_key ( 0 , pinfo - > fd - > num ,
p_rlc_lte_info , FALSE ) ) ;
2010-03-02 18:40:34 +00:00
if ( p_report_in_frame ! = NULL ) {
addChannelRepeatedNACKInfo ( p_report_in_frame , p_rlc_lte_info ,
pinfo , tree , tvb ) ;
return ;
}
else {
/* Give up - we must have tried already... */
return ;
}
}
/**************************************************/
/* Create or find an entry for this channel state */
channel_key . ueId = p_rlc_lte_info - > ueid ;
channel_key . channelType = p_rlc_lte_info - > channelType ;
channel_key . channelId = p_rlc_lte_info - > channelId ;
channel_key . direction = p_rlc_lte_info - > direction ;
2011-02-18 21:44:06 +00:00
memset ( repeatedNACKs , 0 , sizeof ( repeatedNACKs ) ) ;
2010-03-02 18:40:34 +00:00
/* Do the table lookup */
2012-01-23 02:36:46 +00:00
p_channel_status = ( channel_repeated_nack_status * ) g_hash_table_lookup ( repeated_nack_channel_hash , & channel_key ) ;
2010-03-02 18:40:34 +00:00
/* Create table entry if necessary */
if ( p_channel_status = = NULL ) {
/* Allocate a new key and value */
2013-08-30 14:49:55 +00:00
p_channel_key = wmem_new ( wmem_file_scope ( ) , channel_hash_key ) ;
p_channel_status = wmem_new0 ( wmem_file_scope ( ) , channel_repeated_nack_status ) ;
2010-03-02 18:40:34 +00:00
/* Copy key contents */
2012-01-23 02:36:46 +00:00
memcpy ( p_channel_key , & channel_key , sizeof ( channel_hash_key ) ) ;
2010-03-03 15:34:44 +00:00
2010-03-02 18:40:34 +00:00
/* Add entry to table */
2012-01-23 02:36:46 +00:00
g_hash_table_insert ( repeated_nack_channel_hash , p_channel_key , p_channel_status ) ;
2010-03-02 18:40:34 +00:00
}
2010-03-04 20:58:54 +00:00
/* Compare NACKs in channel status with NACKs in tap_info.
2010-03-02 18:40:34 +00:00
Note any that are repeated */
for ( i = 0 ; i < p_channel_status - > noOfNACKs ; i + + ) {
2010-03-04 20:58:54 +00:00
for ( j = 0 ; j < MIN ( tap_info - > noOfNACKs , MAX_NACKs ) ; j + + ) {
2010-03-02 18:40:34 +00:00
if ( tap_info - > NACKs [ j ] = = p_channel_status - > NACKs [ i ] ) {
2010-03-07 10:03:05 +00:00
/* Don't add the same repeated NACK twice! */
if ( ( noOfNACKsRepeated = = 0 ) | |
( repeatedNACKs [ noOfNACKsRepeated - 1 ] ! = p_channel_status - > NACKs [ i ] ) ) {
repeatedNACKs [ noOfNACKsRepeated + + ] = p_channel_status - > NACKs [ i ] ;
}
2010-03-02 18:40:34 +00:00
}
}
}
2010-03-03 15:34:44 +00:00
/* Copy NACKs from tap_info into channel status for next time! */
2010-03-04 20:58:54 +00:00
p_channel_status - > noOfNACKs = 0 ;
for ( n = 0 ; n < MIN ( tap_info - > noOfNACKs , MAX_NACKs ) ; n + + ) {
p_channel_status - > NACKs [ p_channel_status - > noOfNACKs + + ] = tap_info - > NACKs [ n ] ;
2010-03-03 15:34:44 +00:00
}
2010-03-02 18:40:34 +00:00
if ( noOfNACKsRepeated > = 1 ) {
/* Create space for frame state_report */
2013-08-30 14:49:55 +00:00
p_report_in_frame = wmem_new ( wmem_file_scope ( ) , channel_repeated_nack_report ) ;
2010-03-03 15:34:44 +00:00
2010-03-02 18:40:34 +00:00
/* Copy in found duplicates */
2010-03-04 20:58:54 +00:00
for ( n = 0 ; n < MIN ( tap_info - > noOfNACKs , MAX_NACKs ) ; n + + ) {
2010-03-02 18:40:34 +00:00
p_report_in_frame - > repeatedNACKs [ n ] = repeatedNACKs [ n ] ;
}
p_report_in_frame - > noOfNACKsRepeated = noOfNACKsRepeated ;
2010-03-03 15:34:44 +00:00
2010-10-15 21:07:45 +00:00
p_report_in_frame - > previousFrameNum = p_channel_status - > frameNum ;
2010-03-02 18:40:34 +00:00
/* Associate with this frame number */
2012-01-23 02:36:46 +00:00
g_hash_table_insert ( repeated_nack_report_hash ,
get_report_hash_key ( 0 , pinfo - > fd - > num ,
p_rlc_lte_info , TRUE ) ,
p_report_in_frame ) ;
2010-03-03 15:34:44 +00:00
2010-03-02 18:40:34 +00:00
/* Add state report for this frame into tree */
addChannelRepeatedNACKInfo ( p_report_in_frame , p_rlc_lte_info ,
pinfo , tree , tvb ) ;
}
2010-10-15 21:07:45 +00:00
/* Save frame number for next comparison */
p_channel_status - > frameNum = pinfo - > fd - > num ;
2010-03-02 18:40:34 +00:00
}
2011-05-19 01:05:26 +00:00
/* Check that the ACK is consistent with data the expected sequence number
in the other direction */
static void checkChannelACKWindow ( guint16 ack_sn ,
packet_info * pinfo ,
rlc_lte_info * p_rlc_lte_info ,
2011-05-23 17:15:00 +00:00
rlc_lte_tap_info * tap_info ,
2011-05-19 01:05:26 +00:00
proto_tree * tree ,
tvbuff_t * tvb )
{
2012-01-23 02:36:46 +00:00
channel_hash_key channel_key ;
channel_sequence_analysis_status * p_channel_status ;
sequence_analysis_report * p_report_in_frame = NULL ;
2011-05-19 01:05:26 +00:00
/* If find stat_report_in_frame already, use that and get out */
if ( pinfo - > fd - > flags . visited ) {
2012-01-23 02:36:46 +00:00
p_report_in_frame = ( sequence_analysis_report * ) g_hash_table_lookup ( sequence_analysis_report_hash ,
get_report_hash_key ( 0 , pinfo - > fd - > num ,
p_rlc_lte_info ,
FALSE ) ) ;
2011-05-19 01:05:26 +00:00
if ( p_report_in_frame ! = NULL ) {
/* Add any info to tree */
2011-07-26 10:16:02 +00:00
addChannelSequenceInfo ( p_report_in_frame , TRUE , p_rlc_lte_info ,
2011-05-19 01:05:26 +00:00
0 , FALSE ,
2011-05-23 17:15:00 +00:00
tap_info , pinfo , tree , tvb ) ;
2011-05-19 01:05:26 +00:00
return ;
}
else {
/* Give up - we must have tried already... */
return ;
}
}
/*******************************************************************/
/* Find an entry for this channel state (in the opposite direction */
channel_key . ueId = p_rlc_lte_info - > ueid ;
channel_key . channelType = p_rlc_lte_info - > channelType ;
channel_key . channelId = p_rlc_lte_info - > channelId ;
channel_key . direction =
( p_rlc_lte_info - > direction = = DIRECTION_UPLINK ) ? DIRECTION_DOWNLINK : DIRECTION_UPLINK ;
/* Do the table lookup */
2012-01-23 02:36:46 +00:00
p_channel_status = ( channel_sequence_analysis_status * ) g_hash_table_lookup ( sequence_analysis_channel_hash , & channel_key ) ;
2011-05-19 01:05:26 +00:00
/* Create table entry if necessary */
if ( p_channel_status = = NULL ) {
return ;
}
2013-02-26 01:06:19 +00:00
/* Is it in the rx window? This test will catch if it's ahead, but we don't
2011-05-19 01:05:26 +00:00
really know what the back of the tx window is . . . */
if ( ( ( 1024 + p_channel_status - > previousSequenceNumber + 1 - ack_sn ) % 1024 ) > 512 ) {
/* Set result */
2013-08-30 14:49:55 +00:00
p_report_in_frame = wmem_new0 ( wmem_file_scope ( ) , sequence_analysis_report ) ;
2011-05-19 01:05:26 +00:00
p_report_in_frame - > state = ACK_Out_of_Window ;
p_report_in_frame - > previousFrameNum = p_channel_status - > previousFrameNum ;
p_report_in_frame - > sequenceExpected = p_channel_status - > previousSequenceNumber ;
p_report_in_frame - > firstSN = ack_sn ;
/* Associate with this frame number */
2012-01-23 02:36:46 +00:00
g_hash_table_insert ( sequence_analysis_report_hash ,
get_report_hash_key ( 0 , pinfo - > fd - > num ,
p_rlc_lte_info , TRUE ) ,
p_report_in_frame ) ;
2011-05-19 01:05:26 +00:00
/* Add state report for this frame into tree */
2011-07-26 10:16:02 +00:00
addChannelSequenceInfo ( p_report_in_frame , TRUE , p_rlc_lte_info , 0 ,
2011-05-23 17:15:00 +00:00
FALSE , tap_info , pinfo , tree , tvb ) ;
2011-05-19 01:05:26 +00:00
}
}
2010-03-02 18:40:34 +00:00
2009-04-14 14:38:20 +00:00
2009-11-16 15:35:56 +00:00
/***************************************************/
2010-03-01 23:56:35 +00:00
/* Transparent mode PDU. Call RRC if configured to */
2009-11-16 15:35:56 +00:00
static void dissect_rlc_lte_tm ( tvbuff_t * tvb , packet_info * pinfo ,
proto_tree * tree ,
int offset ,
rlc_lte_info * p_rlc_lte_info ,
2011-03-06 23:10:28 +00:00
proto_item * top_ti )
2009-11-16 15:35:56 +00:00
{
proto_item * raw_tm_ti ;
2010-03-06 19:35:40 +00:00
proto_item * tm_ti ;
/* Create hidden TM root */
tm_ti = proto_tree_add_string_format ( tree , hf_rlc_lte_tm ,
2011-06-08 17:10:40 +00:00
tvb , offset , 0 , " " , " TM " ) ;
2010-03-06 19:35:40 +00:00
PROTO_ITEM_SET_HIDDEN ( tm_ti ) ;
2009-11-16 15:35:56 +00:00
/* Remaining bytes are all data */
2011-10-04 22:44:31 +00:00
raw_tm_ti = proto_tree_add_item ( tree , hf_rlc_lte_tm_data , tvb , offset , - 1 , ENC_NA ) ;
2012-10-01 19:51:07 +00:00
if ( ! global_rlc_lte_call_rrc_for_ccch ) {
2010-03-09 01:39:08 +00:00
write_pdu_label_and_info ( top_ti , NULL , pinfo ,
2014-05-05 20:32:33 +00:00
" [%u-bytes] " , tvb_reported_length_remaining ( tvb , offset ) ) ;
2009-11-16 15:35:56 +00:00
}
2012-10-01 19:51:07 +00:00
if ( global_rlc_lte_call_rrc_for_ccch ) {
2013-02-19 23:17:07 +00:00
tvbuff_t * rrc_tvb = tvb_new_subset_remaining ( tvb , offset ) ;
2009-11-16 15:35:56 +00:00
volatile dissector_handle_t protocol_handle = 0 ;
switch ( p_rlc_lte_info - > channelType ) {
case CHANNEL_TYPE_CCCH :
if ( p_rlc_lte_info - > direction = = DIRECTION_UPLINK ) {
2010-06-18 07:07:55 +00:00
protocol_handle = find_dissector ( " lte_rrc.ul_ccch " ) ;
2009-11-16 15:35:56 +00:00
}
else {
2010-06-18 07:07:55 +00:00
protocol_handle = find_dissector ( " lte_rrc.dl_ccch " ) ;
2009-11-16 15:35:56 +00:00
}
break ;
2011-07-19 16:41:56 +00:00
case CHANNEL_TYPE_BCCH_BCH :
2011-07-20 12:19:22 +00:00
protocol_handle = find_dissector ( " lte_rrc.bcch_bch " ) ;
2011-07-19 16:41:56 +00:00
break ;
case CHANNEL_TYPE_BCCH_DL_SCH :
2011-07-20 12:19:22 +00:00
protocol_handle = find_dissector ( " lte_rrc.bcch_dl_sch " ) ;
2011-07-19 16:41:56 +00:00
break ;
2009-11-16 15:35:56 +00:00
case CHANNEL_TYPE_PCCH :
2012-09-23 21:01:05 +00:00
protocol_handle = find_dissector ( " lte_rrc.pcch " ) ;
2009-11-16 15:35:56 +00:00
break ;
2010-01-08 16:07:14 +00:00
case CHANNEL_TYPE_SRB :
case CHANNEL_TYPE_DRB :
2012-10-01 19:51:07 +00:00
case CHANNEL_TYPE_MCCH :
2012-12-11 23:20:22 +00:00
case CHANNEL_TYPE_MTCH :
2010-04-30 17:15:59 +00:00
2010-01-08 16:07:14 +00:00
default :
2010-04-30 17:15:59 +00:00
/* Shouldn't happen, just return... */
2010-01-08 16:07:14 +00:00
return ;
2009-11-16 15:35:56 +00:00
}
/* Hide raw view of bytes */
PROTO_ITEM_SET_HIDDEN ( raw_tm_ti ) ;
/* Call it (catch exceptions) */
TRY {
2012-09-11 08:28:07 +00:00
call_dissector_only ( protocol_handle , rrc_tvb , pinfo , tree , NULL ) ;
2009-11-16 15:35:56 +00:00
}
CATCH_ALL {
}
ENDTRY
}
}
2009-04-14 14:38:20 +00:00
2009-01-05 23:18:00 +00:00
/***************************************************/
/* Unacknowledged mode PDU */
static void dissect_rlc_lte_um ( tvbuff_t * tvb , packet_info * pinfo ,
proto_tree * tree ,
int offset ,
2009-09-15 17:49:58 +00:00
rlc_lte_info * p_rlc_lte_info ,
2010-01-04 14:07:24 +00:00
proto_item * top_ti ,
rlc_lte_tap_info * tap_info )
2009-01-05 23:18:00 +00:00
{
guint64 framing_info ;
2009-01-08 13:28:30 +00:00
gboolean first_includes_start ;
gboolean last_includes_end ;
2009-01-05 23:18:00 +00:00
guint64 fixed_extension ;
guint64 sn ;
gint start_offset = offset ;
2010-03-06 19:35:40 +00:00
proto_item * um_ti ;
2009-01-05 23:18:00 +00:00
proto_tree * um_header_tree ;
proto_item * um_header_ti ;
2013-07-16 12:28:33 +00:00
gboolean is_truncated = FALSE ;
2010-02-01 11:00:08 +00:00
proto_item * truncated_ti ;
2011-09-06 12:01:28 +00:00
rlc_channel_reassembly_info * reassembly_info = NULL ;
2012-01-23 02:36:46 +00:00
sequence_analysis_state seq_anal_state = SN_OK ;
2009-01-05 23:18:00 +00:00
2010-03-06 19:35:40 +00:00
/* Hidden UM root */
um_ti = proto_tree_add_string_format ( tree , hf_rlc_lte_um ,
tvb , offset , 0 , " " , " UM " ) ;
PROTO_ITEM_SET_HIDDEN ( um_ti ) ;
2009-01-05 23:18:00 +00:00
/* Add UM header subtree */
2010-03-06 19:35:40 +00:00
um_header_ti = proto_tree_add_string_format ( tree , hf_rlc_lte_um_header ,
2009-01-05 23:18:00 +00:00
tvb , offset , 0 ,
2010-03-06 19:35:40 +00:00
" " , " UM header " ) ;
2009-01-05 23:18:00 +00:00
um_header_tree = proto_item_add_subtree ( um_header_ti ,
ett_rlc_lte_um_header ) ;
/*******************************/
/* Fixed UM header */
2009-02-19 22:25:36 +00:00
if ( p_rlc_lte_info - > UMSequenceNumberLength = = UM_SN_LENGTH_5_BITS ) {
2009-01-05 23:18:00 +00:00
/* Framing info (2 bits) */
proto_tree_add_bits_ret_val ( um_header_tree , hf_rlc_lte_um_fi ,
tvb , offset * 8 , 2 ,
2011-10-24 19:57:53 +00:00
& framing_info , ENC_BIG_ENDIAN ) ;
2009-01-05 23:18:00 +00:00
/* Extension (1 bit) */
proto_tree_add_bits_ret_val ( um_header_tree , hf_rlc_lte_um_fixed_e , tvb ,
( offset * 8 ) + 2 , 1 ,
2011-10-24 19:57:53 +00:00
& fixed_extension , ENC_BIG_ENDIAN ) ;
2009-01-05 23:18:00 +00:00
/* Sequence Number (5 bit) */
proto_tree_add_bits_ret_val ( um_header_tree , hf_rlc_lte_um_sn , tvb ,
( offset * 8 ) + 3 , 5 ,
2011-10-24 19:57:53 +00:00
& sn , ENC_BIG_ENDIAN ) ;
2009-01-05 23:18:00 +00:00
offset + + ;
}
2009-02-19 22:25:36 +00:00
else if ( p_rlc_lte_info - > UMSequenceNumberLength = = UM_SN_LENGTH_10_BITS ) {
2009-01-05 23:18:00 +00:00
guint8 reserved ;
proto_item * ti ;
/* Check 3 Reserved bits */
reserved = ( tvb_get_guint8 ( tvb , offset ) & 0xe0 ) > > 5 ;
2011-10-06 03:35:44 +00:00
ti = proto_tree_add_item ( um_header_tree , hf_rlc_lte_um_fixed_reserved , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2009-01-05 23:18:00 +00:00
if ( reserved ! = 0 ) {
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , ti , & ei_rlc_lte_reserved_bits_not_zero ,
2009-01-05 23:18:00 +00:00
" RLC UM Fixed header Reserved bits not zero (found 0x%x) " , reserved ) ;
}
/* Framing info (2 bits) */
proto_tree_add_bits_ret_val ( um_header_tree , hf_rlc_lte_um_fi ,
tvb , ( offset * 8 ) + 3 , 2 ,
2011-10-24 19:57:53 +00:00
& framing_info , ENC_BIG_ENDIAN ) ;
2009-01-05 23:18:00 +00:00
/* Extension (1 bit) */
proto_tree_add_bits_ret_val ( um_header_tree , hf_rlc_lte_um_fixed_e , tvb ,
( offset * 8 ) + 5 , 1 ,
2011-10-24 19:57:53 +00:00
& fixed_extension , ENC_BIG_ENDIAN ) ;
2009-01-05 23:18:00 +00:00
/* Sequence Number (10 bits) */
proto_tree_add_bits_ret_val ( um_header_tree , hf_rlc_lte_um_sn , tvb ,
( offset * 8 ) + 6 , 10 ,
2011-10-24 19:57:53 +00:00
& sn , ENC_BIG_ENDIAN ) ;
2009-01-05 23:18:00 +00:00
offset + = 2 ;
}
else {
/* Invalid length of sequence number */
2013-09-05 01:05:16 +00:00
proto_tree_add_expert_format ( um_header_tree , pinfo , & ei_rlc_lte_um_sn , tvb , 0 , 0 ,
2009-01-05 23:18:00 +00:00
" Invalid sequence number length (%u bits) " ,
p_rlc_lte_info - > UMSequenceNumberLength ) ;
return ;
}
2010-01-04 15:24:33 +00:00
tap_info - > sequenceNumber = ( guint16 ) sn ;
2010-01-04 14:07:24 +00:00
2009-01-05 23:18:00 +00:00
/* Show SN in info column */
2013-07-28 14:35:42 +00:00
if ( ( p_rlc_lte_info - > channelType = = CHANNEL_TYPE_MCCH ) | | ( p_rlc_lte_info - > channelType = = CHANNEL_TYPE_MTCH ) ) {
write_pdu_label_and_info ( top_ti , um_header_ti , pinfo , " sn=%-4u " , ( guint16 ) sn ) ;
}
else {
write_pdu_label_and_info ( top_ti , um_header_ti , pinfo , " sn=%-4u " , ( guint16 ) sn ) ;
}
2009-01-05 23:18:00 +00:00
proto_item_set_len ( um_header_ti , offset - start_offset ) ;
/*************************************/
/* UM header extension */
if ( fixed_extension ) {
2014-12-07 19:54:05 +00:00
offset = dissect_rlc_lte_extension_header ( tvb , pinfo , um_header_tree , offset , p_rlc_lte_info ) ;
2009-01-05 23:18:00 +00:00
}
2011-12-01 23:17:17 +00:00
/* Extract these 2 flags from framing_info */
first_includes_start = ( ( guint8 ) framing_info & 0x02 ) = = 0 ;
last_includes_end = ( ( guint8 ) framing_info & 0x01 ) = = 0 ;
2010-02-01 11:00:08 +00:00
if ( global_rlc_lte_headers_expected ) {
/* There might not be any data, if only headers (plus control data) were logged */
2014-05-05 20:32:33 +00:00
is_truncated = ( tvb_reported_length_remaining ( tvb , offset ) = = 0 ) ;
2010-02-01 11:00:08 +00:00
truncated_ti = proto_tree_add_uint ( tree , hf_rlc_lte_header_only , tvb , 0 , 0 ,
is_truncated ) ;
if ( is_truncated ) {
2011-12-01 23:17:17 +00:00
int n ;
2010-02-01 11:00:08 +00:00
PROTO_ITEM_SET_GENERATED ( truncated_ti ) ;
2013-09-05 01:05:16 +00:00
expert_add_info ( pinfo , truncated_ti , & ei_rlc_lte_header_only ) ;
2011-12-01 23:17:17 +00:00
/* Show in the info column how long the data would be */
for ( n = 0 ; n < s_number_of_extensions ; n + + ) {
show_PDU_in_info ( pinfo , top_ti , s_lengths [ n ] ,
( n = = 0 ) ? first_includes_start : TRUE ,
TRUE ) ;
offset + = s_lengths [ n ] ;
}
/* Last one */
show_PDU_in_info ( pinfo , top_ti , p_rlc_lte_info - > pduLength - offset ,
( s_number_of_extensions = = 0 ) ? first_includes_start : TRUE ,
last_includes_end ) ;
2010-02-01 11:00:08 +00:00
}
else {
PROTO_ITEM_SET_HIDDEN ( truncated_ti ) ;
}
}
2009-01-05 23:18:00 +00:00
2012-02-28 19:01:24 +00:00
/* Show number of extensions in header root */
if ( s_number_of_extensions > 0 ) {
proto_item_append_text ( um_header_ti , " (%u extensions) " , s_number_of_extensions ) ;
}
2009-04-14 14:38:20 +00:00
/* Call sequence analysis function now */
2010-02-28 02:18:35 +00:00
if ( ( ( global_rlc_lte_um_sequence_analysis = = SEQUENCE_ANALYSIS_MAC_ONLY ) & &
2013-11-23 02:20:13 +00:00
( p_get_proto_data ( wmem_file_scope ( ) , pinfo , proto_mac_lte , 0 ) ! = NULL ) ) | |
2010-02-28 02:18:35 +00:00
( ( global_rlc_lte_um_sequence_analysis = = SEQUENCE_ANALYSIS_RLC_ONLY ) & &
2013-11-23 02:20:13 +00:00
( p_get_proto_data ( wmem_file_scope ( ) , pinfo , proto_mac_lte , 0 ) = = NULL ) ) ) {
2010-02-28 02:18:35 +00:00
2011-09-06 12:01:28 +00:00
guint16 lastSegmentOffset = offset ;
if ( s_number_of_extensions > = 1 ) {
int n ;
lastSegmentOffset = offset ;
for ( n = 0 ; n < s_number_of_extensions ; n + + ) {
lastSegmentOffset + = s_lengths [ n ] ;
}
}
2012-01-23 02:36:46 +00:00
seq_anal_state = checkChannelSequenceInfo ( pinfo , tvb , p_rlc_lte_info ,
FALSE ,
s_number_of_extensions + 1 ,
2012-10-17 04:01:01 +00:00
offset ,
s_number_of_extensions ?
s_lengths [ 0 ] :
p_rlc_lte_info - > pduLength - offset ,
2012-01-23 02:36:46 +00:00
lastSegmentOffset ,
( guint16 ) sn , first_includes_start , last_includes_end ,
FALSE , /* UM doesn't re-segment */
tap_info , um_header_tree ) ;
2009-04-14 14:38:20 +00:00
}
2013-07-16 12:28:33 +00:00
if ( is_truncated ) {
return ;
}
2009-04-14 14:38:20 +00:00
2009-01-05 23:18:00 +00:00
/*************************************/
/* Data */
2011-09-06 12:01:28 +00:00
2012-01-23 02:36:46 +00:00
reassembly_info = ( rlc_channel_reassembly_info * ) g_hash_table_lookup ( reassembly_report_hash ,
get_report_hash_key ( ( guint16 ) sn , pinfo - > fd - > num ,
p_rlc_lte_info , FALSE ) ) ;
2011-09-06 12:01:28 +00:00
2009-01-05 23:18:00 +00:00
if ( s_number_of_extensions > 0 ) {
/* Show each data segment separately */
int n ;
for ( n = 0 ; n < s_number_of_extensions ; n + + ) {
2011-02-02 23:23:07 +00:00
show_PDU_in_tree ( pinfo , tree , tvb , offset , s_lengths [ n ] , p_rlc_lte_info ,
2011-09-06 12:01:28 +00:00
( n = = 0 ) ? first_includes_start : TRUE ,
2012-01-23 02:36:46 +00:00
( n = = 0 ) ? reassembly_info : NULL ,
seq_anal_state ) ;
2009-09-15 17:49:58 +00:00
show_PDU_in_info ( pinfo , top_ti , s_lengths [ n ] ,
2009-01-05 23:18:00 +00:00
( n = = 0 ) ? first_includes_start : TRUE ,
TRUE ) ;
2014-06-05 17:58:22 +00:00
/* Make sure we don't lose the summary of this SDU */
col_append_str ( pinfo - > cinfo , COL_INFO , " | " ) ;
col_set_fence ( pinfo - > cinfo , COL_INFO ) ;
2009-01-16 10:53:58 +00:00
tvb_ensure_bytes_exist ( tvb , offset , s_lengths [ n ] ) ;
2009-01-05 23:18:00 +00:00
offset + = s_lengths [ n ] ;
}
}
/* Final data element */
2014-06-12 12:42:35 +00:00
show_PDU_in_tree ( pinfo , tree , tvb , offset , tvb_reported_length_remaining ( tvb , offset ) , p_rlc_lte_info ,
2011-09-06 12:01:28 +00:00
( ( s_number_of_extensions = = 0 ) ? first_includes_start : TRUE ) & & last_includes_end ,
2012-01-23 02:36:46 +00:00
( s_number_of_extensions = = 0 ) ? reassembly_info : NULL ,
seq_anal_state ) ;
2014-05-05 20:32:33 +00:00
show_PDU_in_info ( pinfo , top_ti , ( guint16 ) tvb_reported_length_remaining ( tvb , offset ) ,
2009-01-05 23:18:00 +00:00
( s_number_of_extensions = = 0 ) ? first_includes_start : TRUE ,
last_includes_end ) ;
}
/* Dissect an AM STATUS PDU */
2009-04-14 14:38:20 +00:00
static void dissect_rlc_lte_am_status_pdu ( tvbuff_t * tvb ,
packet_info * pinfo ,
2009-01-05 23:18:00 +00:00
proto_tree * tree ,
2009-06-07 13:35:17 +00:00
proto_item * status_ti ,
2009-09-15 17:49:58 +00:00
int offset ,
2010-01-04 14:07:24 +00:00
proto_item * top_ti ,
2010-03-01 22:52:34 +00:00
rlc_lte_info * p_rlc_lte_info ,
2010-01-04 14:07:24 +00:00
rlc_lte_tap_info * tap_info )
2009-01-05 23:18:00 +00:00
{
guint8 cpt ;
guint64 ack_sn , nack_sn ;
2010-03-04 20:58:54 +00:00
guint16 nack_count = 0 ;
2009-01-05 23:18:00 +00:00
guint64 e1 = 0 , e2 = 0 ;
guint64 so_start , so_end ;
int bit_offset = offset * 8 ;
proto_item * ti ;
/****************************************************************/
/* Part of RLC control PDU header */
/* Control PDU Type (CPT) */
cpt = ( tvb_get_guint8 ( tvb , offset ) & 0xf0 ) > > 4 ;
2011-10-06 03:35:44 +00:00
ti = proto_tree_add_item ( tree , hf_rlc_lte_am_cpt , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2009-01-05 23:18:00 +00:00
if ( cpt ! = 0 ) {
/* Protest and stop - only know about STATUS PDUs */
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , ti , & ei_rlc_lte_am_cpt ,
2009-01-05 23:18:00 +00:00
" RLC Control frame type %u not handled " , cpt ) ;
return ;
}
2010-03-01 23:56:35 +00:00
/* The Status PDU itself starts 4 bits into the byte */
2009-01-05 23:18:00 +00:00
bit_offset + = 4 ;
/* ACK SN */
proto_tree_add_bits_ret_val ( tree , hf_rlc_lte_am_ack_sn , tvb ,
2011-10-24 19:57:53 +00:00
bit_offset , 10 , & ack_sn , ENC_BIG_ENDIAN ) ;
2009-01-05 23:18:00 +00:00
bit_offset + = 10 ;
2010-07-20 13:27:20 +00:00
write_pdu_label_and_info ( top_ti , status_ti , pinfo , " ACK_SN=%-4u " , ( guint16 ) ack_sn ) ;
2010-03-09 01:39:08 +00:00
2010-01-04 15:24:33 +00:00
tap_info - > ACKNo = ( guint16 ) ack_sn ;
2009-01-05 23:18:00 +00:00
/* E1 */
proto_tree_add_bits_ret_val ( tree , hf_rlc_lte_am_e1 , tvb ,
2011-10-24 19:57:53 +00:00
bit_offset , 1 , & e1 , ENC_BIG_ENDIAN ) ;
2009-01-05 23:18:00 +00:00
/* Skip another bit to byte-align the next bit... */
bit_offset + + ;
/* Optional, extra fields */
do {
if ( e1 ) {
2009-02-11 17:51:37 +00:00
proto_item * nack_ti ;
2009-01-05 23:18:00 +00:00
/****************************/
/* Read NACK_SN, E1, E2 */
2009-01-16 10:53:58 +00:00
/* NACK_SN */
2009-02-11 17:51:37 +00:00
nack_ti = proto_tree_add_bits_ret_val ( tree , hf_rlc_lte_am_nack_sn , tvb ,
2011-10-24 19:57:53 +00:00
bit_offset , 10 , & nack_sn , ENC_BIG_ENDIAN ) ;
2009-01-05 23:18:00 +00:00
bit_offset + = 10 ;
2010-07-20 13:27:20 +00:00
write_pdu_label_and_info ( top_ti , NULL , pinfo , " NACK_SN=%-4u " , ( guint16 ) nack_sn ) ;
2010-03-09 01:39:08 +00:00
2011-09-21 16:45:03 +00:00
/* We shouldn't NACK the ACK_SN! */
if ( nack_sn = = ack_sn ) {
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , nack_ti , & ei_rlc_lte_am_nack_sn_ack_same ,
2011-09-21 21:07:07 +00:00
" Status PDU shouldn't ACK and NACK the same sequence number (% " G_GINT64_MODIFIER " u) " ,
2011-09-21 16:45:03 +00:00
ack_sn ) ;
}
2012-03-11 23:44:03 +00:00
/* NACK should always be 'behind' the ACK */
if ( ( 1024 + ack_sn - nack_sn ) % 1024 > 512 ) {
2013-09-05 01:05:16 +00:00
expert_add_info ( pinfo , nack_ti , & ei_rlc_lte_am_nack_sn_ahead_ack ) ;
2012-03-11 23:44:03 +00:00
}
2010-03-04 17:49:51 +00:00
/* Copy into struct, but don't exceed buffer */
if ( nack_count < MAX_NACKs ) {
tap_info - > NACKs [ nack_count + + ] = ( guint16 ) nack_sn ;
}
2010-03-04 20:58:54 +00:00
else {
/* Let it get bigger than the array for accurate stats... */
nack_count + + ;
}
2009-01-05 23:18:00 +00:00
/* E1 */
proto_tree_add_bits_ret_val ( tree , hf_rlc_lte_am_e1 , tvb ,
2011-10-24 19:57:53 +00:00
bit_offset , 1 , & e1 , ENC_BIG_ENDIAN ) ;
2009-01-05 23:18:00 +00:00
bit_offset + + ;
/* E2 */
proto_tree_add_bits_ret_val ( tree , hf_rlc_lte_am_e2 , tvb ,
2011-10-24 19:57:53 +00:00
bit_offset , 1 , & e2 , ENC_BIG_ENDIAN ) ;
2009-12-04 11:22:33 +00:00
/* Report as expert info */
if ( e2 ) {
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , nack_ti , & ei_rlc_lte_am_nack_sn_partial ,
2010-03-01 22:52:34 +00:00
" Status PDU reports NACK (partial) on %s for UE %u " ,
2010-03-14 16:36:41 +00:00
val_to_str_const ( p_rlc_lte_info - > direction , direction_vals , " Unknown " ) ,
2010-03-01 22:52:34 +00:00
p_rlc_lte_info - > ueid ) ;
2009-12-04 11:22:33 +00:00
}
else {
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , nack_ti , & ei_rlc_lte_am_nack_sn ,
2010-03-01 22:52:34 +00:00
" Status PDU reports NACK on %s for UE %u " ,
2010-03-14 16:36:41 +00:00
val_to_str_const ( p_rlc_lte_info - > direction , direction_vals , " Unknown " ) ,
2010-03-01 22:52:34 +00:00
p_rlc_lte_info - > ueid ) ;
2009-12-04 11:22:33 +00:00
}
2009-01-05 23:18:00 +00:00
bit_offset + + ;
}
2009-01-16 10:53:58 +00:00
2009-01-05 23:18:00 +00:00
if ( e2 ) {
/* Read SOstart, SOend */
proto_tree_add_bits_ret_val ( tree , hf_rlc_lte_am_so_start , tvb ,
2011-10-24 19:57:53 +00:00
bit_offset , 15 , & so_start , ENC_BIG_ENDIAN ) ;
2009-01-05 23:18:00 +00:00
bit_offset + = 15 ;
proto_tree_add_bits_ret_val ( tree , hf_rlc_lte_am_so_end , tvb ,
2011-10-24 19:57:53 +00:00
bit_offset , 15 , & so_end , ENC_BIG_ENDIAN ) ;
2009-01-05 23:18:00 +00:00
bit_offset + = 15 ;
2009-01-16 15:41:03 +00:00
2009-07-13 11:23:40 +00:00
if ( ( guint16 ) so_end = = 0x7fff ) {
2010-03-09 01:39:08 +00:00
write_pdu_label_and_info ( top_ti , NULL , pinfo ,
2012-03-21 13:53:18 +00:00
" (SOstart=%u SOend=<END-OF_PDU>) " ,
2010-03-09 01:39:08 +00:00
( guint16 ) so_start ) ;
2009-10-29 19:06:10 +00:00
}
else {
2010-03-09 01:39:08 +00:00
write_pdu_label_and_info ( top_ti , NULL , pinfo ,
2012-03-21 13:53:18 +00:00
" (SOstart=%u SOend=%u) " ,
2010-03-09 01:39:08 +00:00
( guint16 ) so_start , ( guint16 ) so_end ) ;
2009-01-16 10:53:58 +00:00
}
2009-01-05 23:18:00 +00:00
/* Reset this flag here */
e2 = 0 ;
}
} while ( e1 | | e2 ) ;
2009-11-03 16:39:01 +00:00
if ( nack_count > 0 ) {
2011-07-18 10:40:57 +00:00
proto_item * count_ti = proto_tree_add_uint ( tree , hf_rlc_lte_am_nacks , tvb , 0 , 1 , nack_count ) ;
PROTO_ITEM_SET_GENERATED ( count_ti ) ;
2009-11-03 16:39:01 +00:00
proto_item_append_text ( status_ti , " (%u NACKs) " , nack_count ) ;
2010-01-04 14:07:24 +00:00
tap_info - > noOfNACKs = nack_count ;
2009-11-03 16:39:01 +00:00
}
2009-06-07 13:35:17 +00:00
/* Check that we've reached the end of the PDU. If not, show malformed */
offset = ( bit_offset + 7 ) / 8 ;
2014-05-05 20:32:33 +00:00
if ( tvb_reported_length_remaining ( tvb , offset ) > 0 ) {
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , status_ti , & ei_rlc_lte_bytes_after_status_pdu_complete ,
2010-06-10 15:28:41 +00:00
" %cL %u bytes remaining after Status PDU complete " ,
( p_rlc_lte_info - > direction = = DIRECTION_UPLINK ) ? ' U ' : ' D ' ,
2014-05-05 20:32:33 +00:00
tvb_reported_length_remaining ( tvb , offset ) ) ;
2009-06-07 13:35:17 +00:00
}
2009-06-11 13:58:08 +00:00
/* Set selected length of control tree */
proto_item_set_len ( status_ti , offset ) ;
2010-03-02 18:40:34 +00:00
2011-05-19 01:05:26 +00:00
/* Repeated NACK analysis & check ACK-SN is in range */
2010-03-02 18:40:34 +00:00
if ( ( ( global_rlc_lte_am_sequence_analysis = = SEQUENCE_ANALYSIS_MAC_ONLY ) & &
2013-11-23 02:20:13 +00:00
( p_get_proto_data ( wmem_file_scope ( ) , pinfo , proto_mac_lte , 0 ) ! = NULL ) ) | |
2010-03-02 18:40:34 +00:00
( ( global_rlc_lte_am_sequence_analysis = = SEQUENCE_ANALYSIS_RLC_ONLY ) & &
2013-11-23 02:20:13 +00:00
( p_get_proto_data ( wmem_file_scope ( ) , pinfo , proto_mac_lte , 0 ) = = NULL ) ) ) {
2010-03-02 18:40:34 +00:00
if ( ! is_mac_lte_frame_retx ( pinfo , p_rlc_lte_info - > direction ) ) {
checkChannelRepeatedNACKInfo ( pinfo , p_rlc_lte_info , tap_info , tree , tvb ) ;
2011-05-23 17:15:00 +00:00
checkChannelACKWindow ( ( guint16 ) ack_sn , pinfo , p_rlc_lte_info , tap_info , tree , tvb ) ;
2010-03-02 18:40:34 +00:00
}
}
2009-01-05 23:18:00 +00:00
}
/***************************************************/
/* Acknowledged mode PDU */
static void dissect_rlc_lte_am ( tvbuff_t * tvb , packet_info * pinfo ,
proto_tree * tree ,
2009-04-14 14:38:20 +00:00
int offset ,
2009-11-16 15:35:56 +00:00
rlc_lte_info * p_rlc_lte_info ,
2010-01-04 14:07:24 +00:00
proto_item * top_ti ,
rlc_lte_tap_info * tap_info )
2009-01-05 23:18:00 +00:00
{
guint8 is_data ;
2010-02-28 02:18:35 +00:00
guint8 is_resegmented ;
2009-01-22 17:18:48 +00:00
guint8 polling ;
2009-01-05 23:18:00 +00:00
guint8 fixed_extension ;
guint8 framing_info ;
2009-01-08 13:28:30 +00:00
gboolean first_includes_start ;
gboolean last_includes_end ;
2010-03-06 19:35:40 +00:00
proto_item * am_ti ;
2009-01-05 23:18:00 +00:00
proto_tree * am_header_tree ;
proto_item * am_header_ti ;
gint start_offset = offset ;
guint16 sn ;
2013-07-16 12:28:33 +00:00
gboolean is_truncated = FALSE ;
2010-02-01 11:00:08 +00:00
proto_item * truncated_ti ;
2011-09-06 12:01:28 +00:00
rlc_channel_reassembly_info * reassembly_info = NULL ;
2012-01-23 02:36:46 +00:00
sequence_analysis_state seq_anal_state = SN_OK ;
2014-12-07 19:54:05 +00:00
guint32 id ;
wmem_tree_key_t key [ 3 ] ;
rlc_ue_parameters * params ;
2009-01-05 23:18:00 +00:00
2010-03-06 19:35:40 +00:00
/* Hidden AM root */
am_ti = proto_tree_add_string_format ( tree , hf_rlc_lte_am ,
tvb , offset , 0 , " " , " AM " ) ;
PROTO_ITEM_SET_HIDDEN ( am_ti ) ;
2009-11-25 23:17:23 +00:00
/* Add AM header subtree */
2010-03-06 19:35:40 +00:00
am_header_ti = proto_tree_add_string_format ( tree , hf_rlc_lte_am_header ,
2009-01-05 23:18:00 +00:00
tvb , offset , 0 ,
2010-03-09 01:39:08 +00:00
" " , " AM Header " ) ;
2009-01-05 23:18:00 +00:00
am_header_tree = proto_item_add_subtree ( am_header_ti ,
ett_rlc_lte_am_header ) ;
/* First bit is Data/Control flag */
is_data = ( tvb_get_guint8 ( tvb , offset ) & 0x80 ) > > 7 ;
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( am_header_tree , hf_rlc_lte_am_data_control , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2010-01-04 14:07:24 +00:00
tap_info - > isControlPDU = ! is_data ;
2009-01-05 23:18:00 +00:00
if ( ! is_data ) {
2010-03-01 23:56:35 +00:00
/**********************/
/* Status PDU */
2012-11-29 22:25:18 +00:00
write_pdu_label_and_info_literal ( top_ti , NULL , pinfo , " [CONTROL] " ) ;
2009-07-13 11:23:40 +00:00
2009-06-15 09:46:13 +00:00
/* Control PDUs are a completely separate format */
2010-01-04 14:07:24 +00:00
dissect_rlc_lte_am_status_pdu ( tvb , pinfo , am_header_tree , am_header_ti ,
2010-03-01 22:52:34 +00:00
offset , top_ti ,
p_rlc_lte_info , tap_info ) ;
2009-01-05 23:18:00 +00:00
return ;
}
/******************************/
/* Data PDU fixed header */
/* Re-segmentation Flag (RF) field */
2010-02-28 02:18:35 +00:00
is_resegmented = ( tvb_get_guint8 ( tvb , offset ) & 0x40 ) > > 6 ;
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( am_header_tree , hf_rlc_lte_am_rf , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2010-02-28 02:18:35 +00:00
tap_info - > isResegmented = is_resegmented ;
2009-01-05 23:18:00 +00:00
2012-11-29 22:25:18 +00:00
write_pdu_label_and_info_literal ( top_ti , NULL , pinfo ,
( is_resegmented ) ? " [DATA-SEGMENT] " : " [DATA] " ) ;
2009-06-15 09:46:13 +00:00
2009-01-05 23:18:00 +00:00
/* Polling bit */
2009-01-22 17:18:48 +00:00
polling = ( tvb_get_guint8 ( tvb , offset ) & 0x20 ) > > 5 ;
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( am_header_tree , hf_rlc_lte_am_p , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2010-03-09 01:39:08 +00:00
2012-11-29 22:25:18 +00:00
write_pdu_label_and_info_literal ( top_ti , NULL , pinfo , ( polling ) ? " (P) " : " " ) ;
2009-01-22 17:18:48 +00:00
if ( polling ) {
2012-09-19 16:56:59 +00:00
proto_item_append_text ( am_header_ti , " (P) " ) ;
2009-01-22 17:18:48 +00:00
}
2009-01-05 23:18:00 +00:00
/* Framing Info */
framing_info = ( tvb_get_guint8 ( tvb , offset ) & 0x18 ) > > 3 ;
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( am_header_tree , hf_rlc_lte_am_fi , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2009-01-05 23:18:00 +00:00
/* Extension bit */
fixed_extension = ( tvb_get_guint8 ( tvb , offset ) & 0x04 ) > > 2 ;
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( am_header_tree , hf_rlc_lte_am_fixed_e , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2009-01-05 23:18:00 +00:00
/* Sequence Number */
sn = tvb_get_ntohs ( tvb , offset ) & 0x03ff ;
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( am_header_tree , hf_rlc_lte_am_fixed_sn , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
2009-01-05 23:18:00 +00:00
offset + = 2 ;
2010-01-04 14:07:24 +00:00
tap_info - > sequenceNumber = sn ;
2009-01-05 23:18:00 +00:00
2010-07-20 13:27:20 +00:00
write_pdu_label_and_info ( top_ti , am_header_ti , pinfo , " sn=%-4u " , sn ) ;
2009-01-05 23:18:00 +00:00
/***************************************/
/* Dissect extra segment header fields */
2010-02-28 02:18:35 +00:00
if ( is_resegmented ) {
2009-06-15 09:46:13 +00:00
guint16 segmentOffset ;
2009-01-05 23:18:00 +00:00
/* Last Segment Field (LSF) */
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( am_header_tree , hf_rlc_lte_am_segment_lsf , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2009-01-05 23:18:00 +00:00
/* SO */
2009-06-15 09:46:13 +00:00
segmentOffset = tvb_get_ntohs ( tvb , offset ) & 0x7fff ;
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( am_header_tree , hf_rlc_lte_am_segment_so , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
2011-04-11 21:34:47 +00:00
write_pdu_label_and_info ( top_ti , am_header_ti , pinfo , " SO=%u " , segmentOffset ) ;
2009-01-05 23:18:00 +00:00
offset + = 2 ;
}
/*************************************/
/* AM header extension */
if ( fixed_extension ) {
2014-12-07 19:54:05 +00:00
if ( ! PINFO_FD_VISITED ( pinfo ) ) {
id = ( p_rlc_lte_info - > channelId < < 16 ) | p_rlc_lte_info - > ueid ;
key [ 0 ] . length = 1 ;
key [ 0 ] . key = & id ;
key [ 1 ] . length = 1 ;
key [ 1 ] . key = & PINFO_FD_NUM ( pinfo ) ;
key [ 2 ] . length = 0 ;
key [ 2 ] . key = NULL ;
params = ( rlc_ue_parameters * ) wmem_tree_lookup32_array_le ( ue_parameters_tree , key ) ;
if ( params & & ( params - > id = = id ) ) {
p_rlc_lte_info - > extendedLiField = ( p_rlc_lte_info - > direction = = DIRECTION_UPLINK ) ?
( params - > ext_li_field & UL_EXT_LI ) : ( params - > ext_li_field & DL_EXT_LI ) ;
}
}
offset = dissect_rlc_lte_extension_header ( tvb , pinfo , am_header_tree , offset , p_rlc_lte_info ) ;
2009-01-05 23:18:00 +00:00
}
2011-12-01 13:53:09 +00:00
/* Header is now complete */
proto_item_set_len ( am_header_ti , offset - start_offset ) ;
2012-02-28 19:01:24 +00:00
/* Show number of extensions in header root */
if ( s_number_of_extensions > 0 ) {
proto_item_append_text ( am_header_ti , " (%u extensions) " , s_number_of_extensions ) ;
}
2011-12-01 13:53:09 +00:00
/* Extract these 2 flags from framing_info */
first_includes_start = ( framing_info & 0x02 ) = = 0 ;
last_includes_end = ( framing_info & 0x01 ) = = 0 ;
2010-02-01 11:00:08 +00:00
/* There might not be any data, if only headers (plus control data) were logged */
if ( global_rlc_lte_headers_expected ) {
2014-05-05 20:32:33 +00:00
is_truncated = ( tvb_reported_length_remaining ( tvb , offset ) = = 0 ) ;
2010-02-01 11:00:08 +00:00
truncated_ti = proto_tree_add_uint ( tree , hf_rlc_lte_header_only , tvb , 0 , 0 ,
is_truncated ) ;
if ( is_truncated ) {
2011-12-01 13:53:09 +00:00
int n ;
2010-02-01 11:00:08 +00:00
PROTO_ITEM_SET_GENERATED ( truncated_ti ) ;
2013-09-05 01:05:16 +00:00
expert_add_info ( pinfo , truncated_ti , & ei_rlc_lte_header_only ) ;
2011-12-01 13:53:09 +00:00
/* Show in the info column how long the data would be */
for ( n = 0 ; n < s_number_of_extensions ; n + + ) {
show_PDU_in_info ( pinfo , top_ti , s_lengths [ n ] ,
( n = = 0 ) ? first_includes_start : TRUE ,
TRUE ) ;
offset + = s_lengths [ n ] ;
}
/* Last one */
2011-12-01 23:17:17 +00:00
show_PDU_in_info ( pinfo , top_ti , p_rlc_lte_info - > pduLength - offset ,
( s_number_of_extensions = = 0 ) ? first_includes_start : TRUE ,
last_includes_end ) ;
2010-02-01 11:00:08 +00:00
}
else {
PROTO_ITEM_SET_HIDDEN ( truncated_ti ) ;
}
}
2010-02-28 02:18:35 +00:00
/* Call sequence analysis function now */
if ( ( ( global_rlc_lte_am_sequence_analysis = = SEQUENCE_ANALYSIS_MAC_ONLY ) & &
2013-11-23 02:20:13 +00:00
( p_get_proto_data ( wmem_file_scope ( ) , pinfo , proto_mac_lte , 0 ) ! = NULL ) ) | |
2010-02-28 02:18:35 +00:00
( ( global_rlc_lte_am_sequence_analysis = = SEQUENCE_ANALYSIS_RLC_ONLY ) & &
2013-11-23 02:20:13 +00:00
( p_get_proto_data ( wmem_file_scope ( ) , pinfo , proto_mac_lte , 0 ) = = NULL ) ) ) {
2010-02-28 02:18:35 +00:00
2011-09-06 12:01:28 +00:00
guint16 firstSegmentLength ;
guint16 lastSegmentOffset = offset ;
if ( s_number_of_extensions > = 1 ) {
int n ;
for ( n = 0 ; n < s_number_of_extensions ; n + + ) {
lastSegmentOffset + = s_lengths [ n ] ;
}
firstSegmentLength = s_lengths [ 0 ] ;
}
else {
2014-05-05 20:32:33 +00:00
firstSegmentLength = tvb_reported_length_remaining ( tvb , offset ) ;
2011-09-06 12:01:28 +00:00
}
2012-01-23 02:36:46 +00:00
seq_anal_state = checkChannelSequenceInfo ( pinfo , tvb , p_rlc_lte_info , FALSE ,
s_number_of_extensions + 1 ,
offset , firstSegmentLength ,
lastSegmentOffset ,
( guint16 ) sn ,
first_includes_start , last_includes_end ,
is_resegmented , tap_info , tree ) ;
2009-04-14 14:38:20 +00:00
}
2013-07-16 12:28:33 +00:00
if ( is_truncated ) {
return ;
}
2009-04-14 14:38:20 +00:00
2009-01-05 23:18:00 +00:00
/*************************************/
2011-09-06 12:01:28 +00:00
/* Data */
2014-01-10 12:51:57 +00:00
if ( ! first_includes_start ) {
2014-08-14 18:55:06 +00:00
reassembly_info = ( rlc_channel_reassembly_info * ) g_hash_table_lookup ( reassembly_report_hash ,
get_report_hash_key ( ( guint16 ) sn ,
pinfo - > fd - > num ,
p_rlc_lte_info ,
FALSE ) ) ;
2014-01-10 12:51:57 +00:00
}
2011-09-06 12:01:28 +00:00
2009-01-05 23:18:00 +00:00
if ( s_number_of_extensions > 0 ) {
/* Show each data segment separately */
int n ;
for ( n = 0 ; n < s_number_of_extensions ; n + + ) {
2011-02-02 23:23:07 +00:00
show_PDU_in_tree ( pinfo , tree , tvb , offset , s_lengths [ n ] , p_rlc_lte_info ,
2011-09-06 12:01:28 +00:00
( n = = 0 ) ? first_includes_start : TRUE ,
2012-01-23 02:36:46 +00:00
( n = = 0 ) ? reassembly_info : NULL ,
seq_anal_state ) ;
2009-09-15 17:49:58 +00:00
show_PDU_in_info ( pinfo , top_ti , s_lengths [ n ] ,
2009-01-05 23:18:00 +00:00
( n = = 0 ) ? first_includes_start : TRUE ,
TRUE ) ;
2014-06-05 17:58:22 +00:00
/* Make sure we don't lose the summary of this SDU */
col_append_str ( pinfo - > cinfo , COL_INFO , " | " ) ;
col_set_fence ( pinfo - > cinfo , COL_INFO ) ;
2009-01-16 10:53:58 +00:00
tvb_ensure_bytes_exist ( tvb , offset , s_lengths [ n ] ) ;
2009-01-05 23:18:00 +00:00
offset + = s_lengths [ n ] ;
}
}
/* Final data element */
2014-05-05 20:32:33 +00:00
if ( tvb_reported_length_remaining ( tvb , offset ) > 0 ) {
2014-06-12 12:42:35 +00:00
show_PDU_in_tree ( pinfo , tree , tvb , offset , tvb_reported_length_remaining ( tvb , offset ) , p_rlc_lte_info ,
2011-09-06 12:01:28 +00:00
( ( s_number_of_extensions = = 0 ) ? first_includes_start : TRUE ) & & last_includes_end ,
2012-01-23 02:36:46 +00:00
( s_number_of_extensions = = 0 ) ? reassembly_info : NULL ,
seq_anal_state ) ;
2014-05-05 20:32:33 +00:00
show_PDU_in_info ( pinfo , top_ti , ( guint16 ) tvb_reported_length_remaining ( tvb , offset ) ,
2009-06-11 13:58:08 +00:00
( s_number_of_extensions = = 0 ) ? first_includes_start : TRUE ,
last_includes_end ) ;
}
2009-07-07 17:07:24 +00:00
else {
2010-02-01 11:00:08 +00:00
/* Report that expected data was missing (unless we know it might happen) */
if ( ! global_rlc_lte_headers_expected ) {
if ( s_number_of_extensions > 0 ) {
2013-09-05 01:05:16 +00:00
expert_add_info ( pinfo , am_header_ti , & ei_rlc_lte_am_data_no_data_beyond_extensions ) ;
2010-02-01 11:00:08 +00:00
}
else {
2013-09-05 01:05:16 +00:00
expert_add_info ( pinfo , am_header_ti , & ei_rlc_lte_am_data_no_data ) ;
2010-02-01 11:00:08 +00:00
}
2009-11-25 23:17:23 +00:00
}
2009-07-07 17:07:24 +00:00
}
2009-01-05 23:18:00 +00:00
}
2009-12-07 10:23:35 +00:00
/* Heuristic dissector looks for supported framing protocol (see wiki page) */
static gboolean dissect_rlc_lte_heur ( tvbuff_t * tvb , packet_info * pinfo ,
2012-09-10 21:40:21 +00:00
proto_tree * tree , void * data _U_ )
2009-12-07 10:23:35 +00:00
{
gint offset = 0 ;
struct rlc_lte_info * p_rlc_lte_info ;
tvbuff_t * rlc_tvb ;
guint8 tag = 0 ;
gboolean infoAlreadySet = FALSE ;
gboolean umSeqNumLengthTagPresent = FALSE ;
/* This is a heuristic dissector, which means we get all the UDP
* traffic not sent to a known dissector and not claimed by
* a heuristic dissector called before us !
*/
if ( ! global_rlc_lte_heur ) {
return FALSE ;
}
/* Do this again on re-dissection to re-discover offset of actual PDU */
2010-10-10 20:39:00 +00:00
2009-12-07 10:23:35 +00:00
/* Needs to be at least as long as:
- the signature string
- fixed header bytes
- tag for data
- at least one byte of RLC PDU payload */
2014-05-05 20:32:33 +00:00
if ( tvb_captured_length_remaining ( tvb , offset ) < ( gint ) ( strlen ( RLC_LTE_START_STRING ) + 1 + 2 ) ) {
2009-12-07 10:23:35 +00:00
return FALSE ;
}
/* OK, compare with signature string */
if ( tvb_strneql ( tvb , offset , RLC_LTE_START_STRING , ( gint ) strlen ( RLC_LTE_START_STRING ) ) ! = 0 ) {
return FALSE ;
}
offset + = ( gint ) strlen ( RLC_LTE_START_STRING ) ;
2010-11-02 15:17:58 +00:00
/* If redissecting, use previous info struct (if available) */
2013-11-23 02:20:13 +00:00
p_rlc_lte_info = ( rlc_lte_info * ) p_get_proto_data ( wmem_file_scope ( ) , pinfo , proto_rlc_lte , 0 ) ;
2010-11-02 15:17:58 +00:00
if ( p_rlc_lte_info = = NULL ) {
/* Allocate new info struct for this frame */
2013-08-30 14:49:55 +00:00
p_rlc_lte_info = wmem_new0 ( wmem_file_scope ( ) , struct rlc_lte_info ) ;
2010-11-02 15:17:58 +00:00
infoAlreadySet = FALSE ;
}
else {
infoAlreadySet = TRUE ;
}
2009-12-07 10:23:35 +00:00
/* Read fixed fields */
p_rlc_lte_info - > rlcMode = tvb_get_guint8 ( tvb , offset + + ) ;
/* Read optional fields */
while ( tag ! = RLC_LTE_PAYLOAD_TAG ) {
/* Process next tag */
tag = tvb_get_guint8 ( tvb , offset + + ) ;
switch ( tag ) {
case RLC_LTE_UM_SN_LENGTH_TAG :
p_rlc_lte_info - > UMSequenceNumberLength = tvb_get_guint8 ( tvb , offset ) ;
offset + + ;
umSeqNumLengthTagPresent = TRUE ;
break ;
case RLC_LTE_DIRECTION_TAG :
p_rlc_lte_info - > direction = tvb_get_guint8 ( tvb , offset ) ;
offset + + ;
break ;
case RLC_LTE_PRIORITY_TAG :
p_rlc_lte_info - > priority = tvb_get_guint8 ( tvb , offset ) ;
offset + + ;
break ;
case RLC_LTE_UEID_TAG :
p_rlc_lte_info - > ueid = tvb_get_ntohs ( tvb , offset ) ;
offset + = 2 ;
break ;
case RLC_LTE_CHANNEL_TYPE_TAG :
p_rlc_lte_info - > channelType = tvb_get_ntohs ( tvb , offset ) ;
offset + = 2 ;
break ;
case RLC_LTE_CHANNEL_ID_TAG :
p_rlc_lte_info - > channelId = tvb_get_ntohs ( tvb , offset ) ;
offset + = 2 ;
break ;
2014-12-07 19:54:05 +00:00
case RLC_LTE_EXT_LI_FIELD_TAG :
p_rlc_lte_info - > extendedLiField = TRUE ;
break ;
2009-12-07 10:23:35 +00:00
case RLC_LTE_PAYLOAD_TAG :
/* Have reached data, so set payload length and get out of loop */
2014-12-07 19:54:05 +00:00
p_rlc_lte_info - > pduLength = tvb_reported_length_remaining ( tvb , offset ) ;
2009-12-07 10:23:35 +00:00
continue ;
default :
/* It must be a recognised tag */
return FALSE ;
}
}
if ( ( p_rlc_lte_info - > rlcMode = = RLC_UM_MODE ) & & ( umSeqNumLengthTagPresent = = FALSE ) ) {
/* Conditional field is not present */
return FALSE ;
}
if ( ! infoAlreadySet ) {
/* Store info in packet */
2013-11-23 02:20:13 +00:00
p_add_proto_data ( wmem_file_scope ( ) , pinfo , proto_rlc_lte , 0 , p_rlc_lte_info ) ;
2009-12-07 10:23:35 +00:00
}
/**************************************/
/* OK, now dissect as RLC LTE */
/* Create tvb that starts at actual RLC PDU */
2013-02-19 23:17:07 +00:00
rlc_tvb = tvb_new_subset_remaining ( tvb , offset ) ;
2013-07-03 20:03:52 +00:00
dissect_rlc_lte_common ( rlc_tvb , pinfo , tree , TRUE ) ;
2009-12-07 10:23:35 +00:00
return TRUE ;
}
2012-01-22 02:55:47 +00:00
2009-01-05 23:18:00 +00:00
/*****************************/
/* Main dissection function. */
/*****************************/
2010-10-10 20:39:00 +00:00
static void dissect_rlc_lte ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree )
2013-07-03 20:03:52 +00:00
{
dissect_rlc_lte_common ( tvb , pinfo , tree , FALSE ) ;
}
static void dissect_rlc_lte_common ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree , gboolean is_udp_framing )
2009-01-05 23:18:00 +00:00
{
proto_tree * rlc_lte_tree ;
2010-03-09 01:39:08 +00:00
proto_tree * context_tree ;
2009-09-10 22:53:57 +00:00
proto_item * top_ti ;
2010-03-09 01:39:08 +00:00
proto_item * context_ti ;
2009-01-05 23:18:00 +00:00
proto_item * ti ;
proto_item * mode_ti ;
gint offset = 0 ;
struct rlc_lte_info * p_rlc_lte_info = NULL ;
2010-07-13 16:25:34 +00:00
/* Allocate and Zero tap struct */
2013-08-30 14:49:55 +00:00
rlc_lte_tap_info * tap_info = wmem_new0 ( wmem_packet_scope ( ) , rlc_lte_tap_info ) ;
2010-01-04 14:07:24 +00:00
2009-01-05 23:18:00 +00:00
/* Set protocol name */
2009-07-13 11:23:40 +00:00
col_set_str ( pinfo - > cinfo , COL_PROTOCOL , " RLC-LTE " ) ;
2009-01-05 23:18:00 +00:00
/* Create protocol tree. */
2011-10-21 02:10:19 +00:00
top_ti = proto_tree_add_item ( tree , proto_rlc_lte , tvb , offset , - 1 , ENC_NA ) ;
2009-09-10 22:53:57 +00:00
rlc_lte_tree = proto_item_add_subtree ( top_ti , ett_rlc_lte ) ;
2009-01-05 23:18:00 +00:00
/* Look for packet info! */
2013-11-23 02:20:13 +00:00
p_rlc_lte_info = ( rlc_lte_info * ) p_get_proto_data ( wmem_file_scope ( ) , pinfo , proto_rlc_lte , 0 ) ;
2009-01-05 23:18:00 +00:00
/* Can't dissect anything without it... */
if ( p_rlc_lte_info = = NULL ) {
2014-09-06 12:44:23 +00:00
proto_tree_add_expert ( rlc_lte_tree , pinfo , & ei_rlc_lte_no_per_frame_info , tvb , offset , - 1 ) ;
2009-01-05 23:18:00 +00:00
return ;
}
2013-07-03 20:03:52 +00:00
/* Clear info column when using UDP framing */
if ( is_udp_framing ) {
col_clear ( pinfo - > cinfo , COL_INFO ) ;
}
2009-01-05 23:18:00 +00:00
/*****************************************/
/* Show context information */
2010-03-09 01:39:08 +00:00
/* Create context root */
context_ti = proto_tree_add_string_format ( rlc_lte_tree , hf_rlc_lte_context ,
tvb , offset , 0 , " " , " Context " ) ;
context_tree = proto_item_add_subtree ( context_ti , ett_rlc_lte_context ) ;
PROTO_ITEM_SET_GENERATED ( context_ti ) ;
ti = proto_tree_add_uint ( context_tree , hf_rlc_lte_context_direction ,
2009-01-05 23:18:00 +00:00
tvb , 0 , 0 , p_rlc_lte_info - > direction ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
2010-03-09 01:39:08 +00:00
mode_ti = proto_tree_add_uint ( context_tree , hf_rlc_lte_context_mode ,
2009-01-05 23:18:00 +00:00
tvb , 0 , 0 , p_rlc_lte_info - > rlcMode ) ;
PROTO_ITEM_SET_GENERATED ( mode_ti ) ;
2009-03-11 11:17:16 +00:00
if ( p_rlc_lte_info - > ueid ! = 0 ) {
2010-03-09 01:39:08 +00:00
ti = proto_tree_add_uint ( context_tree , hf_rlc_lte_context_ueid ,
2009-03-11 11:17:16 +00:00
tvb , 0 , 0 , p_rlc_lte_info - > ueid ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
}
2009-01-05 23:18:00 +00:00
2011-11-24 12:44:11 +00:00
if ( ( p_rlc_lte_info - > priority > = 1 ) & & ( p_rlc_lte_info - > priority < = 16 ) ) {
ti = proto_tree_add_uint ( context_tree , hf_rlc_lte_context_priority ,
tvb , 0 , 0 , p_rlc_lte_info - > priority ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
}
2009-01-05 23:18:00 +00:00
2010-03-09 01:39:08 +00:00
ti = proto_tree_add_uint ( context_tree , hf_rlc_lte_context_channel_type ,
2009-01-05 23:18:00 +00:00
tvb , 0 , 0 , p_rlc_lte_info - > channelType ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
2009-03-11 11:17:16 +00:00
if ( ( p_rlc_lte_info - > channelType = = CHANNEL_TYPE_SRB ) | |
2013-07-26 10:21:05 +00:00
( p_rlc_lte_info - > channelType = = CHANNEL_TYPE_DRB ) | |
( p_rlc_lte_info - > channelType = = CHANNEL_TYPE_MTCH ) ) {
2010-03-09 01:39:08 +00:00
ti = proto_tree_add_uint ( context_tree , hf_rlc_lte_context_channel_id ,
2009-03-11 11:17:16 +00:00
tvb , 0 , 0 , p_rlc_lte_info - > channelId ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
}
2009-01-05 23:18:00 +00:00
2010-03-09 01:39:08 +00:00
ti = proto_tree_add_uint ( context_tree , hf_rlc_lte_context_pdu_length ,
2009-01-05 23:18:00 +00:00
tvb , 0 , 0 , p_rlc_lte_info - > pduLength ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
if ( p_rlc_lte_info - > rlcMode = = RLC_UM_MODE ) {
2010-03-09 01:39:08 +00:00
ti = proto_tree_add_uint ( context_tree , hf_rlc_lte_context_um_sn_length ,
2009-01-05 23:18:00 +00:00
tvb , 0 , 0 , p_rlc_lte_info - > UMSequenceNumberLength ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
}
2009-09-11 15:16:53 +00:00
/* Append highlights to top-level item */
if ( p_rlc_lte_info - > ueid ! = 0 ) {
proto_item_append_text ( top_ti , " UEId=%u " , p_rlc_lte_info - > ueid ) ;
2014-01-10 12:51:57 +00:00
col_append_fstr ( pinfo - > cinfo , COL_INFO , " UEId=%-4u " , p_rlc_lte_info - > ueid ) ;
2009-09-11 15:16:53 +00:00
}
2014-02-25 16:27:32 +00:00
2009-01-05 23:18:00 +00:00
/* Append context highlights to info column */
2010-03-09 01:39:08 +00:00
write_pdu_label_and_info ( top_ti , NULL , pinfo ,
2013-11-04 15:10:58 +00:00
" [%s] [%s] " ,
2010-03-09 01:39:08 +00:00
( p_rlc_lte_info - > direction = = 0 ) ? " UL " : " DL " ,
2010-03-14 16:36:41 +00:00
val_to_str_const ( p_rlc_lte_info - > rlcMode , rlc_mode_short_vals , " Unknown " ) ) ;
2014-01-10 12:51:57 +00:00
2009-07-13 11:23:40 +00:00
if ( p_rlc_lte_info - > channelId = = 0 ) {
2013-07-16 12:28:33 +00:00
write_pdu_label_and_info ( top_ti , NULL , pinfo , " %s " ,
val_to_str_const ( p_rlc_lte_info - > channelType , rlc_channel_type_vals , " Unknown " ) ) ;
2009-07-13 11:23:40 +00:00
}
else {
2010-06-28 17:25:58 +00:00
write_pdu_label_and_info ( top_ti , NULL , pinfo , " %s:%-2u " ,
2010-03-14 16:36:41 +00:00
val_to_str_const ( p_rlc_lte_info - > channelType , rlc_channel_type_vals , " Unknown " ) ,
2010-03-09 01:39:08 +00:00
p_rlc_lte_info - > channelId ) ;
2009-01-05 23:18:00 +00:00
}
2010-01-04 14:07:24 +00:00
/* Set context-info parts of tap struct */
2010-07-13 16:25:34 +00:00
tap_info - > rlcMode = p_rlc_lte_info - > rlcMode ;
tap_info - > direction = p_rlc_lte_info - > direction ;
tap_info - > priority = p_rlc_lte_info - > priority ;
tap_info - > ueid = p_rlc_lte_info - > ueid ;
tap_info - > channelType = p_rlc_lte_info - > channelType ;
tap_info - > channelId = p_rlc_lte_info - > channelId ;
tap_info - > pduLength = p_rlc_lte_info - > pduLength ;
tap_info - > UMSequenceNumberLength = p_rlc_lte_info - > UMSequenceNumberLength ;
2013-11-23 02:20:13 +00:00
tap_info - > loggedInMACFrame = ( p_get_proto_data ( wmem_file_scope ( ) , pinfo , proto_mac_lte , 0 ) ! = NULL ) ;
2010-01-04 14:07:24 +00:00
2010-09-03 15:22:28 +00:00
tap_info - > time = pinfo - > fd - > abs_ts ;
2009-01-05 23:18:00 +00:00
/* Reset this count */
s_number_of_extensions = 0 ;
/* Dissect the RLC PDU itself. Format depends upon mode... */
switch ( p_rlc_lte_info - > rlcMode ) {
case RLC_TM_MODE :
2009-11-16 15:35:56 +00:00
dissect_rlc_lte_tm ( tvb , pinfo , rlc_lte_tree , offset , p_rlc_lte_info , top_ti ) ;
2009-01-05 23:18:00 +00:00
break ;
case RLC_UM_MODE :
2010-01-04 14:07:24 +00:00
dissect_rlc_lte_um ( tvb , pinfo , rlc_lte_tree , offset , p_rlc_lte_info , top_ti ,
2010-07-13 16:25:34 +00:00
tap_info ) ;
2009-01-05 23:18:00 +00:00
break ;
case RLC_AM_MODE :
2010-01-04 14:07:24 +00:00
dissect_rlc_lte_am ( tvb , pinfo , rlc_lte_tree , offset , p_rlc_lte_info , top_ti ,
2010-07-13 16:25:34 +00:00
tap_info ) ;
2009-01-05 23:18:00 +00:00
break ;
2009-01-21 15:44:22 +00:00
case RLC_PREDEF :
/* Predefined data (i.e. not containing a valid RLC header */
2011-10-04 22:44:31 +00:00
proto_tree_add_item ( rlc_lte_tree , hf_rlc_lte_predefined_pdu , tvb , offset , - 1 , ENC_NA ) ;
2010-03-09 01:39:08 +00:00
write_pdu_label_and_info ( top_ti , NULL , pinfo , " [%u-bytes] " ,
2014-05-05 20:32:33 +00:00
tvb_reported_length_remaining ( tvb , offset ) ) ;
2009-01-21 15:44:22 +00:00
break ;
2009-01-05 23:18:00 +00:00
default :
/* Error - unrecognised mode */
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , mode_ti , & ei_rlc_lte_context_mode ,
2009-01-05 23:18:00 +00:00
" Unrecognised RLC Mode set (%u) " , p_rlc_lte_info - > rlcMode ) ;
break ;
}
2010-01-04 14:07:24 +00:00
/* Queue tap info */
2010-07-13 16:25:34 +00:00
tap_queue_packet ( rlc_lte_tap , pinfo , tap_info ) ;
2009-01-05 23:18:00 +00:00
}
2009-04-14 14:38:20 +00:00
2012-01-14 20:14:43 +00:00
/* Initializes the hash tables each time a new
2009-04-14 14:38:20 +00:00
* file is loaded or re - loaded in wireshark */
2014-08-14 18:55:06 +00:00
static void rlc_lte_init_protocol ( void )
2009-04-14 14:38:20 +00:00
{
/* Destroy any existing hashes. */
2012-01-23 02:36:46 +00:00
if ( sequence_analysis_channel_hash ) {
g_hash_table_destroy ( sequence_analysis_channel_hash ) ;
2009-04-14 14:38:20 +00:00
}
2012-01-23 02:36:46 +00:00
if ( sequence_analysis_report_hash ) {
g_hash_table_destroy ( sequence_analysis_report_hash ) ;
2009-04-14 14:38:20 +00:00
}
2012-01-23 02:36:46 +00:00
if ( repeated_nack_channel_hash ) {
g_hash_table_destroy ( repeated_nack_channel_hash ) ;
2010-03-02 18:40:34 +00:00
}
2012-01-23 02:36:46 +00:00
if ( repeated_nack_report_hash ) {
g_hash_table_destroy ( repeated_nack_report_hash ) ;
2010-03-02 18:40:34 +00:00
}
2012-01-23 02:36:46 +00:00
if ( reassembly_report_hash ) {
g_hash_table_destroy ( reassembly_report_hash ) ;
2011-09-06 12:01:28 +00:00
}
2009-04-14 14:38:20 +00:00
/* Now create them over */
2012-01-23 02:36:46 +00:00
sequence_analysis_channel_hash = g_hash_table_new ( rlc_channel_hash_func , rlc_channel_equal ) ;
sequence_analysis_report_hash = g_hash_table_new ( rlc_result_hash_func , rlc_result_hash_equal ) ;
2010-03-02 18:40:34 +00:00
2012-01-23 02:36:46 +00:00
repeated_nack_channel_hash = g_hash_table_new ( rlc_channel_hash_func , rlc_channel_equal ) ;
repeated_nack_report_hash = g_hash_table_new ( rlc_result_hash_func , rlc_result_hash_equal ) ;
reassembly_report_hash = g_hash_table_new ( rlc_result_hash_func , rlc_result_hash_equal ) ;
2009-04-14 14:38:20 +00:00
}
2014-12-07 19:54:05 +00:00
/* Configure number of PDCP SN bits to use for DRB channels */
void set_rlc_lte_drb_pdcp_seqnum_length ( packet_info * pinfo , guint16 ueid , guint8 drbid ,
2011-09-10 23:46:49 +00:00
guint8 userplane_seqnum_length )
2011-04-17 21:34:47 +00:00
{
2014-12-07 19:54:05 +00:00
wmem_tree_key_t key [ 3 ] ;
guint32 id ;
rlc_ue_parameters * params ;
if ( PINFO_FD_VISITED ( pinfo ) ) {
return ;
}
id = ( drbid < < 16 ) | ueid ;
key [ 0 ] . length = 1 ;
key [ 0 ] . key = & id ;
key [ 1 ] . length = 1 ;
key [ 1 ] . key = & PINFO_FD_NUM ( pinfo ) ;
key [ 2 ] . length = 0 ;
key [ 2 ] . key = NULL ;
params = ( rlc_ue_parameters * ) wmem_tree_lookup32_array_le ( ue_parameters_tree , key ) ;
if ( params & & ( params - > id ! = id ) ) {
params = NULL ;
}
if ( params = = NULL ) {
params = ( rlc_ue_parameters * ) wmem_new ( wmem_file_scope ( ) , rlc_ue_parameters ) ;
params - > id = id ;
params - > ext_li_field = NO_EXT_LI ;
wmem_tree_insert32_array ( ue_parameters_tree , key , ( void * ) params ) ;
}
params - > pdcp_sn_bits = userplane_seqnum_length ;
2011-04-17 21:34:47 +00:00
}
2014-12-07 19:54:05 +00:00
/*Configure LI field for AM DRB channels */
void set_rlc_lte_drb_li_field ( packet_info * pinfo , guint16 ueid , guint8 drbid ,
gboolean ul_ext_li_field , gboolean dl_ext_li_field )
{
wmem_tree_key_t key [ 3 ] ;
guint32 id ;
rlc_ue_parameters * params ;
if ( PINFO_FD_VISITED ( pinfo ) ) {
return ;
}
id = ( drbid < < 16 ) | ueid ;
key [ 0 ] . length = 1 ;
key [ 0 ] . key = & id ;
key [ 1 ] . length = 1 ;
key [ 1 ] . key = & PINFO_FD_NUM ( pinfo ) ;
key [ 2 ] . length = 0 ;
key [ 2 ] . key = NULL ;
params = ( rlc_ue_parameters * ) wmem_tree_lookup32_array_le ( ue_parameters_tree , key ) ;
if ( params & & ( params - > id ! = id ) ) {
params = NULL ;
}
if ( params = = NULL ) {
params = ( rlc_ue_parameters * ) wmem_new ( wmem_file_scope ( ) , rlc_ue_parameters ) ;
params - > id = id ;
params - > pdcp_sn_bits = 12 ;
wmem_tree_insert32_array ( ue_parameters_tree , key , ( void * ) params ) ;
}
params - > ext_li_field = ul_ext_li_field ? UL_EXT_LI : NO_EXT_LI ;
params - > ext_li_field | = dl_ext_li_field ? DL_EXT_LI : NO_EXT_LI ;
}
2009-04-14 14:38:20 +00:00
2009-01-05 23:18:00 +00:00
void proto_register_rlc_lte ( void )
{
static hf_register_info hf [ ] =
{
/**********************************/
/* Items for decoding context */
2010-03-09 01:39:08 +00:00
{ & hf_rlc_lte_context ,
{ " Context " ,
" rlc-lte.context " , FT_STRING , BASE_NONE , NULL , 0x0 ,
NULL , HFILL
}
} ,
2009-01-05 23:18:00 +00:00
{ & hf_rlc_lte_context_mode ,
{ " RLC Mode " ,
" rlc-lte.mode " , FT_UINT8 , BASE_DEC , VALS ( rlc_mode_vals ) , 0x0 ,
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
NULL , HFILL
2009-01-05 23:18:00 +00:00
}
} ,
{ & hf_rlc_lte_context_direction ,
{ " Direction " ,
" rlc-lte.direction " , FT_UINT8 , BASE_DEC , VALS ( direction_vals ) , 0x0 ,
" Direction of message " , HFILL
}
} ,
{ & hf_rlc_lte_context_priority ,
{ " Priority " ,
" rlc-lte.priority " , FT_UINT8 , BASE_DEC , 0 , 0x0 ,
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
NULL , HFILL
2009-01-05 23:18:00 +00:00
}
} ,
{ & hf_rlc_lte_context_ueid ,
{ " UEId " ,
" rlc-lte.ueid " , FT_UINT16 , BASE_DEC , 0 , 0x0 ,
" User Equipment Identifier associated with message " , HFILL
}
} ,
{ & hf_rlc_lte_context_channel_type ,
{ " Channel Type " ,
" rlc-lte.channel-type " , FT_UINT16 , BASE_DEC , VALS ( rlc_channel_type_vals ) , 0x0 ,
" Channel Type associated with message " , HFILL
}
} ,
{ & hf_rlc_lte_context_channel_id ,
{ " Channel ID " ,
" rlc-lte.channel-id " , FT_UINT16 , BASE_DEC , 0 , 0x0 ,
" Channel ID associated with message " , HFILL
}
} ,
{ & hf_rlc_lte_context_pdu_length ,
{ " PDU Length " ,
2012-02-03 10:42:01 +00:00
" rlc-lte.pdu-length " , FT_UINT16 , BASE_DEC , 0 , 0x0 ,
2009-01-05 23:18:00 +00:00
" Length of PDU (in bytes) " , HFILL
}
} ,
{ & hf_rlc_lte_context_um_sn_length ,
{ " UM Sequence number length " ,
" rlc-lte.um-seqnum-length " , FT_UINT8 , BASE_DEC , 0 , 0x0 ,
" Length of UM sequence number in bits " , HFILL
}
} ,
/* Transparent mode fields */
2010-03-06 19:35:40 +00:00
{ & hf_rlc_lte_tm ,
{ " TM " ,
" rlc-lte.tm " , FT_STRING , BASE_NONE , NULL , 0x0 ,
" Transparent Mode " , HFILL
}
} ,
2009-01-05 23:18:00 +00:00
{ & hf_rlc_lte_tm_data ,
{ " TM Data " ,
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
" rlc-lte.tm.data " , FT_BYTES , BASE_NONE , 0 , 0x0 ,
2009-01-05 23:18:00 +00:00
" Transparent Mode Data " , HFILL
}
} ,
/* Unacknowledged mode fields */
2010-03-06 19:35:40 +00:00
{ & hf_rlc_lte_um ,
{ " UM " ,
" rlc-lte.um " , FT_STRING , BASE_NONE , NULL , 0x0 ,
2013-04-01 15:29:49 +00:00
" Unacknowledged Mode " , HFILL
2010-03-06 19:35:40 +00:00
}
} ,
2009-01-05 23:18:00 +00:00
{ & hf_rlc_lte_um_header ,
{ " UM Header " ,
" rlc-lte.um.header " , FT_STRING , BASE_NONE , NULL , 0x0 ,
2013-04-01 15:29:49 +00:00
" Unacknowledged Mode Header " , HFILL
2009-01-05 23:18:00 +00:00
}
} ,
{ & hf_rlc_lte_um_fi ,
{ " Framing Info " ,
" rlc-lte.um.fi " , FT_UINT8 , BASE_HEX , VALS ( framing_info_vals ) , 0x0 ,
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
NULL , HFILL
2009-01-05 23:18:00 +00:00
}
} ,
{ & hf_rlc_lte_um_fixed_e ,
{ " Extension " ,
" rlc-lte.um.fixed.e " , FT_UINT8 , BASE_HEX , VALS ( fixed_extension_vals ) , 0x0 ,
" Extension in fixed part of UM header " , HFILL
}
} ,
{ & hf_rlc_lte_um_sn ,
{ " Sequence number " ,
" rlc-lte.um.sn " , FT_UINT8 , BASE_DEC , 0 , 0x0 ,
" Unacknowledged Mode Sequence Number " , HFILL
}
} ,
{ & hf_rlc_lte_um_fixed_reserved ,
{ " Reserved " ,
" rlc-lte.um.reserved " , FT_UINT8 , BASE_DEC , 0 , 0xe0 ,
" Unacknowledged Mode Fixed header reserved bits " , HFILL
}
} ,
{ & hf_rlc_lte_um_data ,
{ " UM Data " ,
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
" rlc-lte.um.data " , FT_BYTES , BASE_NONE , 0 , 0x0 ,
2009-01-05 23:18:00 +00:00
" Unacknowledged Mode Data " , HFILL
}
} ,
{ & hf_rlc_lte_extension_part ,
{ " Extension Part " ,
" rlc-lte.extension-part " , FT_STRING , BASE_NONE , 0 , 0x0 ,
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
NULL , HFILL
2009-01-05 23:18:00 +00:00
}
} ,
{ & hf_rlc_lte_extension_e ,
{ " Extension " ,
" rlc-lte.extension.e " , FT_UINT8 , BASE_HEX , VALS ( extension_extension_vals ) , 0x0 ,
" Extension in extended part of the header " , HFILL
}
} ,
{ & hf_rlc_lte_extension_li ,
{ " Length Indicator " ,
" rlc-lte.extension.li " , FT_UINT16 , BASE_DEC , 0 , 0x0 ,
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
NULL , HFILL
2009-01-05 23:18:00 +00:00
}
} ,
{ & hf_rlc_lte_extension_padding ,
{ " Padding " ,
" rlc-lte.extension.padding " , FT_UINT8 , BASE_HEX , 0 , 0x0f ,
" Extension header padding " , HFILL
}
} ,
2013-11-22 17:18:11 +00:00
/* Acknowledged mode fields */
2010-03-06 19:35:40 +00:00
{ & hf_rlc_lte_am ,
{ " AM " ,
" rlc-lte.am " , FT_STRING , BASE_NONE , NULL , 0x0 ,
2013-04-01 15:29:49 +00:00
" Acknowledged Mode " , HFILL
2010-03-06 19:35:40 +00:00
}
} ,
2009-01-05 23:18:00 +00:00
{ & hf_rlc_lte_am_header ,
2010-01-06 17:07:37 +00:00
{ " AM Header " ,
2009-01-05 23:18:00 +00:00
" rlc-lte.am.header " , FT_STRING , BASE_NONE , NULL , 0x0 ,
2013-04-01 15:29:49 +00:00
" Acknowledged Mode Header " , HFILL
2009-01-05 23:18:00 +00:00
}
} ,
{ & hf_rlc_lte_am_data_control ,
{ " Frame type " ,
2012-02-03 10:42:01 +00:00
" rlc-lte.am.frame-type " , FT_UINT8 , BASE_HEX , VALS ( data_or_control_vals ) , 0x80 ,
2009-01-05 23:18:00 +00:00
" AM Frame Type (Control or Data) " , HFILL
}
} ,
{ & hf_rlc_lte_am_rf ,
{ " Re-segmentation Flag " ,
" rlc-lte.am.rf " , FT_UINT8 , BASE_HEX , VALS ( resegmentation_flag_vals ) , 0x40 ,
" AM Re-segmentation Flag " , HFILL
}
} ,
{ & hf_rlc_lte_am_p ,
{ " Polling Bit " ,
" rlc-lte.am.p " , FT_UINT8 , BASE_HEX , VALS ( polling_bit_vals ) , 0x20 ,
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
NULL , HFILL
2009-01-05 23:18:00 +00:00
}
} ,
{ & hf_rlc_lte_am_fi ,
{ " Framing Info " ,
" rlc-lte.am.fi " , FT_UINT8 , BASE_HEX , VALS ( framing_info_vals ) , 0x18 ,
" AM Framing Info " , HFILL
}
} ,
{ & hf_rlc_lte_am_fixed_e ,
{ " Extension " ,
" rlc-lte.am.fixed.e " , FT_UINT8 , BASE_HEX , VALS ( fixed_extension_vals ) , 0x04 ,
" Fixed Extension Bit " , HFILL
}
} ,
{ & hf_rlc_lte_am_fixed_sn ,
{ " Sequence Number " ,
2009-10-30 15:56:43 +00:00
" rlc-lte.am.fixed.sn " , FT_UINT16 , BASE_DEC , 0 , 0x03ff ,
2009-01-05 23:18:00 +00:00
" AM Fixed Sequence Number " , HFILL
}
} ,
{ & hf_rlc_lte_am_segment_lsf ,
{ " Last Segment Flag " ,
" rlc-lte.am.segment.lsf " , FT_UINT8 , BASE_HEX , VALS ( lsf_vals ) , 0x80 ,
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
NULL , HFILL
2009-01-05 23:18:00 +00:00
}
} ,
{ & hf_rlc_lte_am_segment_so ,
{ " Segment Offset " ,
2009-01-16 15:41:03 +00:00
" rlc-lte.am.segment.offset " , FT_UINT16 , BASE_DEC , 0 , 0x7fff ,
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
NULL , HFILL
2009-01-05 23:18:00 +00:00
}
} ,
{ & hf_rlc_lte_am_data ,
{ " AM Data " ,
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
" rlc-lte.am.data " , FT_BYTES , BASE_NONE , 0 , 0x0 ,
2009-01-05 23:18:00 +00:00
" Acknowledged Mode Data " , HFILL
}
} ,
{ & hf_rlc_lte_am_cpt ,
{ " Control PDU Type " ,
" rlc-lte.am.cpt " , FT_UINT8 , BASE_HEX , VALS ( control_pdu_type_vals ) , 0x70 ,
" AM Control PDU Type " , HFILL
}
} ,
{ & hf_rlc_lte_am_ack_sn ,
{ " ACK Sequence Number " ,
2009-01-16 10:53:58 +00:00
" rlc-lte.am.ack-sn " , FT_UINT16 , BASE_DEC , 0 , 0x0 ,
2010-06-10 15:28:41 +00:00
" Sequence Number we expect to receive next " , HFILL
2009-01-05 23:18:00 +00:00
}
} ,
{ & hf_rlc_lte_am_e1 ,
{ " Extension bit 1 " ,
" rlc-lte.am.e1 " , FT_UINT8 , BASE_HEX , VALS ( am_e1_vals ) , 0x0 ,
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
NULL , HFILL
2009-01-05 23:18:00 +00:00
}
} ,
{ & hf_rlc_lte_am_e2 ,
{ " Extension bit 2 " ,
" rlc-lte.am.e2 " , FT_UINT8 , BASE_HEX , VALS ( am_e2_vals ) , 0x0 ,
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
NULL , HFILL
2009-01-05 23:18:00 +00:00
}
} ,
2011-07-18 10:40:57 +00:00
{ & hf_rlc_lte_am_nacks ,
{ " Number of NACKs " ,
" rlc-lte.am.nacks " , FT_UINT16 , BASE_DEC , 0 , 0x0 ,
" Number of NACKs in this status PDU " , HFILL
}
} ,
2009-01-05 23:18:00 +00:00
{ & hf_rlc_lte_am_nack_sn ,
{ " NACK Sequence Number " ,
" rlc-lte.am.nack-sn " , FT_UINT16 , BASE_DEC , 0 , 0x0 ,
" Negative Acknowledgement Sequence Number " , HFILL
}
} ,
{ & hf_rlc_lte_am_so_start ,
{ " SO Start " ,
" rlc-lte.am.so-start " , FT_UINT16 , BASE_DEC , 0 , 0x0 ,
2010-10-20 12:08:22 +00:00
" Segment Offset Start byte index " , HFILL
2009-01-05 23:18:00 +00:00
}
} ,
{ & hf_rlc_lte_am_so_end ,
{ " SO End " ,
" rlc-lte.am.so-end " , FT_UINT16 , BASE_DEC , 0 , 0x0 ,
2010-10-20 12:08:22 +00:00
" Segment Offset End byte index " , HFILL
2009-01-05 23:18:00 +00:00
}
} ,
2009-01-21 15:44:22 +00:00
{ & hf_rlc_lte_predefined_pdu ,
{ " Predefined data " ,
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
" rlc-lte.predefined-data " , FT_BYTES , BASE_NONE , 0 , 0x0 ,
2009-01-21 15:44:22 +00:00
" Predefined test data " , HFILL
}
} ,
2009-04-14 14:38:20 +00:00
2013-11-22 17:18:11 +00:00
/* Sequence analysis fields */
2009-04-14 14:38:20 +00:00
{ & hf_rlc_lte_sequence_analysis ,
{ " Sequence Analysis " ,
" rlc-lte.sequence-analysis " , FT_STRING , BASE_NONE , 0 , 0x0 ,
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
NULL , HFILL
2009-04-14 14:38:20 +00:00
}
} ,
2010-02-28 20:43:04 +00:00
{ & hf_rlc_lte_sequence_analysis_ok ,
{ " OK " ,
" rlc-lte.sequence-analysis.ok " , FT_BOOLEAN , BASE_NONE , 0 , 0x0 ,
NULL , HFILL
}
} ,
2009-04-14 14:38:20 +00:00
{ & hf_rlc_lte_sequence_analysis_previous_frame ,
{ " Previous frame for channel " ,
" rlc-lte.sequence-analysis.previous-frame " , FT_FRAMENUM , BASE_NONE , 0 , 0x0 ,
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
NULL , HFILL
2009-04-14 14:38:20 +00:00
}
} ,
2012-01-23 02:36:46 +00:00
{ & hf_rlc_lte_sequence_analysis_next_frame ,
{ " Next frame for channel " ,
" rlc-lte.sequence-analysis.next-frame " , FT_FRAMENUM , BASE_NONE , 0 , 0x0 ,
NULL , HFILL
}
} ,
2009-04-14 14:38:20 +00:00
{ & hf_rlc_lte_sequence_analysis_expected_sn ,
{ " Expected SN " ,
" rlc-lte.sequence-analysis.expected-sn " , FT_UINT16 , BASE_DEC , 0 , 0x0 ,
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
NULL , HFILL
2009-04-14 14:38:20 +00:00
}
} ,
{ & hf_rlc_lte_sequence_analysis_framing_info_correct ,
{ " Frame info continued correctly " ,
2010-02-28 02:18:35 +00:00
" rlc-lte.sequence-analysis.framing-info-correct " , FT_BOOLEAN , BASE_NONE , 0 , 0x0 ,
NULL , HFILL
}
} ,
2010-03-01 22:52:34 +00:00
{ & hf_rlc_lte_sequence_analysis_mac_retx ,
{ " Frame retransmitted by MAC " ,
" rlc-lte.sequence-analysis.mac-retx " , FT_BOOLEAN , BASE_NONE , 0 , 0x0 ,
NULL , HFILL
}
} ,
2010-02-28 02:18:35 +00:00
{ & hf_rlc_lte_sequence_analysis_retx ,
{ " Retransmitted frame " ,
" rlc-lte.sequence-analysis.retx " , FT_BOOLEAN , BASE_NONE , 0 , 0x0 ,
NULL , HFILL
}
} ,
{ & hf_rlc_lte_sequence_analysis_skipped ,
{ " Skipped frames " ,
" rlc-lte.sequence-analysis.skipped-frames " , FT_BOOLEAN , BASE_NONE , 0 , 0x0 ,
NULL , HFILL
}
} ,
{ & hf_rlc_lte_sequence_analysis_repeated ,
{ " Repeated frame " ,
" rlc-lte.sequence-analysis.repeated-frame " , FT_BOOLEAN , BASE_NONE , 0 , 0x0 ,
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
NULL , HFILL
2009-04-14 14:38:20 +00:00
}
} ,
2010-03-02 18:40:34 +00:00
{ & hf_rlc_lte_sequence_analysis_repeated_nack ,
{ " Repeated NACK " ,
" rlc-lte.sequence-analysis.repeated-nack " , FT_UINT16 , BASE_DEC , 0 , 0x0 ,
NULL , HFILL
}
} ,
2010-10-15 21:07:45 +00:00
{ & hf_rlc_lte_sequence_analysis_repeated_nack_original_frame ,
{ " Frame with previous status PDU " ,
" rlc-lte.sequence-analysis.repeated-nack.original-frame " , FT_FRAMENUM , BASE_NONE , 0 , 0x0 ,
NULL , HFILL
}
} ,
2010-02-28 02:18:35 +00:00
2011-05-19 01:05:26 +00:00
{ & hf_rlc_lte_sequence_analysis_ack_out_of_range ,
{ " Out of range ACK " ,
" rlc-lte.sequence-analysis.ack-out-of-range " , FT_BOOLEAN , BASE_NONE , 0 , 0x0 ,
NULL , HFILL
}
} ,
{ & hf_rlc_lte_sequence_analysis_ack_out_of_range_opposite_frame ,
{ " Frame with most recent SN " ,
" rlc-lte.sequence-analysis.ack-out-of-range.last-sn-frame " , FT_FRAMENUM , BASE_NONE , 0 , 0x0 ,
NULL , HFILL
}
} ,
2013-11-22 17:18:11 +00:00
/* Reassembly fields */
2011-09-06 12:01:28 +00:00
{ & hf_rlc_lte_reassembly_source ,
{ " Reassembly Source " ,
" rlc-lte.reassembly-info " , FT_STRING , BASE_NONE , 0 , 0x0 ,
NULL , HFILL
}
} ,
{ & hf_rlc_lte_reassembly_source_number_of_segments ,
{ " Number of segments " ,
" rlc-lte.reassembly-info.number-of-segments " , FT_UINT16 , BASE_DEC , 0 , 0x0 ,
NULL , HFILL
}
} ,
{ & hf_rlc_lte_reassembly_source_total_length ,
{ " Total length " ,
" rlc-lte.reassembly-info.total-length " , FT_UINT16 , BASE_DEC , 0 , 0x0 ,
NULL , HFILL
}
} ,
{ & hf_rlc_lte_reassembly_source_segment ,
{ " Segment " ,
" rlc-lte.reassembly-info.segment " , FT_NONE , BASE_NONE , 0 , 0x0 ,
NULL , HFILL
}
} ,
{ & hf_rlc_lte_reassembly_source_segment_sn ,
{ " SN " ,
" rlc-lte.reassembly-info.segment.sn " , FT_UINT16 , BASE_DEC , 0 , 0x0 ,
NULL , HFILL
}
} ,
{ & hf_rlc_lte_reassembly_source_segment_framenum ,
{ " Frame " ,
" rlc-lte.reassembly-info.segment.frame " , FT_FRAMENUM , BASE_NONE , 0 , 0x0 ,
NULL , HFILL
}
} ,
{ & hf_rlc_lte_reassembly_source_segment_length ,
{ " Length " ,
" rlc-lte.reassembly-info.segment.length " , FT_UINT32 , BASE_DEC , 0 , 0x0 ,
NULL , HFILL
}
} ,
2010-02-01 11:00:08 +00:00
{ & hf_rlc_lte_header_only ,
{ " RLC PDU Header only " ,
" rlc-lte.header-only " , FT_UINT8 , BASE_DEC , VALS ( header_only_vals ) , 0x0 ,
NULL , HFILL
}
} ,
2009-01-05 23:18:00 +00:00
} ;
static gint * ett [ ] =
{
& ett_rlc_lte ,
2010-03-09 01:39:08 +00:00
& ett_rlc_lte_context ,
2009-01-05 23:18:00 +00:00
& ett_rlc_lte_um_header ,
& ett_rlc_lte_am_header ,
& ett_rlc_lte_extension_part ,
2011-09-06 12:01:28 +00:00
& ett_rlc_lte_sequence_analysis ,
& ett_rlc_lte_reassembly_source ,
& ett_rlc_lte_reassembly_source_segment
2009-01-05 23:18:00 +00:00
} ;
2013-09-05 01:05:16 +00:00
static ei_register_info ei [ ] = {
2013-11-22 17:18:11 +00:00
{ & ei_rlc_lte_sequence_analysis_last_segment_not_continued , { " rlc-lte.sequence-analysis.last-segment-not-continued " , PI_SEQUENCE , PI_WARN , " Last segment of previous PDU was not continued for UE " , EXPFILL } } ,
{ & ei_rlc_lte_sequence_analysis_last_segment_complete , { " rlc-lte.sequence-analysis.last-segment-complete " , PI_SEQUENCE , PI_WARN , " Last segment of previous PDU was complete, but new segment was not started on UE " , EXPFILL } } ,
2013-09-05 01:05:16 +00:00
{ & ei_rlc_lte_sequence_analysis_mac_retx , { " rlc-lte.sequence-analysis.mac-retx.expert " , PI_SEQUENCE , PI_WARN , " AM Frame retransmitted due to MAC retx! " , EXPFILL } } ,
{ & ei_rlc_lte_sequence_analysis_retx , { " rlc-lte.sequence-analysis.retx.expert " , PI_SEQUENCE , PI_WARN , " AM Frame retransmitted most likely in response to NACK " , EXPFILL } } ,
{ & ei_rlc_lte_sequence_analysis_repeated , { " rlc-lte.sequence-analysis.repeated-frame.expert " , PI_SEQUENCE , PI_WARN , " AM SN Repeated - probably because didn't receive Status PDU? " , EXPFILL } } ,
2013-11-22 17:18:11 +00:00
{ & ei_rlc_lte_am_sn_missing , { " rlc-lte.sequence-analysis.am-sn.missing " , PI_SEQUENCE , PI_WARN , " AM SNs missing " , EXPFILL } } ,
2013-09-05 01:05:16 +00:00
{ & ei_rlc_lte_sequence_analysis_ack_out_of_range_opposite_frame , { " rlc-lte.sequence-analysis.ack-out-of-range.last-sn-frame.expert " , PI_SEQUENCE , PI_ERROR , " AM ACK for SN - but last received SN in other direction is X " , EXPFILL } } ,
2013-11-22 17:18:11 +00:00
{ & ei_rlc_lte_um_sn_missing , { " rlc-lte.sequence-analysis.um-sn.missing " , PI_SEQUENCE , PI_WARN , " UM SNs missing " , EXPFILL } } ,
{ & ei_rlc_lte_um_sn_repeated , { " rlc-lte.sequence-analysis.um-sn.repeated " , PI_SEQUENCE , PI_WARN , " UM SN repeated " , EXPFILL } } ,
{ & ei_rlc_lte_wrong_sequence_number , { " rlc-lte.wrong-sequence-number " , PI_SEQUENCE , PI_WARN , " Wrong Sequence Number " , EXPFILL } } ,
2013-09-05 01:05:16 +00:00
{ & ei_rlc_lte_sequence_analysis_repeated_nack , { " rlc-lte.sequence-analysis.repeated-nack.expert " , PI_SEQUENCE , PI_ERROR , " Same SN NACKd on successive Status PDUs " , EXPFILL } } ,
2013-11-22 17:18:11 +00:00
{ & ei_rlc_lte_reserved_bits_not_zero , { " rlc-lte.reserved-bits-not-zero " , PI_MALFORMED , PI_ERROR , " Reserved bits not zero " , EXPFILL } } ,
2013-09-05 01:05:16 +00:00
{ & ei_rlc_lte_um_sn , { " rlc-lte.um.sn.invalid " , PI_MALFORMED , PI_ERROR , " Invalid sequence number length " , EXPFILL } } ,
{ & ei_rlc_lte_header_only , { " rlc-lte.header-only.expert " , PI_SEQUENCE , PI_NOTE , " RLC PDU SDUs have been omitted " , EXPFILL } } ,
{ & ei_rlc_lte_am_cpt , { " rlc-lte.am.cpt.invalid " , PI_MALFORMED , PI_ERROR , " RLC Control frame type not handled " , EXPFILL } } ,
2013-11-22 17:18:11 +00:00
{ & ei_rlc_lte_am_nack_sn_ack_same , { " rlc-lte.am.nack-sn.ack-same " , PI_MALFORMED , PI_ERROR , " Status PDU shouldn't ACK and NACK the same sequence number " , EXPFILL } } ,
{ & ei_rlc_lte_am_nack_sn_ahead_ack , { " rlc-lte.am.nack-sn.ahead-ack " , PI_MALFORMED , PI_ERROR , " NACK must not be ahead of ACK in status PDU " , EXPFILL } } ,
2013-09-05 01:05:16 +00:00
{ & ei_rlc_lte_am_nack_sn_partial , { " rlc-lte.am.nack-sn.partial " , PI_SEQUENCE , PI_WARN , " Status PDU reports NACK (partial) " , EXPFILL } } ,
{ & ei_rlc_lte_am_nack_sn , { " rlc-lte.am.nack-sn.expert " , PI_SEQUENCE , PI_WARN , " Status PDU reports NACK " , EXPFILL } } ,
2013-11-22 17:18:11 +00:00
{ & ei_rlc_lte_bytes_after_status_pdu_complete , { " rlc-lte.bytes-after-status-pdu-complete " , PI_MALFORMED , PI_ERROR , " bytes remaining after Status PDU complete " , EXPFILL } } ,
{ & ei_rlc_lte_am_data_no_data_beyond_extensions , { " rlc-lte.am-data.no-data-beyond-extensions " , PI_MALFORMED , PI_ERROR , " AM data PDU doesn't contain any data beyond extensions " , EXPFILL } } ,
{ & ei_rlc_lte_am_data_no_data , { " rlc-lte.am-data.no-data " , PI_MALFORMED , PI_ERROR , " AM data PDU doesn't contain any data " , EXPFILL } } ,
2013-09-05 01:05:16 +00:00
{ & ei_rlc_lte_context_mode , { " rlc-lte.mode.invalid " , PI_MALFORMED , PI_ERROR , " Unrecognised RLC Mode set " , EXPFILL } } ,
2014-09-06 12:44:23 +00:00
{ & ei_rlc_lte_no_per_frame_info , { " rlc-lte.no_per_frame_info " , PI_UNDECODED , PI_ERROR , " Can't dissect LTE RLC frame because no per-frame info was attached! " , EXPFILL } } ,
2013-09-05 01:05:16 +00:00
} ;
2012-11-29 20:15:37 +00:00
static const enum_val_t sequence_analysis_vals [ ] = {
2010-02-28 02:18:35 +00:00
{ " no-analysis " , " No-Analysis " , FALSE } ,
{ " mac-only " , " Only-MAC-frames " , SEQUENCE_ANALYSIS_MAC_ONLY } ,
{ " rlc-only " , " Only-RLC-frames " , SEQUENCE_ANALYSIS_RLC_ONLY } ,
{ NULL , NULL , - 1 }
} ;
2010-10-10 20:39:00 +00:00
2009-04-14 14:38:20 +00:00
module_t * rlc_lte_module ;
2013-09-05 01:05:16 +00:00
expert_module_t * expert_rlc_lte ;
2009-04-14 14:38:20 +00:00
2009-01-05 23:18:00 +00:00
/* Register protocol. */
proto_rlc_lte = proto_register_protocol ( " RLC-LTE " , " RLC-LTE " , " rlc-lte " ) ;
proto_register_field_array ( proto_rlc_lte , hf , array_length ( hf ) ) ;
proto_register_subtree_array ( ett , array_length ( ett ) ) ;
2013-09-05 01:05:16 +00:00
expert_rlc_lte = expert_register_protocol ( proto_rlc_lte ) ;
expert_register_field_array ( expert_rlc_lte , ei , array_length ( ei ) ) ;
2009-01-05 23:18:00 +00:00
/* Allow other dissectors to find this one by name. */
register_dissector ( " rlc-lte " , dissect_rlc_lte , proto_rlc_lte ) ;
2009-04-14 14:38:20 +00:00
2010-01-04 14:07:24 +00:00
/* Register the tap name */
rlc_lte_tap = register_tap ( " rlc-lte " ) ;
2009-04-14 14:38:20 +00:00
/* Preferences */
rlc_lte_module = prefs_register_protocol ( proto_rlc_lte , NULL ) ;
2010-02-28 02:18:35 +00:00
prefs_register_enum_preference ( rlc_lte_module , " do_sequence_analysis_am " ,
" Do sequence analysis for AM channels " ,
2010-02-28 18:42:41 +00:00
" Attempt to keep track of PDUs for AM channels, and point out problems " ,
2010-02-28 02:18:35 +00:00
& global_rlc_lte_am_sequence_analysis , sequence_analysis_vals , FALSE ) ;
prefs_register_enum_preference ( rlc_lte_module , " do_sequence_analysis " ,
2009-04-29 21:50:02 +00:00
" Do sequence analysis for UM channels " ,
" Attempt to keep track of PDUs for UM channels, and point out problems " ,
2010-02-28 02:18:35 +00:00
& global_rlc_lte_um_sequence_analysis , sequence_analysis_vals , FALSE ) ;
2009-04-14 14:38:20 +00:00
2009-11-16 15:35:56 +00:00
prefs_register_bool_preference ( rlc_lte_module , " call_pdcp_for_srb " ,
" Call PDCP dissector for SRB PDUs " ,
" Call PDCP dissector for signalling PDUs. Note that without reassembly, it can "
2012-12-11 23:20:22 +00:00
" only be called for complete PDUs (i.e. not segmented over RLC) " ,
2010-07-28 16:58:13 +00:00
& global_rlc_lte_call_pdcp_for_srb ) ;
prefs_register_enum_preference ( rlc_lte_module , " call_pdcp_for_drb " ,
" Call PDCP dissector for DRB PDUs " ,
" Call PDCP dissector for user-plane PDUs. Note that without reassembly, it can "
2012-02-03 10:42:01 +00:00
" only be called for complete PDUs (i.e. not segmented over RLC) " ,
2010-07-28 16:58:13 +00:00
& global_rlc_lte_call_pdcp_for_drb , pdcp_drb_col_vals , FALSE ) ;
2009-11-16 15:35:56 +00:00
prefs_register_bool_preference ( rlc_lte_module , " call_rrc_for_ccch " ,
" Call RRC dissector for CCCH PDUs " ,
" Call RRC dissector for CCCH PDUs " ,
2012-10-01 19:51:07 +00:00
& global_rlc_lte_call_rrc_for_ccch ) ;
prefs_register_bool_preference ( rlc_lte_module , " call_rrc_for_mcch " ,
" Call RRC dissector for MCCH PDUs " ,
2012-12-11 23:20:22 +00:00
" Call RRC dissector for MCCH PDUs Note that without reassembly, it can "
" only be called for complete PDUs (i.e. not segmented over RLC) " ,
2012-10-01 19:51:07 +00:00
& global_rlc_lte_call_rrc_for_mcch ) ;
2009-11-16 15:35:56 +00:00
2012-12-11 23:20:22 +00:00
prefs_register_bool_preference ( rlc_lte_module , " call_ip_for_mtch " ,
" Call IP dissector for MTCH PDUs " ,
" Call ip dissector for MTCH PDUs Note that without reassembly, it can "
" only be called for complete PDUs (i.e. not segmented over RLC) " ,
& global_rlc_lte_call_ip_for_mtch ) ;
2009-12-07 10:23:35 +00:00
prefs_register_bool_preference ( rlc_lte_module , " heuristic_rlc_lte_over_udp " ,
" Try Heuristic LTE-RLC over UDP framing " ,
" When enabled, use heuristic dissector to find RLC-LTE frames sent with "
" UDP framing " ,
& global_rlc_lte_heur ) ;
2009-11-16 15:35:56 +00:00
2010-02-01 11:00:08 +00:00
prefs_register_bool_preference ( rlc_lte_module , " header_only_mode " ,
" May see RLC headers only " ,
" When enabled, if data is not present, don't report as an error, but instead "
2010-12-06 01:34:58 +00:00
" add expert info to indicate that headers were omitted " ,
2010-02-01 11:00:08 +00:00
& global_rlc_lte_headers_expected ) ;
2011-09-06 12:01:28 +00:00
prefs_register_bool_preference ( rlc_lte_module , " reassembly " ,
" Attempt SDU reassembly " ,
" When enabled, attempts to re-assemble upper-layer SDUs that are split over "
" more than one RLC PDU. Note: does not currently support out-of-order or "
" re-segmentation. N.B. sequence analysis must also be turned on in order "
" for reassembly to work " ,
& global_rlc_lte_reassembly ) ;
2014-12-07 19:54:05 +00:00
ue_parameters_tree = wmem_tree_new_autoreset ( wmem_epan_scope ( ) , wmem_file_scope ( ) ) ;
2011-09-06 12:01:28 +00:00
2009-04-14 14:38:20 +00:00
register_init_routine ( & rlc_lte_init_protocol ) ;
2009-01-05 23:18:00 +00:00
}
2014-08-14 18:55:06 +00:00
void proto_reg_handoff_rlc_lte ( void )
2009-12-07 10:23:35 +00:00
{
2010-10-10 20:39:00 +00:00
/* Add as a heuristic UDP dissector */
heur_dissector_add ( " udp " , dissect_rlc_lte_heur , proto_rlc_lte ) ;
2012-10-06 14:59:51 +00:00
pdcp_lte_handle = find_dissector ( " pdcp-lte " ) ;
2012-12-11 23:20:22 +00:00
ip_handle = find_dissector ( " ip " ) ;
2009-12-07 10:23:35 +00:00
}
2014-08-14 18:55:06 +00:00
/*
* Editor modelines - http : //www.wireshark.org/tools/modelines.html
*
* Local variables :
* c - basic - offset : 4
* tab - width : 8
* indent - tabs - mode : nil
* End :
*
* vi : set shiftwidth = 4 tabstop = 8 expandtab :
* : indentSize = 4 : tabSize = 8 : noTabs = true :
*/