blob: 495e283c5c7c7d23c6c573fcb6b315f01cfa2d7f [file] [log] [blame]
Rusty Eddy1da61a22015-09-01 00:48:58 +00001/*
2 * Copyright 2015 Open Networking Laboratory
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.onlab.packet;
17
18import java.nio.ByteBuffer;
19import static org.onlab.packet.PacketUtils.checkBufferLength;
20
21public class IGMPMembership extends IGMPGroup {
22
23 public static final byte MODE_IS_INCLUDE = 0x1;
24 public static final byte MODE_IS_EXCLUDE = 0x2;
25 public static final byte CHANGE_TO_INCLUDE_MODE = 0x3;
26 public static final byte CHANGE_TO_EXCLUDE_MODE = 0x4;
27 public static final byte ALLOW_NEW_SOURCES = 0x5;
28 public static final byte BLOCK_OLD_SOURCES = 0x6;
29
30 private final int minGroupRecordLen = Ip4Address.BYTE_LENGTH + 4;
31
32 protected byte recordType;
33 protected byte auxDataLength = 0;
34 protected byte[] auxData;
35
36 /**
37 * Constructor initialized with a multicast group address.
38 *
39 * @param gaddr A multicast group address.
40 */
41 public IGMPMembership(Ip4Address gaddr) {
42 super(gaddr, 0);
43 }
44
45 /**
46 * Default constructor.
47 */
48 public IGMPMembership() {
49 super();
50 }
51
52 /**
53 * Serialize this Membership Report.
54 *
55 * @param bb the ByteBuffer to write into, positioned at the next spot to be written to.
56 * @return serialized IGMP message.
57 */
58 @Override
59 public byte[] serialize(ByteBuffer bb) {
60
61 bb.put(recordType);
62 bb.put(auxDataLength); // reserved
63 bb.putShort((short) sources.size());
64 bb.put(gaddr.toOctets());
65 for (IpAddress ipaddr : sources) {
66 bb.put(ipaddr.toOctets());
67 }
68
69 if (auxDataLength > 0) {
70 bb.put(auxData);
71 }
72
73 return bb.array();
74 }
75
76 /**
77 * Deserialize the IGMP Membership report packet.
78 *
79 * @param bb the ByteBuffer wrapping the serialized message. The position of the
80 * ByteBuffer should be pointing at the head of either message type.
Ray Milkey9b36d812015-09-09 15:24:54 -070081 * @return IGMP Group
82 * @throws DeserializationException if deserialization fails
Rusty Eddy1da61a22015-09-01 00:48:58 +000083 */
84 public IGMPGroup deserialize(ByteBuffer bb) throws DeserializationException {
85
86 // Make sure there is enough buffer to read the header,
87 // including the number of sources
88 checkBufferLength(bb.remaining(), 0, minGroupRecordLen);
89 recordType = bb.get();
90 auxDataLength = bb.get();
91 int nsrcs = bb.getShort();
92
93 gaddr = Ip4Address.valueOf(bb.getInt());
94
95 // Make sure we have enough buffer to hold all of these sources
96 checkBufferLength(bb.remaining(), 0, Ip4Address.BYTE_LENGTH * nsrcs);
97 for (; nsrcs > 0; nsrcs--) {
98 Ip4Address src = Ip4Address.valueOf(bb.getInt());
99 this.sources.add(src);
100 }
101
102 if (auxDataLength > 0) {
103 auxData = new byte[auxDataLength];
104 bb.get(auxData, 0, auxDataLength);
105 }
106 return this;
107 }
108
109 /*
110 * (non-Javadoc)
111 *
112 * @see java.lang.Object#equals()
113 */
114 public boolean equals(Object obj) {
115 if (this == obj) {
116 return true;
117 }
118 if (!(obj instanceof IGMPMembership)) {
119 return false;
120 }
121 IGMPMembership other = (IGMPMembership) obj;
122
123 if (!this.gaddr.equals(other.gaddr)) {
124 return false;
125 }
126 if (this.recordType != other.recordType) {
127 return false;
128 }
129 if (this.auxDataLength != other.auxDataLength) {
130 return false;
131 }
132 if (this.sources.size() != other.sources.size()) {
133 return false;
134 }
135 // TODO: make these tolerant of order
136 if (!this.sources.equals(other.sources)) {
137 return false;
138 }
139
140 return true;
141 }
142
143 /*
144 * (non-Javadoc)
145 *
146 * @see java.lang.Object#hashCode()
147 */
148 @Override
149 public int hashCode() {
150 final int prime = 2521;
151 int result = super.hashCode();
152 result = prime * result + this.gaddr.hashCode();
153 result = prime * result + this.recordType;
154 result = prime * result + this.auxDataLength;
155 result = prime * result + this.sources.hashCode();
156 return result;
157 }
Ray Milkey9b36d812015-09-09 15:24:54 -0700158}