2 * Copyright (c) 2013 - 2015 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
9 package org.opendaylight.vpnservice.mdsalutil.packet;
11 import java.util.HashMap;
12 import java.util.LinkedHashMap;
15 import org.apache.commons.lang3.tuple.ImmutablePair;
16 import org.apache.commons.lang3.tuple.Pair;
17 import org.opendaylight.controller.liblldp.BitBufferHelper;
18 import org.opendaylight.controller.liblldp.BufferException;
19 import org.opendaylight.controller.liblldp.NetUtils;
20 import org.opendaylight.controller.liblldp.Packet;
21 import org.opendaylight.controller.liblldp.PacketException;
24 * Class that represents the ICMP packet objects
27 public class ICMP extends Packet {
28 private static final String TYPE = "Type";
29 private static final String CODE = "Code";
30 private static final String CHECKSUM = "Checksum";
31 private static final String IDENTIFIER = "Identifier";
32 private static final String SEQNUMBER = "SequenceNumber";
34 private static Map<String, Pair<Integer, Integer>> fieldCoordinates = new LinkedHashMap<String, Pair<Integer, Integer>>() {
35 private static final long serialVersionUID = 1L;
37 put(TYPE, new ImmutablePair<Integer, Integer>(0, 8));
38 put(CODE, new ImmutablePair<Integer, Integer>(8, 8));
39 put(CHECKSUM, new ImmutablePair<Integer, Integer>(16, 16));
40 put(IDENTIFIER, new ImmutablePair<Integer, Integer>(32, 16));
41 put(SEQNUMBER, new ImmutablePair<Integer, Integer>(48, 16));
46 * Default constructor that creates and sets the hash map values
50 fieldValues = new HashMap<String, byte[]>();
51 hdrFieldCoordMap = fieldCoordinates;
52 hdrFieldsMap = fieldValues;
56 * Constructor that sets the access level for the packet
57 * @param writeAccess - boolean
59 public ICMP(boolean writeAccess) {
61 fieldValues = new HashMap<String, byte[]>();
62 hdrFieldCoordMap = fieldCoordinates;
63 hdrFieldsMap = fieldValues;
66 private final Map<String, byte[]> fieldValues;
69 public void setHeaderField(String headerField, byte[] readValue) {
70 hdrFieldsMap.put(headerField, readValue);
74 * Sets the type for the current ICMP message
77 * The ICMP message type
78 * @return This ICMP object
80 public ICMP setType(byte type) {
81 byte[] icmpType = BitBufferHelper.toByteArray(type);
82 fieldValues.put(TYPE, icmpType);
87 * Returns the type field of the current ICMP packet
89 * @return The type code of the current ICMP packet
91 public byte getType() {
92 return BitBufferHelper.getByte(fieldValues.get(TYPE));
96 * Sets the ICMP code (type subtype) for the current ICMP object instance
99 * The ICMP message type subtype
100 * @return This ICMP object
102 public ICMP setCode(byte code) {
103 byte[] icmpCode = BitBufferHelper.toByteArray(code);
104 fieldValues.put(CODE, icmpCode);
109 * Gets the ICMP code (type subtype) for the current ICMP object instance
111 * @return The ICMP message type subtype
113 public byte getCode() {
114 return BitBufferHelper.getByte(fieldValues.get(CODE));
118 * Sets the ICMP checksum for the current ICMP object instance
119 * @param checksum - short
122 public ICMP setChecksum(short checksum) {
123 byte[] icmpChecksum = BitBufferHelper.toByteArray(checksum);
124 fieldValues.put(CHECKSUM, icmpChecksum);
129 * Sets the ICMP identifier for the current ICMP object instance
130 * @param identifier - short
133 public ICMP setIdentifier(short identifier) {
134 byte[] icmpIdentifier = BitBufferHelper.toByteArray(identifier);
135 fieldValues.put(IDENTIFIER, icmpIdentifier);
140 * Gets the ICMP identifier of the current ICMP object instance
142 * @return short - identifier
145 public short getIdentifier() {
146 return BitBufferHelper.getShort(fieldValues.get(IDENTIFIER));
150 * Sets the ICMP sequence number for the current ICMP object instance
151 * @param seqNumber-short
154 public ICMP setSequenceNumber(short seqNumber) {
155 byte[] icmpSeqNumber = BitBufferHelper.toByteArray(seqNumber);
156 fieldValues.put(SEQNUMBER, icmpSeqNumber);
161 * Gets the ICMP sequence number of the current ICMP object instance
163 * @return short - seqNumber
166 public short getSequenceNumber() {
167 return BitBufferHelper.getShort(fieldValues.get(SEQNUMBER));
171 * Gets the header size in bits
172 * @return The ICMP header size in bits
175 public int getHeaderSize() {
180 * Computes the ICMP checksum on the serialized ICMP message
183 * The serialized data stream
185 * The byte index on the data stream from which the ICMP packet
187 * @return The checksum
189 short computeChecksum(byte[] data, int start) {
190 int sum = 0, carry = 0, finalSum = 0;
192 int end = start + this.getHeaderSize() / NetUtils.NumBitsInAByte;
193 if (rawPayload != null) {
194 end += rawPayload.length;
196 int checksumStartByte = start + getfieldOffset(CHECKSUM) / NetUtils.NumBitsInAByte;
199 for (int i = start; i < even; i = i + 2) {
200 // Skip, if the current bytes are checkSum bytes
201 if (i == checksumStartByte) {
204 wordData = ((data[i] << 8) & 0xFF00) + (data[i + 1] & 0xFF);
205 sum = sum + wordData;
208 // Add the last octet with zero padding.
209 wordData = (data[even] << 8) & 0xFF00;
210 sum = sum + wordData;
214 finalSum = (sum & 0xFFFF) + carry;
215 return (short) ~((short) finalSum & 0xFFFF);
219 protected void postSerializeCustomOperation(byte[] serializedBytes)
220 throws PacketException {
221 byte[] checkSum = BitBufferHelper
222 .toByteArray(computeChecksum(serializedBytes, 0));
224 BitBufferHelper.setBytes(serializedBytes, checkSum,
225 getfieldOffset(CHECKSUM), getfieldnumBits(CHECKSUM));
226 } catch (BufferException e) {
227 throw new PacketException(e.getMessage());
232 protected void postDeserializeCustomOperation(byte[] data, int endBitOffset) {
233 short computedChecksum = computeChecksum(data, endBitOffset / NetUtils.NumBitsInAByte);
234 short actualChecksum = BitBufferHelper.getShort(fieldValues.get(CHECKSUM));
236 if (computedChecksum != actualChecksum) {
242 * Gets the checksum value stored
243 * @return the checksum
245 public short getChecksum() {
246 return (BitBufferHelper.getShort(fieldValues.get(CHECKSUM)));