blob: f1054289accdb0d058c31010155f11f56f10ed5f [file] [log] [blame]
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001/**
Ray Milkey269ffb92014-04-03 14:43:30 -07002 * Copyright 2011, Big Switch Networks, Inc.
3 * Originally created by David Erickson, Stanford University
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License"); you may
6 * not use this file except in compliance with the License. You may obtain
7 * a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 * License for the specific language governing permissions and limitations
15 * under the License.
16 **/
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080017
18/**
Ray Milkey269ffb92014-04-03 14:43:30 -070019 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080020 */
Jonathan Hartdeda0ba2014-04-03 11:14:12 -070021package net.onrc.onos.core.packet;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080022
23import java.nio.ByteBuffer;
24import java.util.Arrays;
25import java.util.Collection;
26import java.util.HashMap;
27import java.util.Map;
28
Pavlin Radoslavov1d595c02014-04-16 14:11:54 -070029import org.apache.commons.lang.ArrayUtils;
30
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080031/**
32 * @author David Erickson (daviderickson@cs.stanford.edu)
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080033 */
34public class IPv4 extends BasePacket {
Ray Milkey269ffb92014-04-03 14:43:30 -070035 public static final int ADDRESS_LENGTH = 4;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080036 public static final byte PROTOCOL_ICMP = 0x1;
37 public static final byte PROTOCOL_TCP = 0x6;
38 public static final byte PROTOCOL_UDP = 0x11;
Pavlin Radoslavov608fac32014-04-09 12:40:24 -070039 public static final Map<Byte, Class<? extends IPacket>> PROTOCOL_CLASS_MAP;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080040
41 static {
Pavlin Radoslavov608fac32014-04-09 12:40:24 -070042 PROTOCOL_CLASS_MAP = new HashMap<Byte, Class<? extends IPacket>>();
43 PROTOCOL_CLASS_MAP.put(PROTOCOL_ICMP, ICMP.class);
44 PROTOCOL_CLASS_MAP.put(PROTOCOL_TCP, TCP.class);
45 PROTOCOL_CLASS_MAP.put(PROTOCOL_UDP, UDP.class);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080046 }
47
48 protected byte version;
49 protected byte headerLength;
50 protected byte diffServ;
51 protected short totalLength;
52 protected short identification;
53 protected byte flags;
54 protected short fragmentOffset;
55 protected byte ttl;
56 protected byte protocol;
57 protected short checksum;
58 protected int sourceAddress;
59 protected int destinationAddress;
60 protected byte[] options;
61
62 protected boolean isTruncated;
63
64 /**
65 * Default constructor that sets the version to 4.
66 */
67 public IPv4() {
68 super();
69 this.version = 4;
70 isTruncated = false;
71 }
72
73 /**
74 * @return the version
75 */
76 public byte getVersion() {
77 return version;
78 }
79
80 /**
81 * @param version the version to set
82 */
83 public IPv4 setVersion(byte version) {
84 this.version = version;
85 return this;
86 }
87
88 /**
89 * @return the headerLength
90 */
91 public byte getHeaderLength() {
92 return headerLength;
93 }
94
95 /**
96 * @return the diffServ
97 */
98 public byte getDiffServ() {
99 return diffServ;
100 }
101
102 /**
103 * @param diffServ the diffServ to set
104 */
105 public IPv4 setDiffServ(byte diffServ) {
106 this.diffServ = diffServ;
107 return this;
108 }
109
110 /**
111 * @return the totalLength
112 */
113 public short getTotalLength() {
114 return totalLength;
115 }
116
117 /**
118 * @return the identification
119 */
120 public short getIdentification() {
121 return identification;
122 }
123
124 public boolean isTruncated() {
125 return isTruncated;
126 }
127
128 public void setTruncated(boolean isTruncated) {
129 this.isTruncated = isTruncated;
130 }
131
132 /**
133 * @param identification the identification to set
134 */
135 public IPv4 setIdentification(short identification) {
136 this.identification = identification;
137 return this;
138 }
139
140 /**
141 * @return the flags
142 */
143 public byte getFlags() {
144 return flags;
145 }
146
147 /**
148 * @param flags the flags to set
149 */
150 public IPv4 setFlags(byte flags) {
151 this.flags = flags;
152 return this;
153 }
154
155 /**
156 * @return the fragmentOffset
157 */
158 public short getFragmentOffset() {
159 return fragmentOffset;
160 }
161
162 /**
163 * @param fragmentOffset the fragmentOffset to set
164 */
165 public IPv4 setFragmentOffset(short fragmentOffset) {
166 this.fragmentOffset = fragmentOffset;
167 return this;
168 }
169
170 /**
171 * @return the ttl
172 */
173 public byte getTtl() {
174 return ttl;
175 }
176
177 /**
178 * @param ttl the ttl to set
179 */
180 public IPv4 setTtl(byte ttl) {
181 this.ttl = ttl;
182 return this;
183 }
184
185 /**
186 * @return the protocol
187 */
188 public byte getProtocol() {
189 return protocol;
190 }
191
192 /**
193 * @param protocol the protocol to set
194 */
195 public IPv4 setProtocol(byte protocol) {
196 this.protocol = protocol;
197 return this;
198 }
199
200 /**
201 * @return the checksum
202 */
203 public short getChecksum() {
204 return checksum;
205 }
206
207 /**
208 * @param checksum the checksum to set
209 */
210 public IPv4 setChecksum(short checksum) {
211 this.checksum = checksum;
212 return this;
213 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700214
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800215 @Override
216 public void resetChecksum() {
217 this.checksum = 0;
218 super.resetChecksum();
219 }
220
221 /**
222 * @return the sourceAddress
223 */
224 public int getSourceAddress() {
225 return sourceAddress;
226 }
227
228 /**
229 * @param sourceAddress the sourceAddress to set
230 */
231 public IPv4 setSourceAddress(int sourceAddress) {
232 this.sourceAddress = sourceAddress;
233 return this;
234 }
235
236 /**
237 * @param sourceAddress the sourceAddress to set
238 */
239 public IPv4 setSourceAddress(String sourceAddress) {
240 this.sourceAddress = IPv4.toIPv4Address(sourceAddress);
241 return this;
242 }
243
244 /**
245 * @return the destinationAddress
246 */
247 public int getDestinationAddress() {
248 return destinationAddress;
249 }
250
251 /**
252 * @param destinationAddress the destinationAddress to set
253 */
254 public IPv4 setDestinationAddress(int destinationAddress) {
255 this.destinationAddress = destinationAddress;
256 return this;
257 }
258
259 /**
260 * @param destinationAddress the destinationAddress to set
261 */
262 public IPv4 setDestinationAddress(String destinationAddress) {
263 this.destinationAddress = IPv4.toIPv4Address(destinationAddress);
264 return this;
265 }
266
267 /**
268 * @return the options
269 */
270 public byte[] getOptions() {
Pavlin Radoslavov1d595c02014-04-16 14:11:54 -0700271 return ArrayUtils.clone(this.options);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800272 }
273
274 /**
275 * @param options the options to set
276 */
277 public IPv4 setOptions(byte[] options) {
Ray Milkeyb29e6262014-04-09 16:02:14 -0700278 if (options != null && (options.length % 4) > 0) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800279 throw new IllegalArgumentException(
280 "Options length must be a multiple of 4");
Ray Milkeyb29e6262014-04-09 16:02:14 -0700281 }
Pavlin Radoslavov1d595c02014-04-16 14:11:54 -0700282 this.options = ArrayUtils.clone(options);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800283 return this;
284 }
285
286 /**
287 * Serializes the packet. Will compute and set the following fields if they
288 * are set to specific values at the time serialize is called:
Ray Milkey269ffb92014-04-03 14:43:30 -0700289 * -checksum : 0
290 * -headerLength : 0
291 * -totalLength : 0
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800292 */
293 public byte[] serialize() {
294 byte[] payloadData = null;
295 if (payload != null) {
296 payload.setParent(this);
297 payloadData = payload.serialize();
298 }
299
300 int optionsLength = 0;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700301 if (this.options != null) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800302 optionsLength = this.options.length / 4;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700303 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800304 this.headerLength = (byte) (5 + optionsLength);
305
306 this.totalLength = (short) (this.headerLength * 4 + ((payloadData == null) ? 0
307 : payloadData.length));
308
309 byte[] data = new byte[this.totalLength];
310 ByteBuffer bb = ByteBuffer.wrap(data);
311
312 bb.put((byte) (((this.version & 0xf) << 4) | (this.headerLength & 0xf)));
313 bb.put(this.diffServ);
314 bb.putShort(this.totalLength);
315 bb.putShort(this.identification);
316 bb.putShort((short) (((this.flags & 0x7) << 13) | (this.fragmentOffset & 0x1fff)));
317 bb.put(this.ttl);
318 bb.put(this.protocol);
319 bb.putShort(this.checksum);
320 bb.putInt(this.sourceAddress);
321 bb.putInt(this.destinationAddress);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700322 if (this.options != null) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800323 bb.put(this.options);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700324 }
325 if (payloadData != null) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800326 bb.put(payloadData);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700327 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800328
329 // compute checksum if needed
330 if (this.checksum == 0) {
331 bb.rewind();
332 int accumulation = 0;
333 for (int i = 0; i < this.headerLength * 2; ++i) {
334 accumulation += 0xffff & bb.getShort();
335 }
336 accumulation = ((accumulation >> 16) & 0xffff)
337 + (accumulation & 0xffff);
338 this.checksum = (short) (~accumulation & 0xffff);
339 bb.putShort(10, this.checksum);
340 }
341 return data;
342 }
343
344 @Override
345 public IPacket deserialize(byte[] data, int offset, int length) {
346 ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
347 short sscratch;
348
349 this.version = bb.get();
350 this.headerLength = (byte) (this.version & 0xf);
351 this.version = (byte) ((this.version >> 4) & 0xf);
352 this.diffServ = bb.get();
353 this.totalLength = bb.getShort();
354 this.identification = bb.getShort();
355 sscratch = bb.getShort();
356 this.flags = (byte) ((sscratch >> 13) & 0x7);
357 this.fragmentOffset = (short) (sscratch & 0x1fff);
358 this.ttl = bb.get();
359 this.protocol = bb.get();
360 this.checksum = bb.getShort();
361 this.sourceAddress = bb.getInt();
362 this.destinationAddress = bb.getInt();
363
364 if (this.headerLength > 5) {
365 int optionsLength = (this.headerLength - 5) * 4;
366 this.options = new byte[optionsLength];
367 bb.get(this.options);
368 }
369
370 IPacket payload;
Pavlin Radoslavov608fac32014-04-09 12:40:24 -0700371 if (IPv4.PROTOCOL_CLASS_MAP.containsKey(this.protocol)) {
372 Class<? extends IPacket> clazz = IPv4.PROTOCOL_CLASS_MAP.get(this.protocol);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800373 try {
374 payload = clazz.newInstance();
375 } catch (Exception e) {
376 throw new RuntimeException("Error parsing payload for IPv4 packet", e);
377 }
378 } else {
379 payload = new Data();
380 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700381 this.payload = payload.deserialize(data, bb.position(), bb.limit() - bb.position());
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800382 this.payload.setParent(this);
383
Ray Milkeyb29e6262014-04-09 16:02:14 -0700384 if (this.totalLength != length) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800385 this.isTruncated = true;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700386 } else {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800387 this.isTruncated = false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700388 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800389
390 return this;
391 }
392
393 /**
394 * Accepts an IPv4 address of the form xxx.xxx.xxx.xxx, ie 192.168.0.1 and
395 * returns the corresponding 32 bit integer.
Ray Milkey269ffb92014-04-03 14:43:30 -0700396 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800397 * @param ipAddress
398 * @return
399 */
400 public static int toIPv4Address(String ipAddress) {
Ray Milkeyb29e6262014-04-09 16:02:14 -0700401 if (ipAddress == null) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800402 throw new IllegalArgumentException("Specified IPv4 address must" +
Ray Milkey269ffb92014-04-03 14:43:30 -0700403 "contain 4 sets of numerical digits separated by periods");
Ray Milkeyb29e6262014-04-09 16:02:14 -0700404 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800405 String[] octets = ipAddress.split("\\.");
Ray Milkeyb29e6262014-04-09 16:02:14 -0700406 if (octets.length != 4) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800407 throw new IllegalArgumentException("Specified IPv4 address must" +
Ray Milkey269ffb92014-04-03 14:43:30 -0700408 "contain 4 sets of numerical digits separated by periods");
Ray Milkeyb29e6262014-04-09 16:02:14 -0700409 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800410
411 int result = 0;
412 for (int i = 0; i < 4; ++i) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700413 result |= Integer.valueOf(octets[i]) << ((3 - i) * 8);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800414 }
415 return result;
416 }
417
418 /**
419 * Accepts an IPv4 address in a byte array and returns the corresponding
420 * 32-bit integer value.
Ray Milkey269ffb92014-04-03 14:43:30 -0700421 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800422 * @param ipAddress
423 * @return
424 */
425 public static int toIPv4Address(byte[] ipAddress) {
426 int ip = 0;
427 for (int i = 0; i < 4; i++) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700428 int t = (ipAddress[i] & 0xff) << ((3 - i) * 8);
429 ip |= t;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800430 }
431 return ip;
432 }
433
434 /**
435 * Accepts an IPv4 address and returns of string of the form xxx.xxx.xxx.xxx
Ray Milkeyb41100a2014-04-10 10:42:15 -0700436 * ie 192.168.0.1.
Ray Milkey269ffb92014-04-03 14:43:30 -0700437 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800438 * @param ipAddress
439 * @return
440 */
441 public static String fromIPv4Address(int ipAddress) {
442 StringBuffer sb = new StringBuffer();
443 int result = 0;
444 for (int i = 0; i < 4; ++i) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700445 result = (ipAddress >> ((3 - i) * 8)) & 0xff;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800446 sb.append(Integer.valueOf(result).toString());
Ray Milkeyb29e6262014-04-09 16:02:14 -0700447 if (i != 3) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800448 sb.append(".");
Ray Milkeyb29e6262014-04-09 16:02:14 -0700449 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800450 }
451 return sb.toString();
452 }
453
454 /**
455 * Accepts a collection of IPv4 addresses as integers and returns a single
456 * String useful in toString method's containing collections of IP
457 * addresses.
Ray Milkey269ffb92014-04-03 14:43:30 -0700458 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800459 * @param ipAddresses collection
460 * @return
461 */
462 public static String fromIPv4AddressCollection(Collection<Integer> ipAddresses) {
Ray Milkeyb29e6262014-04-09 16:02:14 -0700463 if (ipAddresses == null) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800464 return "null";
Ray Milkeyb29e6262014-04-09 16:02:14 -0700465 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800466 StringBuffer sb = new StringBuffer();
467 sb.append("[");
468 for (Integer ip : ipAddresses) {
469 sb.append(fromIPv4Address(ip));
470 sb.append(",");
471 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700472 sb.replace(sb.length() - 1, sb.length(), "]");
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800473 return sb.toString();
474 }
475
476 /**
477 * Accepts an IPv4 address of the form xxx.xxx.xxx.xxx, ie 192.168.0.1 and
478 * returns the corresponding byte array.
Ray Milkey269ffb92014-04-03 14:43:30 -0700479 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800480 * @param ipAddress The IP address in the form xx.xxx.xxx.xxx.
481 * @return The IP address separated into bytes
482 */
483 public static byte[] toIPv4AddressBytes(String ipAddress) {
484 String[] octets = ipAddress.split("\\.");
Ray Milkeyb29e6262014-04-09 16:02:14 -0700485 if (octets.length != 4) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800486 throw new IllegalArgumentException("Specified IPv4 address must" +
Ray Milkey269ffb92014-04-03 14:43:30 -0700487 "contain 4 sets of numerical digits separated by periods");
Ray Milkeyb29e6262014-04-09 16:02:14 -0700488 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800489
490 byte[] result = new byte[4];
491 for (int i = 0; i < 4; ++i) {
492 result[i] = Integer.valueOf(octets[i]).byteValue();
493 }
494 return result;
495 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700496
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800497 /**
498 * Accepts an IPv4 address in the form of an integer and
499 * returns the corresponding byte array.
Ray Milkey269ffb92014-04-03 14:43:30 -0700500 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800501 * @param ipAddress The IP address as an integer.
502 * @return The IP address separated into bytes.
503 */
504 public static byte[] toIPv4AddressBytes(int ipAddress) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700505 return new byte[]{
506 (byte) (ipAddress >>> 24),
507 (byte) (ipAddress >>> 16),
508 (byte) (ipAddress >>> 8),
509 (byte) ipAddress};
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800510 }
511
512 /* (non-Javadoc)
513 * @see java.lang.Object#hashCode()
514 */
515 @Override
516 public int hashCode() {
517 final int prime = 2521;
518 int result = super.hashCode();
519 result = prime * result + checksum;
520 result = prime * result + destinationAddress;
521 result = prime * result + diffServ;
522 result = prime * result + flags;
523 result = prime * result + fragmentOffset;
524 result = prime * result + headerLength;
525 result = prime * result + identification;
526 result = prime * result + Arrays.hashCode(options);
527 result = prime * result + protocol;
528 result = prime * result + sourceAddress;
529 result = prime * result + totalLength;
530 result = prime * result + ttl;
531 result = prime * result + version;
532 return result;
533 }
534
535 /* (non-Javadoc)
536 * @see java.lang.Object#equals(java.lang.Object)
537 */
538 @Override
539 public boolean equals(Object obj) {
Ray Milkeyb29e6262014-04-09 16:02:14 -0700540 if (this == obj) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800541 return true;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700542 }
543 if (!super.equals(obj)) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800544 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700545 }
546 if (!(obj instanceof IPv4)) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800547 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700548 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800549 IPv4 other = (IPv4) obj;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700550 if (checksum != other.checksum) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800551 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700552 }
553 if (destinationAddress != other.destinationAddress) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800554 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700555 }
556 if (diffServ != other.diffServ) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800557 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700558 }
559 if (flags != other.flags) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800560 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700561 }
562 if (fragmentOffset != other.fragmentOffset) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800563 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700564 }
565 if (headerLength != other.headerLength) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800566 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700567 }
568 if (identification != other.identification) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800569 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700570 }
571 if (!Arrays.equals(options, other.options)) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800572 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700573 }
574 if (protocol != other.protocol) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800575 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700576 }
577 if (sourceAddress != other.sourceAddress) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800578 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700579 }
580 if (totalLength != other.totalLength) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800581 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700582 }
583 if (ttl != other.ttl) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800584 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700585 }
586 if (version != other.version) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800587 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700588 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800589 return true;
590 }
591}