Bug 1926: fixed features/mdsal/pom.xml dependencies
[controller.git] / opendaylight / sal / api / src / main / java / org / opendaylight / controller / sal / packet / ICMP.java
1
2 /*
3  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
4  *
5  * This program and the accompanying materials are made available under the
6  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
7  * and is available at http://www.eclipse.org/legal/epl-v10.html
8  */
9
10 package org.opendaylight.controller.sal.packet;
11
12 import java.util.HashMap;
13 import java.util.LinkedHashMap;
14 import java.util.Map;
15
16 import org.apache.commons.lang3.tuple.ImmutablePair;
17 import org.apache.commons.lang3.tuple.Pair;
18 import org.opendaylight.controller.sal.utils.NetUtils;
19
20 /**
21  * Class that represents the ICMP packet objects
22  */
23
24 public class ICMP extends Packet {
25     private static final String TYPE = "Type";
26     private static final String CODE = "Code";
27     private static final String CHECKSUM = "Checksum";
28     private static final String IDENTIFIER = "Identifier";
29     private static final String SEQNUMBER = "SequenceNumber";
30
31     private static Map<String, Pair<Integer, Integer>> fieldCoordinates = new LinkedHashMap<String, Pair<Integer, Integer>>() {
32         private static final long serialVersionUID = 1L;
33         {
34             put(TYPE, new ImmutablePair<Integer, Integer>(0, 8));
35             put(CODE, new ImmutablePair<Integer, Integer>(8, 8));
36             put(CHECKSUM, new ImmutablePair<Integer, Integer>(16, 16));
37             put(IDENTIFIER, new ImmutablePair<Integer, Integer>(32, 16));
38             put(SEQNUMBER, new ImmutablePair<Integer, Integer>(48, 16));
39         }
40     };
41
42     /**
43      * Default constructor that creates and sets the hash map values
44      */
45     public ICMP() {
46         super();
47         fieldValues = new HashMap<String, byte[]>();
48         hdrFieldCoordMap = fieldCoordinates;
49         hdrFieldsMap = fieldValues;
50     }
51
52     /**
53      * Constructor that sets the access level for the packet
54      */
55     public ICMP(boolean writeAccess) {
56         super(writeAccess);
57         fieldValues = new HashMap<String, byte[]>();
58         hdrFieldCoordMap = fieldCoordinates;
59         hdrFieldsMap = fieldValues;
60     }
61
62     private final Map<String, byte[]> fieldValues;
63
64     @Override
65     public void setHeaderField(String headerField, byte[] readValue) {
66         hdrFieldsMap.put(headerField, readValue);
67     }
68
69     /**
70      * Sets the type for the current ICMP message
71      *
72      * @param type
73      *            The ICMP message type
74      * @return This ICMP object
75      */
76     public ICMP setType(byte type) {
77         byte[] icmpType = BitBufferHelper.toByteArray(type);
78         fieldValues.put(TYPE, icmpType);
79         return this;
80     }
81
82     /**
83      * Returns the type field of the current ICMP packet
84      *
85      * @return The type code of the current ICMP packet
86      */
87     public byte getType() {
88         return BitBufferHelper.getByte(fieldValues.get(TYPE));
89     }
90
91     /**
92      * Sets the ICMP code (type subtype) for the current ICMP object instance
93      *
94      * @param code
95      *            The ICMP message type subtype
96      * @return This ICMP object
97      */
98     public ICMP setCode(byte code) {
99         byte[] icmpCode = BitBufferHelper.toByteArray(code);
100         fieldValues.put(CODE, icmpCode);
101         return this;
102     }
103
104     /**
105      * Gets the ICMP code (type subtype) for the current ICMP object instance
106      *
107      * @return The ICMP message type subtype
108      */
109     public byte getCode() {
110         return BitBufferHelper.getByte(fieldValues.get(CODE));
111     }
112
113     /**
114      * Sets the ICMP checksum  for the current ICMP object instance
115      * @param short - checksum
116      * @return ICMP
117      */
118     public ICMP setChecksum(short checksum) {
119         byte[] icmpChecksum = BitBufferHelper.toByteArray(checksum);
120         fieldValues.put(CHECKSUM, icmpChecksum);
121         return this;
122     }
123
124     /**
125      * Sets the ICMP identifier for the current ICMP object instance
126      * @param short - identifier
127      * @return ICMP
128      */
129     public ICMP setIdentifier(short identifier) {
130         byte[] icmpIdentifier = BitBufferHelper.toByteArray(identifier);
131         fieldValues.put(IDENTIFIER, icmpIdentifier);
132         return this;
133     }
134
135     /**
136      * Gets the ICMP identifier of the current ICMP object instance
137      *
138      * @return short - identifier
139      */
140
141     public short getIdentifier() {
142         return BitBufferHelper.getShort(fieldValues.get(IDENTIFIER));
143     }
144
145     /**
146      * Sets the ICMP sequence number for the current ICMP object instance
147      * @param short - seqNumber
148      * @return ICMP
149      */
150     public ICMP setSequenceNumber(short seqNumber) {
151         byte[] icmpSeqNumber = BitBufferHelper.toByteArray(seqNumber);
152         fieldValues.put(SEQNUMBER, icmpSeqNumber);
153         return this;
154     }
155
156     /**
157      * Gets the ICMP sequence number of the current ICMP object instance
158      *
159      * @return short - seqNumber
160      */
161
162     public short getSequenceNumber() {
163         return BitBufferHelper.getShort(fieldValues.get(SEQNUMBER));
164     }
165
166     /**
167      * Gets the header size in bits
168      * @return The ICMP header size in bits
169      */
170     @Override
171     public int getHeaderSize() {
172         return 64;
173     }
174
175     /**
176      * Computes the ICMP checksum on the serialized ICMP message
177      *
178      * @param serialized
179      *            The data stream
180      * @param start
181      *            The byte index on the data stream from which the ICMP packet
182      *            starts
183      * @return The checksum
184      */
185     short computeChecksum(byte[] data, int start) {
186         int sum = 0, carry = 0, finalSum = 0;
187         int wordData;
188         int end = start + this.getHeaderSize() / NetUtils.NumBitsInAByte;
189         if (rawPayload != null) {
190             end += rawPayload.length;
191         }
192         int checksumStartByte = start + getfieldOffset(CHECKSUM) / NetUtils.NumBitsInAByte;
193
194         for (int i = start; i <= (end - 1); i = i + 2) {
195             // Skip, if the current bytes are checkSum bytes
196             if (i == checksumStartByte) {
197                 continue;
198             }
199             wordData = ((data[i] << 8) & 0xFF00) + (data[i + 1] & 0xFF);
200             sum = sum + wordData;
201         }
202         carry = (sum >> 16) & 0xFF;
203         finalSum = (sum & 0xFFFF) + carry;
204         return (short) ~((short) finalSum & 0xFFFF);
205     }
206
207     @Override
208     protected void postSerializeCustomOperation(byte[] serializedBytes)
209             throws PacketException {
210         byte[] checkSum = BitBufferHelper
211                 .toByteArray(computeChecksum(serializedBytes, 0));
212         try {
213             BitBufferHelper.setBytes(serializedBytes, checkSum,
214                     getfieldOffset(CHECKSUM), getfieldnumBits(CHECKSUM));
215         } catch (BufferException e) {
216             throw new PacketException(e.getMessage());
217         }
218     }
219
220     @Override
221     protected void postDeserializeCustomOperation(byte[] data, int endBitOffset) {
222         short computedChecksum = computeChecksum(data, endBitOffset / NetUtils.NumBitsInAByte);
223         short actualChecksum = BitBufferHelper.getShort(fieldValues.get(CHECKSUM));
224
225         if (computedChecksum != actualChecksum) {
226             corrupted = true;
227         }
228     }
229
230     /**
231      * Gets the checksum value stored
232      * @return the checksum
233      */
234     public short getChecksum() {
235         return (BitBufferHelper.getShort(fieldValues.get(CHECKSUM)));
236     }
237 }