class IPv6 extends BasePacket {

	@Override
	public IPacket deserialize(byte[] data, int offset, int length)
			throws PacketParsingException {
		// Wrap the data in a byte buffer for easier retrieval.
		ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
		// Retrieve values from IPv6 header.
		byte firstByte = bb.get();
		byte secondByte = bb.get();
		this.version = (byte) ((firstByte & 0xF0) >>> 4);
		if (this.version != 6) {
			throw new PacketParsingException(
					"Invalid version for IPv6 packet: " +
							this.version);
		}
		this.trafficClass = (byte) (((firstByte & 0xF) << 4) |
				((secondByte & 0xF0) >>> 4));
		this.flowLabel = ((secondByte & 0xF) << 16) |
				(bb.getShort() & 0xFFFF);
		this.payloadLength = bb.getShort();
		this.nextHeader = IpProtocol.of(bb.get());
		this.hopLimit = bb.get();
		byte[] sourceAddress = new byte[16];
		bb.get(sourceAddress, 0, 16);
		byte[] destinationAddress = new byte[16];
		bb.get(destinationAddress, 0, 16);
		this.sourceAddress = IPv6Address.of(sourceAddress);
		this.destinationAddress = IPv6Address.of(destinationAddress);
		// Retrieve the payload, if possible.
		IPacket payload;
		if (IPv6.nextHeaderClassMap.containsKey(this.nextHeader)) {
			Class<? extends IPacket> clazz = IPv6.nextHeaderClassMap.get(this.nextHeader);
			try {
				payload = clazz.newInstance();
			} catch (Exception e) {
				throw new RuntimeException("Error parsing payload for IPv6 packet", e);
			}
		} else {
			payload = new Data();
		}
		// Deserialize as much of the payload as we can (hopefully all of it).
		this.payload = payload.deserialize(data, bb.position(),
				Math.min(this.payloadLength, bb.limit() - bb.position()));
		this.payload.setParent(this);
		// We're done!
		return this;
	}

	public  IPv6();

}