blob: 1ce9eec61140f11dc267df9610a08ef4d53751dc [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 */
Yuta HIGUCHI0fe749a2014-05-27 09:35:16 -0700293 @Override
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800294 public byte[] serialize() {
295 byte[] payloadData = null;
296 if (payload != null) {
297 payload.setParent(this);
298 payloadData = payload.serialize();
299 }
300
301 int optionsLength = 0;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700302 if (this.options != null) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800303 optionsLength = this.options.length / 4;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700304 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800305 this.headerLength = (byte) (5 + optionsLength);
306
307 this.totalLength = (short) (this.headerLength * 4 + ((payloadData == null) ? 0
308 : payloadData.length));
309
310 byte[] data = new byte[this.totalLength];
311 ByteBuffer bb = ByteBuffer.wrap(data);
312
313 bb.put((byte) (((this.version & 0xf) << 4) | (this.headerLength & 0xf)));
314 bb.put(this.diffServ);
315 bb.putShort(this.totalLength);
316 bb.putShort(this.identification);
317 bb.putShort((short) (((this.flags & 0x7) << 13) | (this.fragmentOffset & 0x1fff)));
318 bb.put(this.ttl);
319 bb.put(this.protocol);
320 bb.putShort(this.checksum);
321 bb.putInt(this.sourceAddress);
322 bb.putInt(this.destinationAddress);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700323 if (this.options != null) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800324 bb.put(this.options);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700325 }
326 if (payloadData != null) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800327 bb.put(payloadData);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700328 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800329
330 // compute checksum if needed
331 if (this.checksum == 0) {
332 bb.rewind();
333 int accumulation = 0;
334 for (int i = 0; i < this.headerLength * 2; ++i) {
335 accumulation += 0xffff & bb.getShort();
336 }
337 accumulation = ((accumulation >> 16) & 0xffff)
338 + (accumulation & 0xffff);
339 this.checksum = (short) (~accumulation & 0xffff);
340 bb.putShort(10, this.checksum);
341 }
342 return data;
343 }
344
345 @Override
346 public IPacket deserialize(byte[] data, int offset, int length) {
347 ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
348 short sscratch;
349
350 this.version = bb.get();
351 this.headerLength = (byte) (this.version & 0xf);
352 this.version = (byte) ((this.version >> 4) & 0xf);
353 this.diffServ = bb.get();
354 this.totalLength = bb.getShort();
355 this.identification = bb.getShort();
356 sscratch = bb.getShort();
357 this.flags = (byte) ((sscratch >> 13) & 0x7);
358 this.fragmentOffset = (short) (sscratch & 0x1fff);
359 this.ttl = bb.get();
360 this.protocol = bb.get();
361 this.checksum = bb.getShort();
362 this.sourceAddress = bb.getInt();
363 this.destinationAddress = bb.getInt();
364
365 if (this.headerLength > 5) {
366 int optionsLength = (this.headerLength - 5) * 4;
367 this.options = new byte[optionsLength];
368 bb.get(this.options);
369 }
370
371 IPacket payload;
Pavlin Radoslavov608fac32014-04-09 12:40:24 -0700372 if (IPv4.PROTOCOL_CLASS_MAP.containsKey(this.protocol)) {
373 Class<? extends IPacket> clazz = IPv4.PROTOCOL_CLASS_MAP.get(this.protocol);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800374 try {
375 payload = clazz.newInstance();
376 } catch (Exception e) {
377 throw new RuntimeException("Error parsing payload for IPv4 packet", e);
378 }
379 } else {
380 payload = new Data();
381 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700382 this.payload = payload.deserialize(data, bb.position(), bb.limit() - bb.position());
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800383 this.payload.setParent(this);
384
Ray Milkeyb29e6262014-04-09 16:02:14 -0700385 if (this.totalLength != length) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800386 this.isTruncated = true;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700387 } else {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800388 this.isTruncated = false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700389 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800390
391 return this;
392 }
393
394 /**
395 * Accepts an IPv4 address of the form xxx.xxx.xxx.xxx, ie 192.168.0.1 and
396 * returns the corresponding 32 bit integer.
Ray Milkey269ffb92014-04-03 14:43:30 -0700397 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800398 * @param ipAddress
399 * @return
400 */
401 public static int toIPv4Address(String ipAddress) {
Ray Milkeyb29e6262014-04-09 16:02:14 -0700402 if (ipAddress == null) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800403 throw new IllegalArgumentException("Specified IPv4 address must" +
Ray Milkey269ffb92014-04-03 14:43:30 -0700404 "contain 4 sets of numerical digits separated by periods");
Ray Milkeyb29e6262014-04-09 16:02:14 -0700405 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800406 String[] octets = ipAddress.split("\\.");
Ray Milkeyb29e6262014-04-09 16:02:14 -0700407 if (octets.length != 4) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800408 throw new IllegalArgumentException("Specified IPv4 address must" +
Ray Milkey269ffb92014-04-03 14:43:30 -0700409 "contain 4 sets of numerical digits separated by periods");
Ray Milkeyb29e6262014-04-09 16:02:14 -0700410 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800411
412 int result = 0;
413 for (int i = 0; i < 4; ++i) {
Yuta HIGUCHI0fe749a2014-05-27 09:35:16 -0700414 result |= Integer.parseInt(octets[i]) << ((3 - i) * 8);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800415 }
416 return result;
417 }
418
419 /**
420 * Accepts an IPv4 address in a byte array and returns the corresponding
421 * 32-bit integer value.
Ray Milkey269ffb92014-04-03 14:43:30 -0700422 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800423 * @param ipAddress
424 * @return
425 */
426 public static int toIPv4Address(byte[] ipAddress) {
427 int ip = 0;
428 for (int i = 0; i < 4; i++) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700429 int t = (ipAddress[i] & 0xff) << ((3 - i) * 8);
430 ip |= t;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800431 }
432 return ip;
433 }
434
435 /**
436 * Accepts an IPv4 address and returns of string of the form xxx.xxx.xxx.xxx
Ray Milkeyb41100a2014-04-10 10:42:15 -0700437 * ie 192.168.0.1.
Ray Milkey269ffb92014-04-03 14:43:30 -0700438 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800439 * @param ipAddress
440 * @return
441 */
442 public static String fromIPv4Address(int ipAddress) {
443 StringBuffer sb = new StringBuffer();
444 int result = 0;
445 for (int i = 0; i < 4; ++i) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700446 result = (ipAddress >> ((3 - i) * 8)) & 0xff;
Yuta HIGUCHI0fe749a2014-05-27 09:35:16 -0700447 sb.append(Integer.toString(result));
Ray Milkeyb29e6262014-04-09 16:02:14 -0700448 if (i != 3) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800449 sb.append(".");
Ray Milkeyb29e6262014-04-09 16:02:14 -0700450 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800451 }
452 return sb.toString();
453 }
454
455 /**
456 * Accepts a collection of IPv4 addresses as integers and returns a single
457 * String useful in toString method's containing collections of IP
458 * addresses.
Ray Milkey269ffb92014-04-03 14:43:30 -0700459 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800460 * @param ipAddresses collection
461 * @return
462 */
463 public static String fromIPv4AddressCollection(Collection<Integer> ipAddresses) {
Ray Milkeyb29e6262014-04-09 16:02:14 -0700464 if (ipAddresses == null) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800465 return "null";
Ray Milkeyb29e6262014-04-09 16:02:14 -0700466 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800467 StringBuffer sb = new StringBuffer();
468 sb.append("[");
469 for (Integer ip : ipAddresses) {
470 sb.append(fromIPv4Address(ip));
471 sb.append(",");
472 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700473 sb.replace(sb.length() - 1, sb.length(), "]");
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800474 return sb.toString();
475 }
476
477 /**
478 * Accepts an IPv4 address of the form xxx.xxx.xxx.xxx, ie 192.168.0.1 and
479 * returns the corresponding byte array.
Ray Milkey269ffb92014-04-03 14:43:30 -0700480 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800481 * @param ipAddress The IP address in the form xx.xxx.xxx.xxx.
482 * @return The IP address separated into bytes
483 */
484 public static byte[] toIPv4AddressBytes(String ipAddress) {
485 String[] octets = ipAddress.split("\\.");
Ray Milkeyb29e6262014-04-09 16:02:14 -0700486 if (octets.length != 4) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800487 throw new IllegalArgumentException("Specified IPv4 address must" +
Ray Milkey269ffb92014-04-03 14:43:30 -0700488 "contain 4 sets of numerical digits separated by periods");
Ray Milkeyb29e6262014-04-09 16:02:14 -0700489 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800490
491 byte[] result = new byte[4];
492 for (int i = 0; i < 4; ++i) {
493 result[i] = Integer.valueOf(octets[i]).byteValue();
494 }
495 return result;
496 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700497
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800498 /**
499 * Accepts an IPv4 address in the form of an integer and
500 * returns the corresponding byte array.
Ray Milkey269ffb92014-04-03 14:43:30 -0700501 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800502 * @param ipAddress The IP address as an integer.
503 * @return The IP address separated into bytes.
504 */
505 public static byte[] toIPv4AddressBytes(int ipAddress) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700506 return new byte[]{
507 (byte) (ipAddress >>> 24),
508 (byte) (ipAddress >>> 16),
509 (byte) (ipAddress >>> 8),
510 (byte) ipAddress};
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800511 }
512
513 /* (non-Javadoc)
514 * @see java.lang.Object#hashCode()
515 */
516 @Override
517 public int hashCode() {
518 final int prime = 2521;
519 int result = super.hashCode();
520 result = prime * result + checksum;
521 result = prime * result + destinationAddress;
522 result = prime * result + diffServ;
523 result = prime * result + flags;
524 result = prime * result + fragmentOffset;
525 result = prime * result + headerLength;
526 result = prime * result + identification;
527 result = prime * result + Arrays.hashCode(options);
528 result = prime * result + protocol;
529 result = prime * result + sourceAddress;
530 result = prime * result + totalLength;
531 result = prime * result + ttl;
532 result = prime * result + version;
533 return result;
534 }
535
536 /* (non-Javadoc)
537 * @see java.lang.Object#equals(java.lang.Object)
538 */
539 @Override
540 public boolean equals(Object obj) {
Ray Milkeyb29e6262014-04-09 16:02:14 -0700541 if (this == obj) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800542 return true;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700543 }
544 if (!super.equals(obj)) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800545 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700546 }
547 if (!(obj instanceof IPv4)) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800548 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700549 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800550 IPv4 other = (IPv4) obj;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700551 if (checksum != other.checksum) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800552 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700553 }
554 if (destinationAddress != other.destinationAddress) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800555 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700556 }
557 if (diffServ != other.diffServ) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800558 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700559 }
560 if (flags != other.flags) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800561 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700562 }
563 if (fragmentOffset != other.fragmentOffset) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800564 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700565 }
566 if (headerLength != other.headerLength) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800567 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700568 }
569 if (identification != other.identification) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800570 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700571 }
572 if (!Arrays.equals(options, other.options)) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800573 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700574 }
575 if (protocol != other.protocol) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800576 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700577 }
578 if (sourceAddress != other.sourceAddress) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800579 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700580 }
581 if (totalLength != other.totalLength) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800582 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700583 }
584 if (ttl != other.ttl) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800585 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700586 }
587 if (version != other.version) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800588 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700589 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800590 return true;
591 }
592}