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.genius.mdsalutil.packet;
11 import java.util.HashMap;
12 import java.util.LinkedHashMap;
14 import org.apache.commons.lang3.tuple.ImmutablePair;
15 import org.apache.commons.lang3.tuple.Pair;
16 import org.opendaylight.openflowplugin.libraries.liblldp.BitBufferHelper;
17 import org.opendaylight.openflowplugin.libraries.liblldp.BufferException;
18 import org.opendaylight.openflowplugin.libraries.liblldp.Packet;
19 import org.opendaylight.openflowplugin.libraries.liblldp.PacketException;
22 * Class that represents the ICMP packet objects.
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";
31 @SuppressWarnings("serial")
32 private static final Map<String, Pair<Integer, Integer>> FIELD_COORDINATES
33 = new LinkedHashMap<String, Pair<Integer, Integer>>() { {
34 put(TYPE, new ImmutablePair<>(0, 8));
35 put(CODE, new ImmutablePair<>(8, 8));
36 put(CHECKSUM, new ImmutablePair<>(16, 16));
37 put(IDENTIFIER, new ImmutablePair<>(32, 16));
38 put(SEQNUMBER, new ImmutablePair<>(48, 16));
43 * Default constructor that creates and sets the hash map values.
46 fieldValues = new HashMap<>();
47 hdrFieldCoordMap = FIELD_COORDINATES;
48 hdrFieldsMap = fieldValues;
52 * Constructor that sets the access level for the packet.
53 * @param writeAccess - boolean
55 public ICMP(boolean writeAccess) {
57 fieldValues = new HashMap<>();
58 hdrFieldCoordMap = FIELD_COORDINATES;
59 hdrFieldsMap = fieldValues;
62 private final Map<String, byte[]> fieldValues;
65 public void setHeaderField(String headerField, byte[] readValue) {
66 hdrFieldsMap.put(headerField, readValue);
70 * Sets the type for the current ICMP message.
73 * The ICMP message type
74 * @return This ICMP object
76 public ICMP setType(byte type) {
77 byte[] icmpType = BitBufferHelper.toByteArray(type);
78 fieldValues.put(TYPE, icmpType);
83 * Returns the type field of the current ICMP packet.
85 * @return The type code of the current ICMP packet
87 public byte getType() {
88 return BitBufferHelper.getByte(fieldValues.get(TYPE));
92 * Sets the ICMP code (type subtype) for the current ICMP object instance.
95 * The ICMP message type subtype
96 * @return This ICMP object
98 public ICMP setCode(byte code) {
99 byte[] icmpCode = BitBufferHelper.toByteArray(code);
100 fieldValues.put(CODE, icmpCode);
105 * Gets the ICMP code (type subtype) for the current ICMP object instance.
107 * @return The ICMP message type subtype
109 public byte getCode() {
110 return BitBufferHelper.getByte(fieldValues.get(CODE));
114 * Sets the ICMP checksum for the current ICMP object instance.
115 * @param checksum - short
118 public ICMP setChecksum(short checksum) {
119 byte[] icmpChecksum = BitBufferHelper.toByteArray(checksum);
120 fieldValues.put(CHECKSUM, icmpChecksum);
125 * Sets the ICMP identifier for the current ICMP object instance.
126 * @param identifier - short
129 public ICMP setIdentifier(short identifier) {
130 byte[] icmpIdentifier = BitBufferHelper.toByteArray(identifier);
131 fieldValues.put(IDENTIFIER, icmpIdentifier);
136 * Gets the ICMP identifier of the current ICMP object instance.
138 * @return short - identifier
140 public short getIdentifier() {
141 return BitBufferHelper.getShort(fieldValues.get(IDENTIFIER));
145 * Sets the ICMP sequence number for the current ICMP object instance.
146 * @param seqNumber sequence number
147 * @return sequence number
149 public ICMP setSequenceNumber(short seqNumber) {
150 byte[] icmpSeqNumber = BitBufferHelper.toByteArray(seqNumber);
151 fieldValues.put(SEQNUMBER, icmpSeqNumber);
156 * Gets the ICMP sequence number of the current ICMP object instance.
158 * @return short - seqNumber
160 public short getSequenceNumber() {
161 return BitBufferHelper.getShort(fieldValues.get(SEQNUMBER));
165 * Gets the header size in bits.
166 * @return The ICMP header size in bits
169 public int getHeaderSize() {
174 * Computes the ICMP checksum on the serialized ICMP message..
177 * The serialized data stream
179 * The byte index on the data stream from which the ICMP packet
181 * @return The checksum
183 short computeChecksum(byte[] data, int start) {
186 int end = start + this.getHeaderSize() / Byte.SIZE;
187 if (rawPayload != null) {
188 end += rawPayload.length;
190 int checksumStartByte = start + getfieldOffset(CHECKSUM) / Byte.SIZE;
193 for (int i = start; i < even; i = i + 2) {
194 // Skip, if the current bytes are checkSum bytes
195 if (i == checksumStartByte) {
198 wordData = (data[i] << 8 & 0xFF00) + (data[i + 1] & 0xFF);
199 sum = sum + wordData;
202 // Add the last octet with zero padding.
203 wordData = data[even] << 8 & 0xFF00;
204 sum = sum + wordData;
207 int carry = sum >>> 16;
208 int finalSum = (sum & 0xFFFF) + carry;
209 return (short) ~((short) finalSum & 0xFFFF);
213 protected void postSerializeCustomOperation(byte[] serializedBytes)
214 throws PacketException {
215 byte[] checkSum = BitBufferHelper
216 .toByteArray(computeChecksum(serializedBytes, 0));
218 BitBufferHelper.setBytes(serializedBytes, checkSum,
219 getfieldOffset(CHECKSUM), getfieldnumBits(CHECKSUM));
220 } catch (BufferException e) {
221 throw new PacketException(e.getMessage(), e);
226 protected void postDeserializeCustomOperation(byte[] data, int endBitOffset) {
227 short computedChecksum = computeChecksum(data, endBitOffset / Byte.SIZE);
228 short actualChecksum = BitBufferHelper.getShort(fieldValues.get(CHECKSUM));
230 if (computedChecksum != actualChecksum) {
236 * Gets the checksum value stored.
237 * @return the checksum
239 public short getChecksum() {
240 return BitBufferHelper.getShort(fieldValues.get(CHECKSUM));