blob: 5b78719d5f7c82861654795bf4d85f86969f9180 [file] [log] [blame]
Daniel Park4d486842018-07-24 17:06:43 +09001/*
2 * Copyright 2018-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.openstacknetworking.impl;
17
18import org.onlab.packet.Data;
19import org.onlab.packet.Deserializer;
20import org.onlab.packet.ICMP;
21import org.onlab.packet.IPv4;
22
23import java.nio.ByteBuffer;
24
25import static com.google.common.base.MoreObjects.toStringHelper;
26import static org.onlab.packet.PacketUtils.checkInput;
27
28/**
29 * ICMP packet class for echo purpose.
30 */
31public class IcmpEcho extends ICMP {
32 protected byte icmpType;
33 protected byte icmpCode;
34 protected short checksum;
35 protected short identifier;
36 protected short sequenceNum;
37
38 public static final short ICMP_HEADER_LENGTH = 8;
39
40 /**
41 * @return the icmpType
42 */
43 public byte getIcmpType() {
44 return this.icmpType;
45 }
46
47 /**
48 * @param icmpType to set
49 * @return this
50 */
51 public IcmpEcho setIcmpType(final byte icmpType) {
52 this.icmpType = icmpType;
53 return this;
54 }
55
56 /**
57 * @return the icmp code
58 */
59 public byte getIcmpCode() {
60 return this.icmpCode;
61 }
62
63 /**
64 * @param icmpCode code to set
65 * @return this
66 */
67 public IcmpEcho setIcmpCode(final byte icmpCode) {
68 this.icmpCode = icmpCode;
69 return this;
70 }
71
72 /**
73 * @return the checksum
74 */
75 public short getChecksum() {
76 return this.checksum;
77 }
78
79 /**
80 * @param checksum the checksum to set
81 * @return this
82 */
83 public IcmpEcho setChecksum(final short checksum) {
84 this.checksum = checksum;
85 return this;
86 }
87
88 /**
89 * Sets the identifier.
90 *
91 * @param identifier identifier
92 * @return this
93 */
94 public IcmpEcho setIdentifier(final short identifier) {
95 this.identifier = identifier;
96 return this;
97 }
98
99 /**
100 * Sets the sequencer number.
101 *
102 * @param sequenceNum sequence number
103 * @return this
104 */
105
106 public IcmpEcho setSequenceNum(final short sequenceNum) {
107 this.sequenceNum = sequenceNum;
108 return this;
109 }
110
111 /**
112 * Gets the identifier.
113 *
114 * @return identifier
115 */
116 public short getIdentifier() {
117 return this.identifier;
118 }
119
120 /**
121 * Gets the sequence number.
122 *
123 * @return sequence number
124 */
125 public short getSequenceNum() {
126 return this.sequenceNum;
127 }
128
129 /**
130 * Serializes the packet. Will compute and set the following fields if they
131 * are set to specific values at the time serialize is called: -checksum : 0
132 * -length : 0
133 */
134 @Override
135 public byte[] serialize() {
136 int length = 8;
137 byte[] payloadData = null;
138 if (this.payload != null) {
139 this.payload.setParent(this);
140 payloadData = this.payload.serialize();
141 length += payloadData.length;
142 }
143
144 final byte[] data = new byte[length];
145 final ByteBuffer bb = ByteBuffer.wrap(data);
146
147 bb.put(this.icmpType);
148 bb.put(this.icmpCode);
149 bb.putShort(this.checksum);
150 bb.putShort(this.identifier);
151 bb.putShort(this.sequenceNum);
152 if (payloadData != null) {
153 bb.put(payloadData);
154 }
155
156 if (this.parent != null && this.parent instanceof IPv4) {
157 ((IPv4) this.parent).setProtocol(IPv4.PROTOCOL_ICMP);
158 }
159
160 // compute checksum if needed
161 if (this.checksum == 0) {
162 bb.rewind();
163 int accumulation = 0;
164
165 for (int i = 0; i < length / 2; ++i) {
166 accumulation += 0xffff & bb.getShort();
167 }
168 // pad to an even number of shorts
169 if (length % 2 > 0) {
170 accumulation += (bb.get() & 0xff) << 8;
171 }
172
173 accumulation = (accumulation >> 16 & 0xffff)
174 + (accumulation & 0xffff);
175 this.checksum = (short) (~accumulation & 0xffff);
176 bb.putShort(2, this.checksum);
177 }
178 return data;
179 }
180
181 /*
182 * (non-Javadoc)
183 *
184 * @see java.lang.Object#hashCode()
185 */
186 @Override
187 public int hashCode() {
188 final int prime = 5807;
189 int result = super.hashCode();
190 result = prime * result + this.icmpType;
191 result = prime * result + this.icmpCode;
192 result = prime * result + this.checksum;
193 result = prime * result + this.identifier;
194 result = prime * result + this.sequenceNum;
195 return result;
196 }
197
198 /*
199 * (non-Javadoc)
200 *
201 * @see java.lang.Object#equals(java.lang.Object)
202 */
203 @Override
204 public boolean equals(final Object obj) {
205 if (this == obj) {
206 return true;
207 }
208 if (!super.equals(obj)) {
209 return false;
210 }
211 if (!(obj instanceof IcmpEcho)) {
212 return false;
213 }
214 final IcmpEcho other = (IcmpEcho) obj;
215 if (this.icmpType != other.icmpType) {
216 return false;
217 }
218 if (this.icmpCode != other.icmpCode) {
219 return false;
220 }
221 if (this.checksum != other.checksum) {
222 return false;
223 }
224 if (this.identifier != other.identifier) {
225 return false;
226 }
227 if (this.sequenceNum != other.sequenceNum) {
228 return false;
229 }
230 return true;
231 }
232
233 /**
234 * Deserializer function for ICMP packets.
235 *
236 * @return deserializer function
237 */
238 public static Deserializer<ICMP> deserializer() {
239 return (data, offset, length) -> {
240 checkInput(data, offset, length, ICMP_HEADER_LENGTH);
241
242 IcmpEcho icmp = new IcmpEcho();
243
244 final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
245 icmp.icmpType = bb.get();
246 icmp.icmpCode = bb.get();
247 icmp.checksum = bb.getShort();
248 icmp.identifier = bb.getShort();
249 icmp.sequenceNum = bb.getShort();
250
251 icmp.payload = Data.deserializer()
252 .deserialize(data, bb.position(), bb.limit()
253 - bb.position());
254 icmp.payload.setParent(icmp);
255 return icmp;
256 };
257 }
258
259 @Override
260 public String toString() {
261 return toStringHelper(getClass())
262 .add("icmpType", Byte.toString(icmpType))
263 .add("icmpCode", Byte.toString(icmpCode))
264 .add("checksum", Short.toString(checksum))
265 .add("identifier", Short.toString(identifier))
266 .add("sequenceNumber", Short.toString(sequenceNum))
267 .toString();
268 }
269}