def from_bytes(cls, bitstream, decode_payload=True):
        '''
        Parse the given packet and update properties accordingly
        '''
        packet = cls()

        # Convert to ConstBitStream (if not already provided)
        if not isinstance(bitstream, ConstBitStream):
            if isinstance(bitstream, Bits):
                bitstream = ConstBitStream(auto=bitstream)
            else:
                bitstream = ConstBitStream(bytes=bitstream)

        # Read the version
        version = bitstream.read('uint:4')
        if version != packet.version:
            raise ValueError('Provided bytes do not contain an IPv6 packet')

        # Read the traffic class
        packet.traffic_class = bitstream.read('uint:8')

        # Read the flow label
        packet.flow_label = bitstream.read('uint:20')

        # Read the payload length
        payload_length = bitstream.read('uint:16')

        # Read the next header type
        packet.next_header = bitstream.read('uint:8')

        # Read the hop limit
        packet.hop_limit = bitstream.read('uint:8')

        # Read the source and destination addresses
        packet.source = IPv6Address(bitstream.read('uint:128'))
        packet.destination = IPv6Address(bitstream.read('uint:128'))

        # And the rest is payload
        packet.payload = bitstream.read('bytes:%d' % payload_length)

        if decode_payload:
            payload_class = protocol_registry.get_type_class(packet.next_header)
            if payload_class:
                packet.payload = payload_class.from_bytes(packet.payload)

        # There should be no remaining bits
        if bitstream.pos != bitstream.len:
            raise ValueError('Bits remaining after processing packet')

        # Verify that the properties make sense
        packet.sanitize()

        return packet
Parse the given packet and update properties accordingly