RLC: Fix duplication check after sqn reset

When rlc sequence number wrapped around, duplicate frames wouldn't be
marked because they were compared to the sqn from the first round.
Change-Id: Ia57aac9b86b4cc84dd8ec411fe0a94972acb9526
Reviewed-on: https://code.wireshark.org/review/26208
Petri-Dish: Anders Broman <a.broman58@gmail.com>
Tested-by: Petri Dish Buildbot
Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
Lutz Kresge 2018-03-01 16:25:40 +02:00 committed by Anders Broman
parent 1fa2781b7a
commit 68e16ab05b
1 changed files with 27 additions and 12 deletions

View File

@ -1237,6 +1237,8 @@ rlc_is_duplicate(enum rlc_mode mode, packet_info *pinfo, guint16 seq,
struct rlc_seqlist lookup, *list;
struct rlc_seq seq_item, *seq_new;
guint16 snmod;
nstime_t delta;
gboolean is_duplicate,is_unseen;
if (rlc_channel_assign(&lookup.ch, mode, pinfo, atm) == -1)
return FALSE;
@ -1262,26 +1264,39 @@ rlc_is_duplicate(enum rlc_mode mode, packet_info *pinfo, guint16 seq,
}
}
is_duplicate = FALSE;
is_unseen = TRUE;
element = g_list_find_custom(list->list, &seq_item, rlc_cmp_seq);
if (element) {
while(element) {
/* Check if this is a different frame (by comparing frame numbers) which arrived less than */
/* RLC_RETRANSMISSION_TIMEOUT seconds ago */
seq_new = (struct rlc_seq *)element->data;
if (seq_new->frame_num != seq_item.frame_num) {
nstime_t delta;
if (seq_new->frame_num < seq_item.frame_num) {
nstime_delta(&delta, &pinfo->abs_ts, &seq_new->arrival);
if (delta.secs < RLC_RETRANSMISSION_TIMEOUT) {
if (original)
/* This is a duplicate. */
if (original) {
/* Save the frame number where our sequence number was previously seen */
*original = seq_new->frame_num;
return TRUE;
}
is_duplicate = TRUE;
}
return FALSE;
}
return FALSE; /* we revisit the seq that was already seen */
else if (seq_new->frame_num == seq_item.frame_num) {
/* Check if our frame is already in the list and this is a secondary check.*/
/* in this case raise a flag so the frame isn't entered more than once to the list */
is_unseen = FALSE;
}
element = g_list_find_custom(element->next, &seq_item, rlc_cmp_seq);
}
seq_new = (struct rlc_seq *)wmem_alloc0(wmem_file_scope(), sizeof(struct rlc_seq));
*seq_new = seq_item;
seq_new->arrival = pinfo->abs_ts;
list->list = g_list_append(list->list, seq_new); /* insert in order of arrival */
return FALSE;
if(is_unseen) {
/* Add to list for the first time this frame is checked */
seq_new = (struct rlc_seq *)wmem_alloc0(wmem_file_scope(), sizeof(struct rlc_seq));
*seq_new = seq_item;
seq_new->arrival = pinfo->abs_ts;
list->list = g_list_append(list->list, seq_new); /* insert in order of arrival */
}
return is_duplicate;
}
static void