diff options
author | Lutz Kresge <LutzKr@protonmail.ch> | 2018-03-01 16:25:40 +0200 |
---|---|---|
committer | Anders Broman <a.broman58@gmail.com> | 2018-03-02 06:24:17 +0000 |
commit | 68e16ab05b7d6e726bd6adb7fab48875f28a6631 (patch) | |
tree | a00a3749cbc165552a65316c455ad71bf79d4fa2 | |
parent | 1fa2781b7a2e97a77b8ef7ddb3b3c48a93f2516d (diff) |
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>
-rw-r--r-- | epan/dissectors/packet-umts_rlc.c | 39 |
1 files changed, 27 insertions, 12 deletions
diff --git a/epan/dissectors/packet-umts_rlc.c b/epan/dissectors/packet-umts_rlc.c index 250d958efe..bd39bf0faf 100644 --- a/epan/dissectors/packet-umts_rlc.c +++ b/epan/dissectors/packet-umts_rlc.c @@ -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 |