This is our old Q&A Site. Please post any new questions and answers at ask.wireshark.org.

Can anyone identify a way to filter Duplicate RTP packets in WS? We are sniffing RTP packets on a workstation which are coming from a Cisco Cube and compiling them into an ASF file for Call Recording Evaluation purposes. The duplciate packets are causing problems for us and our network team is asking for evidence.

It took a lot of time to identify it in one of the WS captures but we showed the duplicate packet to them. The network and telephony teams now want numerous examples and we cannot find an easy way to identify duplicate RTP packets in the WS captures, only TCP. Ideas would be greatly appreciated.

Thanks.

This question is marked "community wiki".

asked 22 Dec '14, 12:43

swaisboy's gravatar image

swaisboy
1111
accept rate: 0%


Duplicate IP ID field values in the IP header would be one clear indicator of a duplicate packet. The system generating the initial IP packet typically increments that field with each successive packet, and no router should every modify it, so if you see two packets with the same IP ID field and the same content, that's a really strong indicator of a duplicate.

permanent link

answered 22 Dec '14, 15:39

Quadratic's gravatar image

Quadratic
1.9k6928
accept rate: 13%

edited 22 Dec '14, 15:40

Thanks Quadratic. We are able to identify the duplicate packets as you indicated above using similar methods, but we need help trying to Filter for all Duplicate RTP packets. There is a ton of data to parse through. We see there is a way to do that with TCP, but have not found a way to Filter specificlaly duplciate RTP packets. Thanks.

(22 Dec '14, 16:10) swaisboy

One method is simply to use editcap to filter them out. The '-d' option of editcap should do it if the duplicates are close together and truly identical (uses MD5 hash comparison to detect them):

https://www.wireshark.org/docs/man-pages/editcap.html

In that example: editcap -d capture.pcap capture_without_duplicates.pcap

(22 Dec '14, 19:28) Quadratic

You could use a Lua script to do it.

For example the script below will create a fake "rtpdup" protocol for RTP packets, and set a new field called "rtpdup.duplicate" to true if it's a duplicate. That way you can filter on that field's value in Wireshark.

So just copy paste the below code into a new file with a .lua extension (e.g., "rtpdup.lua"), and put it in your Wireshark personal plugins directory; and then start Wireshark, load up your capture file, and use the display filter "rtpdup.duplicate == true", and voilĂ  you'll only see duplicate RTP packets. This script uses the combination of IP ID field, RTP sequence number, and RTP SSRC field... all three must match for another packet to be considered a duplicate. (or you can reduce it by changing the Lua code... it's fairly straightforward)


-- our new Proto object
local rtpdup = Proto("rtpdup","RTP Duplicates Protocol")

-- new fields for our "rtpdup" protocol
-- the purpose for these is so they can be filtered upon
local pf_is_dup    = ProtoField.bool("rtpdup.duplicate", "Duplicated")
local pf_dup_frame = ProtoField.framenum("rtpdup.frame", "DupFrame", base.NONE)

-- register the ProtoFields above
rtpdup.fields = { pf_is_dup, pf_dup_frame }

-- some existing fields we need to extract from RTP packets, to determine duplicates
-- all 3 of these must be the same for us to consider two packets duplicates
local f_ip_id    = Field.new("ip.id")
local f_rtp_seq  = Field.new("rtp.seq")
local f_rtp_ssrc = Field.new("rtp.ssrc")

-- the table we use to track seen packet #s and seen field info
-- we'll use this as both an array and map table
-- the array portion is indexed by packet number
-- the map portion is keyed by "ip.id:rtp.seq:rtp.ssrc"
-- the resultant for both is the same instance of a subtable with the
-- packet numbers of the dups in an array list
local packets = {}

local function generateKey(...)
    local t = { ... }
    return table.concat(t, ':')
end

-- adds the packet's number to both the array and map
-- which is done when we see a particular set of fields for the first time
local function addPacketList(pnum, key)
    local list = { pnum }
    packets[key] = list
    packets[pnum] = list
end

-- adds the packet to the array part, using an existing list of dups
-- also adds the packet's number to the list of dups
local function addPacket(pnum, list)
    -- add this packet's number to the array portion of the big table
    packets[pnum] = list
    -- add this packet's number to the list of dups
    list[#list + 1] = pnum
end

-- whenever a new capture file is opened, we want to reset our table
-- so we hook into the init() routine to do that
function rtpdup.init()
    packets = {}
end

-- some forward "declarations" of helper functions we use in the dissector
local createProtoTree

-- our dissector function
function rtpdup.dissector(tvb, pinfo, tree)
    -- first, check if this is an rtp packet, by seeing if it has a rtp.seq
    local rtp_seq = select(1, f_rtp_seq())

    if not rtp_seq then
        -- not an RTP packet
        return
    end

    local pnum = pinfo.number

    -- see if we've already processed this packet number
    local list = packets[pnum]

    if not list then
        -- haven't processed this packet
        -- see if the fields match another packet we've seen before
        local ip_id = select(1, f_ip_id())
        local rtp_ssrc = select(1, f_rtp_ssrc())
        local key = generateKey(tostring(ip_id), tostring(rtp_seq), tostring(rtp_ssrc))

        list = packets[key]

        if not list then
            -- haven't seen these fields before, so add it as a non-dup (so far)
            addPacketList(pnum, key)
            createProtoTree(pnum, tree)
        else
            -- we haven't processed this packet, but we have seen the same fields
            -- so it's a duplicate.  Add its number to the array and entry...
            addPacket(pnum, list)
            -- and now create its tree
            createProtoTree(pnum, tree, list)
        end
    else
        -- we found the packet number already in the table, which means
        -- we've processed it before
        createProtoTree(pnum, tree, list)
    end
end

createProtoTree = function (pnum, root, list)
    -- add our "protocol"
    local tree = root:add(rtpdup)

    if not list or #list < 2 then
        -- it's not a duplicate
        tree:add(pf_is_dup, false):set_generated()
    else
        tree:add(pf_is_dup, true):set_generated()
        -- now add the other packet numbers as reference tree item fields
        for _, num in ipairs(list) do
            if num ~= pnum then
                tree:add(pf_dup_frame, num):set_generated()
            end
        end
    end
end

-- then we register rtpdup as a postdissector
register_postdissector(rtpdup)
permanent link

answered 23 Dec '14, 00:39

Hadriel's gravatar image

Hadriel
2.7k2939
accept rate: 18%

Your answer
toggle preview

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Markdown Basics

  • *italic* or _italic_
  • **bold** or __bold__
  • link:[text](http://url.com/ "title")
  • image?![alt text](/path/img.jpg "title")
  • numbered list: 1. Foo 2. Bar
  • to add a line break simply add two spaces to where you would like the new line to be.
  • basic HTML tags are also supported

Question tags:

×349
×238
×205
×41

question asked: 22 Dec '14, 12:43

question was seen: 7,264 times

last updated: 23 Dec '14, 00:39

p​o​w​e​r​e​d by O​S​Q​A