code: def _defrag_logic(plist, complete=False):
      
      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)
docs: Internal function used to defragment a list of packets.
      It contains the logic behind the defrag() and defragment() functions