Removed ipv4decoder, arpdecoder, & ethernetdecoder modules from parent pom.xml. ...
[l2switch.git] / packethandler / implementation / src / main / java / org / opendaylight / l2switch / packethandler / decoders / EthernetDecoder.java
1 package org.opendaylight.l2switch.packethandler.decoders;
2
3 import org.opendaylight.controller.sal.packet.BitBufferHelper;
4 import org.opendaylight.controller.sal.packet.BufferException;
5 import org.opendaylight.controller.sal.utils.HexEncode;
6 import org.opendaylight.controller.sal.utils.NetUtils;
7 import org.opendaylight.l2switch.packethandler.decoders.PacketDecoder;
8 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
9 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.basepacket.rev140528.Packet;
10 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.basepacket.rev140528.PacketType;
11 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.basepacket.rev140528.packet.PacketPayloadTypeBuilder;
12 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.basepacket.rev140528.packet.RawPacket;
13 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.basepacket.rev140528.packet.RawPacketBuilder;
14 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.ethernet.rev140528.EthernetPacketBuilder;
15 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.ethernet.rev140528.EthernetPacketGrp;
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.ethernet.rev140528.EthernetPacketReceivedBuilder;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.ethernet.rev140528.Header8021qType;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.ethernet.rev140528.KnownEtherType;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.ethernet.rev140528.ethernet.packet.grp.Header8021q;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.ethernet.rev140528.ethernet.packet.grp.Header8021qBuilder;
21 import org.opendaylight.yangtools.yang.binding.Notification;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
24
25 import java.util.ArrayList;
26 import java.util.Arrays;
27
28 /**
29  * Ethernet Packet Decoder
30  */
31 public class EthernetDecoder implements PacketDecoder {
32   private static final Logger _logger = LoggerFactory.getLogger(EthernetDecoder.class);
33   public static final Integer LENGTH_MAX = 1500;
34   public static final Integer ETHERTYPE_MIN = 1536;
35   public static final Integer ETHERTYPE_8021Q = 0x8100;
36   public static final Integer ETHERTYPE_QINQ = 0x9100;
37
38   /**
39    * Decode a RawPacket into an EthernetPacket
40    *
41    * @param packet -- data from wire to deserialize
42    * @return
43    * @throws BufferException
44    */
45   @Override
46   public Packet decode(Packet packet) {
47     RawPacket rawPacket = packet.getRawPacket();
48     EthernetPacketBuilder builder = new EthernetPacketBuilder();
49     byte[] data = rawPacket.getPayload();
50
51     try {
52       // Save original rawPacket
53       builder.setRawPacket(new RawPacketBuilder().setIngress(rawPacket.getIngress()).setPayload(data).build());
54
55       // Deserialize the destination & source fields
56       builder.setDestinationMac(new MacAddress(HexEncode.bytesToHexStringFormat(BitBufferHelper.getBits(data, 0, 48))));
57       builder.setSourceMac(new MacAddress(HexEncode.bytesToHexStringFormat(BitBufferHelper.getBits(data, 48, 48))));
58
59       // Deserialize the optional field 802.1Q headers
60       Integer nextField = BitBufferHelper.getInt(BitBufferHelper.getBits(data, 96, 16));
61       int extraHeaderBits = 0;
62       ArrayList<Header8021q> headerList = new ArrayList<Header8021q>();
63       while(nextField.equals(ETHERTYPE_8021Q) || nextField.equals(ETHERTYPE_QINQ)) {
64         Header8021qBuilder hBuilder = new Header8021qBuilder();
65         hBuilder.setType(Header8021qType.forValue(nextField));
66
67         // Read 2 more bytes for priority (3bits), drop eligible (1bit), vlan-id (12bits)
68         byte[] vlanBytes = BitBufferHelper.getBits(data, 112 + extraHeaderBits, 16);
69
70         // Remove the sign & right-shift to get the priority code
71         hBuilder.setPriorityCode((short) ((vlanBytes[0] & 0xff) >> 5));
72
73         // Remove the sign & remove priority code bits & right-shift to get drop-eligible bit
74         hBuilder.setDropEligible(1 == (((vlanBytes[0] & 0xff) & 0x10) >> 4));
75
76         // Remove priority code & drop-eligible bits, to get the VLAN-id
77         vlanBytes[0] = (byte) (vlanBytes[0] & 0x0F);
78         hBuilder.setVlan(BitBufferHelper.getInt(vlanBytes));
79
80         // Add 802.1Q header to the growing collection
81         headerList.add(hBuilder.build());
82
83         // Reset value of "nextField" to correspond to following 2 bytes for next 802.1Q header or EtherType/Length
84         nextField = BitBufferHelper.getInt(BitBufferHelper.getBits(data, 128 + extraHeaderBits, 16));
85
86         // 802.1Q header means payload starts at a later position
87         extraHeaderBits += 32;
88       }
89       // Set 802.1Q headers
90       if(!headerList.isEmpty()) {
91         builder.setHeader8021q(headerList);
92       }
93
94       // Deserialize the EtherType or Length field
95       if(nextField >= ETHERTYPE_MIN) {
96         builder.setEthertype(KnownEtherType.forValue(nextField));
97       } else if(nextField <= LENGTH_MAX) {
98         builder.setEthernetLength(nextField);
99       } else {
100         _logger.debug("Undefined header, value is not valid EtherType or length.  Value is " + nextField);
101       }
102
103       // Deserialize the payload now
104       int payloadStart = 96 + 16 + extraHeaderBits;
105       int payloadSize = data.length * NetUtils.NumBitsInAByte - payloadStart;
106       int start = payloadStart / NetUtils.NumBitsInAByte;
107       int stop = start + payloadSize / NetUtils.NumBitsInAByte;
108       builder.setEthernetPayload(Arrays.copyOfRange(data, start, stop));
109
110       if(null != builder.getEthertype()) {
111         builder.setPacketPayloadType(new PacketPayloadTypeBuilder()
112             .setPacketType(PacketType.Ethernet)
113             .setPayloadType(builder.getEthertype().getIntValue())
114             .build());
115       }
116
117     } catch(BufferException be) {
118       _logger.info("Exception during decoding raw packet to ethernet.");
119     }
120
121     return builder.build();
122
123     //ToDo:  Possibly log these values
124       /*if (_logger.isTraceEnabled()) {
125         _logger.trace("{}: {}: {} (offset {} bitsize {})",
126           new Object[] { this.getClass().getSimpleName(), hdrField,
127             HexEncode.bytesToHexString(hdrFieldBytes),
128             startOffset, numBits });
129       }*/
130   }
131
132   @Override
133   public Notification buildPacketNotification(Packet decodedPacket) {
134     if(!(decodedPacket instanceof EthernetPacketGrp)) return null;
135
136     EthernetPacketReceivedBuilder ethernetPacketReceivedBuilder = new EthernetPacketReceivedBuilder((EthernetPacketGrp) decodedPacket);
137     return ethernetPacketReceivedBuilder.build();
138   }
139 }