2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.l2switch.packethandler.decoders;
10 import java.net.InetAddress;
11 import java.net.UnknownHostException;
12 import java.util.ArrayList;
13 import java.util.Arrays;
14 import java.util.List;
16 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
17 import org.opendaylight.l2switch.packethandler.decoders.utils.BitBufferHelper;
18 import org.opendaylight.l2switch.packethandler.decoders.utils.BufferException;
19 import org.opendaylight.l2switch.packethandler.decoders.utils.NetUtils;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Dscp;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.basepacket.rev140528.packet.chain.grp.PacketChain;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.basepacket.rev140528.packet.chain.grp.PacketChainBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.basepacket.rev140528.packet.chain.grp.packet.chain.Packet;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.ethernet.rev140528.EthernetPacketListener;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.ethernet.rev140528.EthernetPacketReceived;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.ethernet.rev140528.KnownEtherType;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.ethernet.rev140528.ethernet.packet.received.packet.chain.packet.EthernetPacket;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.ipv4.rev140528.KnownIpProtocols;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.ipv6.rev140528.Ipv6PacketReceived;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.ipv6.rev140528.Ipv6PacketReceivedBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.ipv6.rev140528.ipv6.packet.fields.ExtensionHeaders;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.ipv6.rev140528.ipv6.packet.fields.ExtensionHeadersBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.ipv6.rev140528.ipv6.packet.received.packet.chain.packet.Ipv6PacketBuilder;
35 import org.opendaylight.yangtools.yang.binding.NotificationListener;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
42 public class Ipv6Decoder extends AbstractPacketDecoder<EthernetPacketReceived, Ipv6PacketReceived>
43 implements EthernetPacketListener {
45 private static final Logger LOG = LoggerFactory.getLogger(Ipv6Decoder.class);
47 public Ipv6Decoder(NotificationProviderService notificationProviderService) {
48 super(Ipv6PacketReceived.class, notificationProviderService);
52 * Decode an EthernetPacket into an Ipv4Packet
55 public Ipv6PacketReceived decode(EthernetPacketReceived ethernetPacketReceived) {
56 Ipv6PacketReceivedBuilder ipv6ReceivedBuilder = new Ipv6PacketReceivedBuilder();
58 // Find the latest packet in the packet-chain, which is an
60 List<PacketChain> packetChainList = ethernetPacketReceived.getPacketChain();
61 EthernetPacket ethernetPacket = (EthernetPacket) packetChainList.get(packetChainList.size() - 1).getPacket();
62 int bitOffset = ethernetPacket.getPayloadOffset() * NetUtils.NumBitsInAByte;
63 byte[] data = ethernetPacketReceived.getPayload();
65 Ipv6PacketBuilder builder = new Ipv6PacketBuilder();
67 builder.setVersion(BitBufferHelper.getShort(BitBufferHelper.getBits(data, bitOffset, 4)));
68 if (builder.getVersion().intValue() != 6) {
69 LOG.debug("Version should be 6, but is {}", builder.getVersion());
72 builder.setDscp(new Dscp(BitBufferHelper.getShort(BitBufferHelper.getBits(data, bitOffset + 4, 6))));
73 builder.setEcn(BitBufferHelper.getShort(BitBufferHelper.getBits(data, bitOffset + 10, 2)));
74 builder.setFlowLabel(BitBufferHelper.getLong(BitBufferHelper.getBits(data, bitOffset + 12, 20)));
75 builder.setIpv6Length(BitBufferHelper.getInt(BitBufferHelper.getBits(data, bitOffset + 32, 16)));
76 builder.setNextHeader(KnownIpProtocols
77 .forValue(BitBufferHelper.getInt(BitBufferHelper.getBits(data, bitOffset + 48, 8))));
78 builder.setHopLimit(BitBufferHelper.getShort(BitBufferHelper.getBits(data, bitOffset + 56, 8)));
79 builder.setSourceIpv6(Ipv6Address.getDefaultInstance(
80 InetAddress.getByAddress(BitBufferHelper.getBits(data, bitOffset + 64, 128)).getHostAddress()));
81 builder.setDestinationIpv6(Ipv6Address.getDefaultInstance(
82 InetAddress.getByAddress(BitBufferHelper.getBits(data, bitOffset + 192, 128)).getHostAddress()));
83 builder.setPayloadOffset((320 + bitOffset) / NetUtils.NumBitsInAByte);
84 builder.setPayloadLength(builder.getIpv6Length());
86 // Decode the optional "extension headers"
87 List<ExtensionHeaders> extensionHeaders = new ArrayList<ExtensionHeaders>();
88 KnownIpProtocols nextHeader = builder.getNextHeader();
89 int extHeaderOffset = 0;
90 while (nextHeader != null && !nextHeader.equals(KnownIpProtocols.Tcp)
91 && !nextHeader.equals(KnownIpProtocols.Udp)) {
92 // Set the extension header's type & length & data
93 short nextHeaderType = BitBufferHelper
94 .getShort(BitBufferHelper.getBits(data, 320 + extHeaderOffset + bitOffset, 8));
95 nextHeader = KnownIpProtocols.forValue(nextHeaderType);
96 int octetLength = BitBufferHelper
97 .getInt(BitBufferHelper.getBits(data, 328 + extHeaderOffset + bitOffset, 8));
98 int start = (336 + extHeaderOffset + bitOffset) / NetUtils.NumBitsInAByte;
99 int end = start + 6 + octetLength;
101 extensionHeaders.add(new ExtensionHeadersBuilder().setNextHeader(nextHeader).setLength(octetLength)
102 .setData(Arrays.copyOfRange(data, start, end)).build());
104 // Update the NextHeader field
105 extHeaderOffset += 64 + octetLength * NetUtils.NumBitsInAByte;
107 if (!extensionHeaders.isEmpty()) {
108 builder.setExtensionHeaders(extensionHeaders);
110 } catch (BufferException | UnknownHostException e) {
111 LOG.debug("Exception while decoding IPv4 packet", e.getMessage());
115 packetChainList.add(new PacketChainBuilder().setPacket(builder.build()).build());
116 ipv6ReceivedBuilder.setPacketChain(packetChainList);
118 // carry forward the original payload.
119 ipv6ReceivedBuilder.setPayload(ethernetPacketReceived.getPayload());
121 return ipv6ReceivedBuilder.build();
125 public NotificationListener getConsumedNotificationListener() {
130 public void onEthernetPacketReceived(EthernetPacketReceived notification) {
131 decodeAndPublish(notification);
135 public boolean canDecode(EthernetPacketReceived ethernetPacketReceived) {
136 if (ethernetPacketReceived == null || ethernetPacketReceived.getPacketChain() == null)
139 // Only decode the latest packet in the chain
140 EthernetPacket ethernetPacket = null;
141 if (!ethernetPacketReceived.getPacketChain().isEmpty()) {
142 Packet packet = ethernetPacketReceived.getPacketChain()
143 .get(ethernetPacketReceived.getPacketChain().size() - 1).getPacket();
144 if (packet instanceof EthernetPacket) {
145 ethernetPacket = (EthernetPacket) packet;
149 return ethernetPacket != null && KnownEtherType.Ipv6.equals(ethernetPacket.getEthertype());