Internal function used to defragment a list of packets.
    It contains the logic behind the defrag() and defragment() functions

def _defrag_logic(plist, complete=False):
    """Internal function used to defragment a list of packets.
    It contains the logic behind the defrag() and defragment() functions
    """
    frags = defaultdict(lambda: [])
    final = []
    pos = 0
    for p in plist:
        p._defrag_pos = pos
        pos += 1
        if IP in p:
            ip = p[IP]
            if ip.frag != 0 or ip.flags.MF:
                uniq = (ip.id, ip.src, ip.dst, ip.proto)
                frags[uniq].append(p)
                continue
        final.append(p)

    defrag = []
    missfrag = []
    for lst in six.itervalues(frags):
        lst.sort(key=lambda x: x.frag)
        _defrag_list(lst, defrag, missfrag)
    defrag2 = []
    for p in defrag:
        q = p.__class__(raw(p))
        q._defrag_pos = p._defrag_pos
        q.time = p.time
        defrag2.append(q)
    if complete:
        final.extend(defrag2)
        final.extend(missfrag)
        final.sort(key=lambda x: x._defrag_pos)
        if hasattr(plist, "listname"):
            name = "Defragmented %s" % plist.listname
        else:
            name = "Defragmented"
        return PacketList(final, name=name)
    else:
        return PacketList(final), PacketList(defrag2), PacketList(missfrag)