blob: fbb91abab862f5041d325704676085cacb5c8bc0 [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
29/**
30 * @author David Erickson (daviderickson@cs.stanford.edu)
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080031 */
32public class IPv4 extends BasePacket {
Ray Milkey269ffb92014-04-03 14:43:30 -070033 public static final int ADDRESS_LENGTH = 4;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080034 public static final byte PROTOCOL_ICMP = 0x1;
35 public static final byte PROTOCOL_TCP = 0x6;
36 public static final byte PROTOCOL_UDP = 0x11;
Pavlin Radoslavov608fac32014-04-09 12:40:24 -070037 public static final Map<Byte, Class<? extends IPacket>> PROTOCOL_CLASS_MAP;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080038
39 static {
Pavlin Radoslavov608fac32014-04-09 12:40:24 -070040 PROTOCOL_CLASS_MAP = new HashMap<Byte, Class<? extends IPacket>>();
41 PROTOCOL_CLASS_MAP.put(PROTOCOL_ICMP, ICMP.class);
42 PROTOCOL_CLASS_MAP.put(PROTOCOL_TCP, TCP.class);
43 PROTOCOL_CLASS_MAP.put(PROTOCOL_UDP, UDP.class);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080044 }
45
46 protected byte version;
47 protected byte headerLength;
48 protected byte diffServ;
49 protected short totalLength;
50 protected short identification;
51 protected byte flags;
52 protected short fragmentOffset;
53 protected byte ttl;
54 protected byte protocol;
55 protected short checksum;
56 protected int sourceAddress;
57 protected int destinationAddress;
58 protected byte[] options;
59
60 protected boolean isTruncated;
61
62 /**
63 * Default constructor that sets the version to 4.
64 */
65 public IPv4() {
66 super();
67 this.version = 4;
68 isTruncated = false;
69 }
70
71 /**
72 * @return the version
73 */
74 public byte getVersion() {
75 return version;
76 }
77
78 /**
79 * @param version the version to set
80 */
81 public IPv4 setVersion(byte version) {
82 this.version = version;
83 return this;
84 }
85
86 /**
87 * @return the headerLength
88 */
89 public byte getHeaderLength() {
90 return headerLength;
91 }
92
93 /**
94 * @return the diffServ
95 */
96 public byte getDiffServ() {
97 return diffServ;
98 }
99
100 /**
101 * @param diffServ the diffServ to set
102 */
103 public IPv4 setDiffServ(byte diffServ) {
104 this.diffServ = diffServ;
105 return this;
106 }
107
108 /**
109 * @return the totalLength
110 */
111 public short getTotalLength() {
112 return totalLength;
113 }
114
115 /**
116 * @return the identification
117 */
118 public short getIdentification() {
119 return identification;
120 }
121
122 public boolean isTruncated() {
123 return isTruncated;
124 }
125
126 public void setTruncated(boolean isTruncated) {
127 this.isTruncated = isTruncated;
128 }
129
130 /**
131 * @param identification the identification to set
132 */
133 public IPv4 setIdentification(short identification) {
134 this.identification = identification;
135 return this;
136 }
137
138 /**
139 * @return the flags
140 */
141 public byte getFlags() {
142 return flags;
143 }
144
145 /**
146 * @param flags the flags to set
147 */
148 public IPv4 setFlags(byte flags) {
149 this.flags = flags;
150 return this;
151 }
152
153 /**
154 * @return the fragmentOffset
155 */
156 public short getFragmentOffset() {
157 return fragmentOffset;
158 }
159
160 /**
161 * @param fragmentOffset the fragmentOffset to set
162 */
163 public IPv4 setFragmentOffset(short fragmentOffset) {
164 this.fragmentOffset = fragmentOffset;
165 return this;
166 }
167
168 /**
169 * @return the ttl
170 */
171 public byte getTtl() {
172 return ttl;
173 }
174
175 /**
176 * @param ttl the ttl to set
177 */
178 public IPv4 setTtl(byte ttl) {
179 this.ttl = ttl;
180 return this;
181 }
182
183 /**
184 * @return the protocol
185 */
186 public byte getProtocol() {
187 return protocol;
188 }
189
190 /**
191 * @param protocol the protocol to set
192 */
193 public IPv4 setProtocol(byte protocol) {
194 this.protocol = protocol;
195 return this;
196 }
197
198 /**
199 * @return the checksum
200 */
201 public short getChecksum() {
202 return checksum;
203 }
204
205 /**
206 * @param checksum the checksum to set
207 */
208 public IPv4 setChecksum(short checksum) {
209 this.checksum = checksum;
210 return this;
211 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700212
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800213 @Override
214 public void resetChecksum() {
215 this.checksum = 0;
216 super.resetChecksum();
217 }
218
219 /**
220 * @return the sourceAddress
221 */
222 public int getSourceAddress() {
223 return sourceAddress;
224 }
225
226 /**
227 * @param sourceAddress the sourceAddress to set
228 */
229 public IPv4 setSourceAddress(int sourceAddress) {
230 this.sourceAddress = sourceAddress;
231 return this;
232 }
233
234 /**
235 * @param sourceAddress the sourceAddress to set
236 */
237 public IPv4 setSourceAddress(String sourceAddress) {
238 this.sourceAddress = IPv4.toIPv4Address(sourceAddress);
239 return this;
240 }
241
242 /**
243 * @return the destinationAddress
244 */
245 public int getDestinationAddress() {
246 return destinationAddress;
247 }
248
249 /**
250 * @param destinationAddress the destinationAddress to set
251 */
252 public IPv4 setDestinationAddress(int destinationAddress) {
253 this.destinationAddress = destinationAddress;
254 return this;
255 }
256
257 /**
258 * @param destinationAddress the destinationAddress to set
259 */
260 public IPv4 setDestinationAddress(String destinationAddress) {
261 this.destinationAddress = IPv4.toIPv4Address(destinationAddress);
262 return this;
263 }
264
265 /**
266 * @return the options
267 */
268 public byte[] getOptions() {
Pavlin Radoslavov0a9d5c32014-04-15 17:45:23 -0700269 if (this.options == null) {
270 return null;
271 }
272 return this.options.clone();
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800273 }
274
275 /**
276 * @param options the options to set
277 */
278 public IPv4 setOptions(byte[] options) {
Ray Milkeyb29e6262014-04-09 16:02:14 -0700279 if (options != null && (options.length % 4) > 0) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800280 throw new IllegalArgumentException(
281 "Options length must be a multiple of 4");
Ray Milkeyb29e6262014-04-09 16:02:14 -0700282 }
Pavlin Radoslavov0a9d5c32014-04-15 17:45:23 -0700283 if (options == null) {
284 this.options = null;
285 } else {
286 this.options = options.clone();
287 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800288 return this;
289 }
290
291 /**
292 * Serializes the packet. Will compute and set the following fields if they
293 * are set to specific values at the time serialize is called:
Ray Milkey269ffb92014-04-03 14:43:30 -0700294 * -checksum : 0
295 * -headerLength : 0
296 * -totalLength : 0
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800297 */
298 public byte[] serialize() {
299 byte[] payloadData = null;
300 if (payload != null) {
301 payload.setParent(this);
302 payloadData = payload.serialize();
303 }
304
305 int optionsLength = 0;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700306 if (this.options != null) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800307 optionsLength = this.options.length / 4;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700308 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800309 this.headerLength = (byte) (5 + optionsLength);
310
311 this.totalLength = (short) (this.headerLength * 4 + ((payloadData == null) ? 0
312 : payloadData.length));
313
314 byte[] data = new byte[this.totalLength];
315 ByteBuffer bb = ByteBuffer.wrap(data);
316
317 bb.put((byte) (((this.version & 0xf) << 4) | (this.headerLength & 0xf)));
318 bb.put(this.diffServ);
319 bb.putShort(this.totalLength);
320 bb.putShort(this.identification);
321 bb.putShort((short) (((this.flags & 0x7) << 13) | (this.fragmentOffset & 0x1fff)));
322 bb.put(this.ttl);
323 bb.put(this.protocol);
324 bb.putShort(this.checksum);
325 bb.putInt(this.sourceAddress);
326 bb.putInt(this.destinationAddress);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700327 if (this.options != null) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800328 bb.put(this.options);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700329 }
330 if (payloadData != null) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800331 bb.put(payloadData);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700332 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800333
334 // compute checksum if needed
335 if (this.checksum == 0) {
336 bb.rewind();
337 int accumulation = 0;
338 for (int i = 0; i < this.headerLength * 2; ++i) {
339 accumulation += 0xffff & bb.getShort();
340 }
341 accumulation = ((accumulation >> 16) & 0xffff)
342 + (accumulation & 0xffff);
343 this.checksum = (short) (~accumulation & 0xffff);
344 bb.putShort(10, this.checksum);
345 }
346 return data;
347 }
348
349 @Override
350 public IPacket deserialize(byte[] data, int offset, int length) {
351 ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
352 short sscratch;
353
354 this.version = bb.get();
355 this.headerLength = (byte) (this.version & 0xf);
356 this.version = (byte) ((this.version >> 4) & 0xf);
357 this.diffServ = bb.get();
358 this.totalLength = bb.getShort();
359 this.identification = bb.getShort();
360 sscratch = bb.getShort();
361 this.flags = (byte) ((sscratch >> 13) & 0x7);
362 this.fragmentOffset = (short) (sscratch & 0x1fff);
363 this.ttl = bb.get();
364 this.protocol = bb.get();
365 this.checksum = bb.getShort();
366 this.sourceAddress = bb.getInt();
367 this.destinationAddress = bb.getInt();
368
369 if (this.headerLength > 5) {
370 int optionsLength = (this.headerLength - 5) * 4;
371 this.options = new byte[optionsLength];
372 bb.get(this.options);
373 }
374
375 IPacket payload;
Pavlin Radoslavov608fac32014-04-09 12:40:24 -0700376 if (IPv4.PROTOCOL_CLASS_MAP.containsKey(this.protocol)) {
377 Class<? extends IPacket> clazz = IPv4.PROTOCOL_CLASS_MAP.get(this.protocol);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800378 try {
379 payload = clazz.newInstance();
380 } catch (Exception e) {
381 throw new RuntimeException("Error parsing payload for IPv4 packet", e);
382 }
383 } else {
384 payload = new Data();
385 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700386 this.payload = payload.deserialize(data, bb.position(), bb.limit() - bb.position());
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800387 this.payload.setParent(this);
388
Ray Milkeyb29e6262014-04-09 16:02:14 -0700389 if (this.totalLength != length) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800390 this.isTruncated = true;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700391 } else {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800392 this.isTruncated = false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700393 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800394
395 return this;
396 }
397
398 /**
399 * Accepts an IPv4 address of the form xxx.xxx.xxx.xxx, ie 192.168.0.1 and
400 * returns the corresponding 32 bit integer.
Ray Milkey269ffb92014-04-03 14:43:30 -0700401 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800402 * @param ipAddress
403 * @return
404 */
405 public static int toIPv4Address(String ipAddress) {
Ray Milkeyb29e6262014-04-09 16:02:14 -0700406 if (ipAddress == null) {
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 String[] octets = ipAddress.split("\\.");
Ray Milkeyb29e6262014-04-09 16:02:14 -0700411 if (octets.length != 4) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800412 throw new IllegalArgumentException("Specified IPv4 address must" +
Ray Milkey269ffb92014-04-03 14:43:30 -0700413 "contain 4 sets of numerical digits separated by periods");
Ray Milkeyb29e6262014-04-09 16:02:14 -0700414 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800415
416 int result = 0;
417 for (int i = 0; i < 4; ++i) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700418 result |= Integer.valueOf(octets[i]) << ((3 - i) * 8);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800419 }
420 return result;
421 }
422
423 /**
424 * Accepts an IPv4 address in a byte array and returns the corresponding
425 * 32-bit integer value.
Ray Milkey269ffb92014-04-03 14:43:30 -0700426 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800427 * @param ipAddress
428 * @return
429 */
430 public static int toIPv4Address(byte[] ipAddress) {
431 int ip = 0;
432 for (int i = 0; i < 4; i++) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700433 int t = (ipAddress[i] & 0xff) << ((3 - i) * 8);
434 ip |= t;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800435 }
436 return ip;
437 }
438
439 /**
440 * Accepts an IPv4 address and returns of string of the form xxx.xxx.xxx.xxx
Ray Milkeyb41100a2014-04-10 10:42:15 -0700441 * ie 192.168.0.1.
Ray Milkey269ffb92014-04-03 14:43:30 -0700442 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800443 * @param ipAddress
444 * @return
445 */
446 public static String fromIPv4Address(int ipAddress) {
447 StringBuffer sb = new StringBuffer();
448 int result = 0;
449 for (int i = 0; i < 4; ++i) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700450 result = (ipAddress >> ((3 - i) * 8)) & 0xff;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800451 sb.append(Integer.valueOf(result).toString());
Ray Milkeyb29e6262014-04-09 16:02:14 -0700452 if (i != 3) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800453 sb.append(".");
Ray Milkeyb29e6262014-04-09 16:02:14 -0700454 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800455 }
456 return sb.toString();
457 }
458
459 /**
460 * Accepts a collection of IPv4 addresses as integers and returns a single
461 * String useful in toString method's containing collections of IP
462 * addresses.
Ray Milkey269ffb92014-04-03 14:43:30 -0700463 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800464 * @param ipAddresses collection
465 * @return
466 */
467 public static String fromIPv4AddressCollection(Collection<Integer> ipAddresses) {
Ray Milkeyb29e6262014-04-09 16:02:14 -0700468 if (ipAddresses == null) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800469 return "null";
Ray Milkeyb29e6262014-04-09 16:02:14 -0700470 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800471 StringBuffer sb = new StringBuffer();
472 sb.append("[");
473 for (Integer ip : ipAddresses) {
474 sb.append(fromIPv4Address(ip));
475 sb.append(",");
476 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700477 sb.replace(sb.length() - 1, sb.length(), "]");
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800478 return sb.toString();
479 }
480
481 /**
482 * Accepts an IPv4 address of the form xxx.xxx.xxx.xxx, ie 192.168.0.1 and
483 * returns the corresponding byte array.
Ray Milkey269ffb92014-04-03 14:43:30 -0700484 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800485 * @param ipAddress The IP address in the form xx.xxx.xxx.xxx.
486 * @return The IP address separated into bytes
487 */
488 public static byte[] toIPv4AddressBytes(String ipAddress) {
489 String[] octets = ipAddress.split("\\.");
Ray Milkeyb29e6262014-04-09 16:02:14 -0700490 if (octets.length != 4) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800491 throw new IllegalArgumentException("Specified IPv4 address must" +
Ray Milkey269ffb92014-04-03 14:43:30 -0700492 "contain 4 sets of numerical digits separated by periods");
Ray Milkeyb29e6262014-04-09 16:02:14 -0700493 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800494
495 byte[] result = new byte[4];
496 for (int i = 0; i < 4; ++i) {
497 result[i] = Integer.valueOf(octets[i]).byteValue();
498 }
499 return result;
500 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700501
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800502 /**
503 * Accepts an IPv4 address in the form of an integer and
504 * returns the corresponding byte array.
Ray Milkey269ffb92014-04-03 14:43:30 -0700505 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800506 * @param ipAddress The IP address as an integer.
507 * @return The IP address separated into bytes.
508 */
509 public static byte[] toIPv4AddressBytes(int ipAddress) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700510 return new byte[]{
511 (byte) (ipAddress >>> 24),
512 (byte) (ipAddress >>> 16),
513 (byte) (ipAddress >>> 8),
514 (byte) ipAddress};
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800515 }
516
517 /* (non-Javadoc)
518 * @see java.lang.Object#hashCode()
519 */
520 @Override
521 public int hashCode() {
522 final int prime = 2521;
523 int result = super.hashCode();
524 result = prime * result + checksum;
525 result = prime * result + destinationAddress;
526 result = prime * result + diffServ;
527 result = prime * result + flags;
528 result = prime * result + fragmentOffset;
529 result = prime * result + headerLength;
530 result = prime * result + identification;
531 result = prime * result + Arrays.hashCode(options);
532 result = prime * result + protocol;
533 result = prime * result + sourceAddress;
534 result = prime * result + totalLength;
535 result = prime * result + ttl;
536 result = prime * result + version;
537 return result;
538 }
539
540 /* (non-Javadoc)
541 * @see java.lang.Object#equals(java.lang.Object)
542 */
543 @Override
544 public boolean equals(Object obj) {
Ray Milkeyb29e6262014-04-09 16:02:14 -0700545 if (this == obj) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800546 return true;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700547 }
548 if (!super.equals(obj)) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800549 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700550 }
551 if (!(obj instanceof IPv4)) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800552 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700553 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800554 IPv4 other = (IPv4) obj;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700555 if (checksum != other.checksum) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800556 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700557 }
558 if (destinationAddress != other.destinationAddress) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800559 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700560 }
561 if (diffServ != other.diffServ) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800562 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700563 }
564 if (flags != other.flags) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800565 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700566 }
567 if (fragmentOffset != other.fragmentOffset) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800568 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700569 }
570 if (headerLength != other.headerLength) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800571 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700572 }
573 if (identification != other.identification) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800574 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700575 }
576 if (!Arrays.equals(options, other.options)) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800577 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700578 }
579 if (protocol != other.protocol) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800580 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700581 }
582 if (sourceAddress != other.sourceAddress) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800583 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700584 }
585 if (totalLength != other.totalLength) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800586 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700587 }
588 if (ttl != other.ttl) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800589 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700590 }
591 if (version != other.version) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800592 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700593 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800594 return true;
595 }
596}