As Specified in RFC 2460 - 8.1 Upper-Layer Checksums

    Performs IPv6 Upper Layer checksum computation. Provided parameters are:
    - 'nh' : value of upper layer protocol
    - 'u'  : upper layer instance (TCP, UDP, ICMPv6*, ). Instance must be
             provided with all under layers (IPv6 and all extension headers,
             for example)
    - 'p'  : the payload of the upper layer provided as a string

    Functions operate by filling a pseudo header class instance (PseudoIPv6)
    with
    - Next Header value
    - the address of _final_ destination (if some Routing Header with non
    segleft field is present in underlayer classes, last address is used.)
    - the address of _real_ source (basically the source address of an
    IPv6 class instance available in the underlayer or the source address
    in HAO option if some Destination Option header found in underlayer
    includes this option).
    - the length is the length of provided payload string ('p')

def in6_chksum(nh, u, p):
    """
    As Specified in RFC 2460 - 8.1 Upper-Layer Checksums

    Performs IPv6 Upper Layer checksum computation. Provided parameters are:
    - 'nh' : value of upper layer protocol
    - 'u'  : upper layer instance (TCP, UDP, ICMPv6*, ). Instance must be
             provided with all under layers (IPv6 and all extension headers,
             for example)
    - 'p'  : the payload of the upper layer provided as a string

    Functions operate by filling a pseudo header class instance (PseudoIPv6)
    with
    - Next Header value
    - the address of _final_ destination (if some Routing Header with non
    segleft field is present in underlayer classes, last address is used.)
    - the address of _real_ source (basically the source address of an
    IPv6 class instance available in the underlayer or the source address
    in HAO option if some Destination Option header found in underlayer
    includes this option).
    - the length is the length of provided payload string ('p')
    """

    ph6 = PseudoIPv6()
    ph6.nh = nh
    rthdr = 0
    hahdr = 0
    final_dest_addr_found = 0
    while u is not None and not isinstance(u, IPv6):
        if (isinstance(u, IPv6ExtHdrRouting) and
            u.segleft != 0 and len(u.addresses) != 0 and
                final_dest_addr_found == 0):
            rthdr = u.addresses[-1]
            final_dest_addr_found = 1
        elif (isinstance(u, IPv6ExtHdrSegmentRouting) and
              u.segleft != 0 and len(u.addresses) != 0 and
              final_dest_addr_found == 0):
            rthdr = u.addresses[0]
            final_dest_addr_found = 1
        elif (isinstance(u, IPv6ExtHdrDestOpt) and (len(u.options) == 1) and
              isinstance(u.options[0], HAO)):
            hahdr = u.options[0].hoa
        u = u.underlayer
    if u is None:
        warning("No IPv6 underlayer to compute checksum. Leaving null.")
        return 0
    if hahdr:
        ph6.src = hahdr
    else:
        ph6.src = u.src
    if rthdr:
        ph6.dst = rthdr
    else:
        ph6.dst = u.dst
    ph6.uplen = len(p)
    ph6s = raw(ph6)
    return checksum(ph6s + p)