Performs fragmentation of an IPv6 packet. Provided packet ('pkt') must
    already contain an IPv6ExtHdrFragment() class. 'fragSize' argument is the
    expected maximum size of fragments (MTU). The list of packets is returned.

    If packet does not contain an IPv6ExtHdrFragment class, it is returned in
    result list.

def fragment6(pkt, fragSize):
    """
    Performs fragmentation of an IPv6 packet. Provided packet ('pkt') must
    already contain an IPv6ExtHdrFragment() class. 'fragSize' argument is the
    expected maximum size of fragments (MTU). The list of packets is returned.

    If packet does not contain an IPv6ExtHdrFragment class, it is returned in
    result list.
    """

    pkt = pkt.copy()

    if IPv6ExtHdrFragment not in pkt:
        # TODO : automatically add a fragment before upper Layer
        #        at the moment, we do nothing and return initial packet
        #        as single element of a list
        return [pkt]

    # If the payload is bigger than 65535, a Jumbo payload must be used, as
    # an IPv6 packet can't be bigger than 65535 bytes.
    if len(raw(pkt[IPv6ExtHdrFragment])) > 65535:
        warning("An IPv6 packet can'be bigger than 65535, please use a Jumbo payload.")  # noqa: E501
        return []

    s = raw(pkt)  # for instantiation to get upper layer checksum right

    if len(s) <= fragSize:
        return [pkt]

    # Fragmentable part : fake IPv6 for Fragmentable part length computation
    fragPart = pkt[IPv6ExtHdrFragment].payload
    tmp = raw(IPv6(src="::1", dst="::1") / fragPart)
    fragPartLen = len(tmp) - 40  # basic IPv6 header length
    fragPartStr = s[-fragPartLen:]

    # Grab Next Header for use in Fragment Header
    nh = pkt[IPv6ExtHdrFragment].nh

    # Keep fragment header
    fragHeader = pkt[IPv6ExtHdrFragment]
    del fragHeader.payload  # detach payload

    # Unfragmentable Part
    unfragPartLen = len(s) - fragPartLen - 8
    unfragPart = pkt
    del pkt[IPv6ExtHdrFragment].underlayer.payload  # detach payload

    # Cut the fragmentable part to fit fragSize. Inner fragments have
    # a length that is an integer multiple of 8 octets. last Frag MTU
    # can be anything below MTU
    lastFragSize = fragSize - unfragPartLen - 8
    innerFragSize = lastFragSize - (lastFragSize % 8)

    if lastFragSize <= 0 or innerFragSize == 0:
        warning("Provided fragment size value is too low. " +
                "Should be more than %d" % (unfragPartLen + 8))
        return [unfragPart / fragHeader / fragPart]

    remain = fragPartStr
    res = []
    fragOffset = 0     # offset, incremeted during creation
    fragId = random.randint(0, 0xffffffff)  # random id ...
    if fragHeader.id is not None:  # ... except id provided by user
        fragId = fragHeader.id
    fragHeader.m = 1
    fragHeader.id = fragId
    fragHeader.nh = nh

    # Main loop : cut, fit to FRAGSIZEs, fragOffset, Id ...
    while True:
        if (len(remain) > lastFragSize):
            tmp = remain[:innerFragSize]
            remain = remain[innerFragSize:]
            fragHeader.offset = fragOffset    # update offset
            fragOffset += (innerFragSize // 8)  # compute new one
            if IPv6 in unfragPart:
                unfragPart[IPv6].plen = None
            tempo = unfragPart / fragHeader / conf.raw_layer(load=tmp)
            res.append(tempo)
        else:
            fragHeader.offset = fragOffset    # update offSet
            fragHeader.m = 0
            if IPv6 in unfragPart:
                unfragPart[IPv6].plen = None
            tempo = unfragPart / fragHeader / conf.raw_layer(load=remain)
            res.append(tempo)
            break
    return res