*/
/* TODO:
- - AM re-assembly?
+ - UM & AM re-assembly?
*/
/********************************/
static int hf_rlc_lte_sequence_analysis_skipped = -1;
static int hf_rlc_lte_sequence_analysis_repeated_nack = -1;
+static int hf_rlc_lte_sequence_analysis_repeated_nack_original_frame = -1;
/* Subtrees. */
static int ett_rlc_lte = -1;
/**********************************************************************************/
/* These are for keeping track of UM/AM extension headers, and the lengths found */
/* in them */
-guint8 s_number_of_extensions = 0;
+static guint8 s_number_of_extensions = 0;
#define MAX_RLC_SDUS 64
-guint16 s_lengths[MAX_RLC_SDUS];
+static guint16 s_lengths[MAX_RLC_SDUS];
/*********************************************************************/
{
guint16 noOfNACKs;
guint16 NACKs[MAX_NACKs];
+ guint32 frameNum;
} rlc_channel_repeated_nack_status;
static GHashTable *rlc_lte_repeated_nack_channel_hash = NULL;
typedef struct {
guint16 noOfNACKsRepeated;
guint16 repeatedNACKs[MAX_NACKs];
+ guint32 previousFrameNum;
} rlc_channel_repeated_nack_report_in_frame;
static GHashTable *rlc_lte_frame_repeated_nack_report_hash = NULL;
/********************************************************/
/* Forward declarations & functions */
-void proto_reg_handoff_rlc_lte(void);
-void dissect_rlc_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+static void dissect_rlc_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
/* Write the given formatted text to:
{
#define MAX_INFO_BUFFER 256
static char info_buffer[MAX_INFO_BUFFER];
-
+
va_list ap;
va_start(ap, format);
p_add_proto_data(pinfo->fd, proto_pdcp_lte, p_pdcp_lte_info);
}
+ 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;
+
+ /* Set plane and sequnce 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;
}
else {
p_pdcp_lte_info->plane = USER_PLANE;
- }
- /* Set sequence number field length */
- 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;
- default:
- DISSECTOR_ASSERT(FALSE);
- break;
+ 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;
+ default:
+ DISSECTOR_ASSERT(FALSE);
+ break;
+ }
}
p_pdcp_lte_info->rohc_compression = FALSE;
tvb, 0, 0, TRUE);
PROTO_ITEM_SET_GENERATED(ti);
expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
- "AM SN Repeated for %s for UE %u - probably because didn't receive Status PDU?",
+ "AM SN %u Repeated for %s for UE %u - probably because didn't receive Status PDU?",
+ p->firstSN,
val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
p_rlc_lte_info->ueid);
proto_item_append_text(seqnum_ti, "- SN %u Repeated",
- p->sequenceExpected);
+ p->firstSN);
break;
case SN_Missing:
val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
p_rlc_lte_info->ueid);
proto_item_append_text(seqnum_ti, "- SN %u Repeated",
- p->sequenceExpected);
+ p->firstSN);
break;
case SN_MAC_Retx:
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;
/* Set report for this frame */
p_report_in_frame->sequenceExpectedCorrect = FALSE;
- p_report_in_frame->sequenceExpected = sequenceNumber;
+ p_report_in_frame->sequenceExpected = expectedSequenceNumber;
+ p_report_in_frame->firstSN = sequenceNumber;
p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
p_report_in_frame->previousSegmentIncomplete = p_channel_status->previousSegmentIncomplete;
p_rlc_lte_info->ueid);
}
+ /* 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);
+
/* Append count to sequence analysis root */
proto_item_append_text(seqnum_ti, " - %u SNs repeated from previous Status PDU",
- p->noOfNACKsRepeated);
+ p->noOfNACKsRepeated);
}
}
p_report_in_frame->noOfNACKsRepeated = noOfNACKsRepeated;
+ p_report_in_frame->previousFrameNum = p_channel_status->frameNum;
+
/* Associate with this frame number */
g_hash_table_insert(rlc_lte_frame_repeated_nack_report_hash, &pinfo->fd->num, p_report_in_frame);
addChannelRepeatedNACKInfo(p_report_in_frame, p_rlc_lte_info,
pinfo, tree, tvb);
}
+
+ /* Save frame number for next comparison */
+ p_channel_status->frameNum = pinfo->fd->num;
}
return FALSE;
}
- /* If redissecting, use previous info struct (if available) */
- p_rlc_lte_info = p_get_proto_data(pinfo->fd, proto_rlc_lte);
- if (p_rlc_lte_info == NULL) {
- /* Allocate new info struct for this frame */
- p_rlc_lte_info = se_alloc0(sizeof(struct rlc_lte_info));
- infoAlreadySet = FALSE;
- }
- else {
- infoAlreadySet = TRUE;
- }
-
/* Do this again on re-dissection to re-discover offset of actual PDU */
-
+
/* Needs to be at least as long as:
- the signature string
- fixed header bytes
}
offset += (gint)strlen(RLC_LTE_START_STRING);
+
+ /* If redissecting, use previous info struct (if available) */
+ p_rlc_lte_info = p_get_proto_data(pinfo->fd, proto_rlc_lte);
+ if (p_rlc_lte_info == NULL) {
+ /* Allocate new info struct for this frame */
+ p_rlc_lte_info = se_alloc0(sizeof(struct rlc_lte_info));
+ infoAlreadySet = FALSE;
+ }
+ else {
+ infoAlreadySet = TRUE;
+ }
+
+
/* Read fixed fields */
p_rlc_lte_info->rlcMode = tvb_get_guint8(tvb, offset++);
/* Main dissection function. */
/*****************************/
-void dissect_rlc_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+static void dissect_rlc_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
proto_tree *rlc_lte_tree;
proto_tree *context_tree;
tap_info->UMSequenceNumberLength = p_rlc_lte_info->UMSequenceNumberLength;
tap_info->loggedInMACFrame = (p_get_proto_data(pinfo->fd, proto_mac_lte) != NULL);
+ tap_info->time = pinfo->fd->abs_ts;
+
/* Reset this count */
s_number_of_extensions = 0;
{ &hf_rlc_lte_am_so_start,
{ "SO Start",
"rlc-lte.am.so-start", FT_UINT16, BASE_DEC, 0, 0x0,
- NULL, HFILL
+ "Segment Offset Start byte index", HFILL
}
},
{ &hf_rlc_lte_am_so_end,
{ "SO End",
"rlc-lte.am.so-end", FT_UINT16, BASE_DEC, 0, 0x0,
- NULL, HFILL
+ "Segment Offset End byte index", HFILL
}
},
NULL, HFILL
}
},
+ { &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
+ }
+ },
{ &hf_rlc_lte_header_only,
{ "RLC PDU Header only",
{"rlc-only", "Only-RLC-frames", SEQUENCE_ANALYSIS_RLC_ONLY},
{NULL, NULL, -1}
};
-
+
module_t *rlc_lte_module;
/* Register protocol. */
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 "
- "add expert info to indicate that headers were ommitted",
+ "add expert info to indicate that headers were omitted",
&global_rlc_lte_headers_expected);
register_init_routine(&rlc_lte_init_protocol);
void
proto_reg_handoff_rlc_lte(void)
{
- static dissector_handle_t rlc_lte_handle;
- if (!rlc_lte_handle) {
- rlc_lte_handle = find_dissector("rlc-lte");
+ dissector_handle_t rlc_lte_handle;
- /* Add as a heuristic UDP dissector */
- heur_dissector_add("udp", dissect_rlc_lte_heur, proto_rlc_lte);
- }
+ rlc_lte_handle = find_dissector("rlc-lte");
+ /* Add as a heuristic UDP dissector */
+ heur_dissector_add("udp", dissect_rlc_lte_heur, proto_rlc_lte);
}