5a99901043f8d9c3f2d8a98a3be84ccb664c8b15
[l2switch.git] / packethandler / implementation / src / main / java / org / opendaylight / l2switch / packethandler / decoders / ArpDecoder.java
1 package org.opendaylight.l2switch.packethandler.decoders;
2
3 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
4 import org.opendaylight.controller.sal.packet.BitBufferHelper;
5 import org.opendaylight.controller.sal.packet.BufferException;
6 import org.opendaylight.controller.sal.utils.HexEncode;
7 import org.opendaylight.controller.sal.utils.NetUtils;
8 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.arp.rev140528.ArpPacketOverEthernetReceived;
9 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.arp.rev140528.ArpPacketOverEthernetReceivedBuilder;
10 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.arp.rev140528.KnownHardwareType;
11 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.arp.rev140528.KnownOperation;
12 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.arp.rev140528.arp.packet.over.ethernet.fields.ArpPacketBuilder;
13 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.arp.rev140528.arp.packet.over.ethernet.fields.EthernetOverRawPacket;
14 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.arp.rev140528.arp.packet.over.ethernet.fields.EthernetOverRawPacketBuilder;
15 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.ethernet.rev140528.EthernetPacketListener;
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.ethernet.rev140528.EthernetPacketOverRawReceived;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.ethernet.rev140528.KnownEtherType;
18 import org.opendaylight.yangtools.yang.binding.NotificationListener;
19 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
21
22 import java.net.InetAddress;
23 import java.net.UnknownHostException;
24
25 /**
26  * ARP (Address Resolution Protocol) Packet Decoder
27  */
28 public class ArpDecoder extends AbstractPacketDecoder<EthernetPacketOverRawReceived, ArpPacketOverEthernetReceived>
29     implements EthernetPacketListener {
30
31   private static final Logger _logger = LoggerFactory.getLogger(ArpDecoder.class);
32
33   public ArpDecoder(NotificationProviderService notificationProviderService) {
34     super(ArpPacketOverEthernetReceived.class, notificationProviderService);
35   }
36
37   /**
38    * Decode an EthernetPacket into an ArpPacket
39    */
40   @Override
41   public ArpPacketOverEthernetReceived decode(EthernetPacketOverRawReceived ethernetPacketOverRawReceived) {
42     ArpPacketOverEthernetReceivedBuilder arpReceivedBuilder = new ArpPacketOverEthernetReceivedBuilder();
43
44     byte[] data = ethernetPacketOverRawReceived.getPayload();
45     int bitOffset = ethernetPacketOverRawReceived.getEthernetPacket().getPayloadOffset() * NetUtils.NumBitsInAByte;
46
47     ArpPacketBuilder builder = new ArpPacketBuilder();
48
49     try {
50       // Decode the hardware-type (HTYPE) and protocol-type (PTYPE) fields
51       builder.setHardwareType(KnownHardwareType.forValue(BitBufferHelper.getInt(BitBufferHelper.getBits(data, bitOffset + 0, 16))));
52       builder.setProtocolType(KnownEtherType.forValue(BitBufferHelper.getInt(BitBufferHelper.getBits(data, bitOffset+16, 16))));
53
54       // Decode the hardware-length and protocol-length fields
55       builder.setHardwareLength(BitBufferHelper.getShort(BitBufferHelper.getBits(data, bitOffset+32, 8)));
56       builder.setProtocolLength(BitBufferHelper.getShort(BitBufferHelper.getBits(data, bitOffset+40, 8)));
57
58       // Decode the operation field
59       builder.setOperation(KnownOperation.forValue(BitBufferHelper.getInt(BitBufferHelper.getBits(data, bitOffset+48, 16))));
60
61       // Decode the address fields
62       int indexSrcProtAdd = 64 + 8 * builder.getHardwareLength();
63       int indexDstHardAdd = indexSrcProtAdd + 8 * builder.getProtocolLength();
64       int indexDstProtAdd = indexDstHardAdd + 8 * builder.getHardwareLength();
65       if(builder.getHardwareType().equals(KnownHardwareType.Ethernet)) {
66         builder.setSourceHardwareAddress(HexEncode.bytesToHexStringFormat(BitBufferHelper.getBits(data, bitOffset + 64, 8 * builder.getHardwareLength())));
67         builder.setDestinationHardwareAddress(HexEncode.bytesToHexStringFormat(BitBufferHelper.getBits(data, bitOffset + indexDstHardAdd, 8 * builder.getHardwareLength())));
68       } else {
69         _logger.debug("Unknown HardwareType -- sourceHardwareAddress and destinationHardwareAddress are not decoded");
70       }
71
72       if(builder.getProtocolType().equals(KnownEtherType.Ipv4) || builder.getProtocolType().equals(KnownEtherType.Ipv6)) {
73         builder.setSourceProtocolAddress(InetAddress.getByAddress(BitBufferHelper.getBits(data, bitOffset + indexSrcProtAdd, 8 * builder.getProtocolLength())).getHostAddress());
74         builder.setDestinationProtocolAddress(InetAddress.getByAddress(BitBufferHelper.getBits(data, bitOffset + indexDstProtAdd, 8 * builder.getProtocolLength())).getHostAddress());
75       } else {
76         _logger.debug("Unknown ProtocolType -- sourceProtocolAddress and destinationProtocolAddress are not decoded");
77       }
78     } catch(BufferException | UnknownHostException e) {
79       _logger.debug("Exception while decoding APR packet", e.getMessage());
80     }
81
82     //build arp
83     arpReceivedBuilder.setArpPacket(builder.build());
84
85     // extract ethernet over raw context from the consumed notification and set it and set it in Produced notification
86     EthernetOverRawPacketBuilder ethernetOverRawPacketBuilder =  new EthernetOverRawPacketBuilder();
87     ethernetOverRawPacketBuilder.setRawPacket(ethernetPacketOverRawReceived.getRawPacket());
88     ethernetOverRawPacketBuilder.setEthernetPacket(ethernetPacketOverRawReceived.getEthernetPacket());
89
90     //set the context of previous decoded fields
91     arpReceivedBuilder.setEthernetOverRawPacket(ethernetOverRawPacketBuilder.build());
92
93     // carry forward the original payload.
94     arpReceivedBuilder.setPayload(ethernetPacketOverRawReceived.getPayload());
95
96     return arpReceivedBuilder.build();
97   }
98
99   @Override
100   public NotificationListener getConsumedNotificationListener() {
101     return this;
102   }
103
104   @Override
105   public void onEthernetPacketOverRawReceived(EthernetPacketOverRawReceived notification) {
106     decodeAndPublish(notification);
107   }
108
109   @Override
110   public boolean canDecode(EthernetPacketOverRawReceived ethernetPacketOverRawReceived) {
111     if(ethernetPacketOverRawReceived==null || ethernetPacketOverRawReceived.getEthernetPacket()==null)
112       return false;
113     return KnownEtherType.Arp.equals(ethernetPacketOverRawReceived.getEthernetPacket().getEthertype());
114   }
115 }