Jonathan Hart
Committed by Gerrit Code Review

Calculate IGMP checksum and use more reasonble max response time.

Also made IGMP properties configurable at runtime.

Change-Id: I98b40a43a0c17b7bf21f1bd622032c64d7434214
...@@ -138,7 +138,9 @@ public class CordMcast { ...@@ -138,7 +138,9 @@ public class CordMcast {
138 private String fabricOnosUrl; 138 private String fabricOnosUrl;
139 139
140 @Activate 140 @Activate
141 - public void activate() { 141 + public void activate(ComponentContext context) {
142 + modified(context);
143 +
142 appId = coreService.registerApplication("org.onosproject.cordmcast"); 144 appId = coreService.registerApplication("org.onosproject.cordmcast");
143 componentConfigService.registerProperties(getClass()); 145 componentConfigService.registerProperties(getClass());
144 mcastService.addListener(listener); 146 mcastService.addListener(listener);
......
...@@ -18,6 +18,7 @@ package org.onosproject.igmp; ...@@ -18,6 +18,7 @@ package org.onosproject.igmp;
18 import org.apache.felix.scr.annotations.Activate; 18 import org.apache.felix.scr.annotations.Activate;
19 import org.apache.felix.scr.annotations.Component; 19 import org.apache.felix.scr.annotations.Component;
20 import org.apache.felix.scr.annotations.Deactivate; 20 import org.apache.felix.scr.annotations.Deactivate;
21 +import org.apache.felix.scr.annotations.Modified;
21 import org.apache.felix.scr.annotations.Property; 22 import org.apache.felix.scr.annotations.Property;
22 import org.apache.felix.scr.annotations.Reference; 23 import org.apache.felix.scr.annotations.Reference;
23 import org.apache.felix.scr.annotations.ReferenceCardinality; 24 import org.apache.felix.scr.annotations.ReferenceCardinality;
...@@ -31,6 +32,8 @@ import org.onlab.packet.Ip4Address; ...@@ -31,6 +32,8 @@ import org.onlab.packet.Ip4Address;
31 import org.onlab.packet.IpAddress; 32 import org.onlab.packet.IpAddress;
32 import org.onlab.packet.IpPrefix; 33 import org.onlab.packet.IpPrefix;
33 import org.onlab.util.SafeRecurringTask; 34 import org.onlab.util.SafeRecurringTask;
35 +import org.onlab.util.Tools;
36 +import org.onosproject.cfg.ComponentConfigService;
34 import org.onosproject.core.ApplicationId; 37 import org.onosproject.core.ApplicationId;
35 import org.onosproject.core.CoreService; 38 import org.onosproject.core.CoreService;
36 import org.onosproject.net.ConnectPoint; 39 import org.onosproject.net.ConnectPoint;
...@@ -63,12 +66,15 @@ import org.onosproject.net.packet.PacketProcessor; ...@@ -63,12 +66,15 @@ import org.onosproject.net.packet.PacketProcessor;
63 import org.onosproject.net.packet.PacketService; 66 import org.onosproject.net.packet.PacketService;
64 import org.onosproject.olt.AccessDeviceConfig; 67 import org.onosproject.olt.AccessDeviceConfig;
65 import org.onosproject.olt.AccessDeviceData; 68 import org.onosproject.olt.AccessDeviceData;
69 +import org.osgi.service.component.ComponentContext;
66 import org.slf4j.Logger; 70 import org.slf4j.Logger;
67 71
68 import java.nio.ByteBuffer; 72 import java.nio.ByteBuffer;
69 import java.util.Collection; 73 import java.util.Collection;
74 +import java.util.Dictionary;
70 import java.util.List; 75 import java.util.List;
71 import java.util.Map; 76 import java.util.Map;
77 +import java.util.Properties;
72 import java.util.concurrent.ConcurrentHashMap; 78 import java.util.concurrent.ConcurrentHashMap;
73 import java.util.concurrent.Executors; 79 import java.util.concurrent.Executors;
74 import java.util.concurrent.ScheduledExecutorService; 80 import java.util.concurrent.ScheduledExecutorService;
...@@ -90,7 +96,7 @@ public class IgmpSnoop { ...@@ -90,7 +96,7 @@ public class IgmpSnoop {
90 private static final String DEST_IP = "224.0.0.1"; 96 private static final String DEST_IP = "224.0.0.1";
91 97
92 private static final int DEFAULT_QUERY_PERIOD_SECS = 60; 98 private static final int DEFAULT_QUERY_PERIOD_SECS = 60;
93 - private static final byte DEFAULT_IGMP_RESP_CODE = 0; 99 + private static final byte DEFAULT_IGMP_RESP_CODE = 100;
94 private static final String DEFAULT_MCAST_ADDR = "224.0.0.0/4"; 100 private static final String DEFAULT_MCAST_ADDR = "224.0.0.0/4";
95 101
96 @Property(name = "multicastAddress", 102 @Property(name = "multicastAddress",
...@@ -118,6 +124,9 @@ public class IgmpSnoop { ...@@ -118,6 +124,9 @@ public class IgmpSnoop {
118 protected NetworkConfigRegistry networkConfig; 124 protected NetworkConfigRegistry networkConfig;
119 125
120 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 126 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
127 + protected ComponentConfigService componentConfigService;
128 +
129 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
121 protected MulticastRouteService multicastService; 130 protected MulticastRouteService multicastService;
122 131
123 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 132 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
...@@ -169,9 +178,13 @@ public class IgmpSnoop { ...@@ -169,9 +178,13 @@ public class IgmpSnoop {
169 178
170 179
171 @Activate 180 @Activate
172 - public void activate() { 181 + public void activate(ComponentContext context) {
182 + modified(context);
183 +
173 appId = coreService.registerApplication("org.onosproject.igmp"); 184 appId = coreService.registerApplication("org.onosproject.igmp");
174 185
186 + componentConfigService.registerProperties(getClass());
187 +
175 packetService.addProcessor(processor, PacketProcessor.director(1)); 188 packetService.addProcessor(processor, PacketProcessor.director(1));
176 189
177 networkConfig.registerConfigFactory(configFactory); 190 networkConfig.registerConfigFactory(configFactory);
...@@ -208,13 +221,7 @@ public class IgmpSnoop { ...@@ -208,13 +221,7 @@ public class IgmpSnoop {
208 221
209 deviceService.addListener(deviceListener); 222 deviceService.addListener(deviceListener);
210 223
211 - queryPacket = buildQueryPacket(); 224 + restartQueryTask();
212 -
213 - queryTask = queryService.scheduleWithFixedDelay(
214 - SafeRecurringTask.wrap(this::querySubscribers),
215 - 0,
216 - queryPeriod,
217 - TimeUnit.SECONDS);
218 225
219 log.info("Started"); 226 log.info("Started");
220 } 227 }
...@@ -229,9 +236,49 @@ public class IgmpSnoop { ...@@ -229,9 +236,49 @@ public class IgmpSnoop {
229 networkConfig.unregisterConfigFactory(ssmTranslateConfigFactory); 236 networkConfig.unregisterConfigFactory(ssmTranslateConfigFactory);
230 queryTask.cancel(true); 237 queryTask.cancel(true);
231 queryService.shutdownNow(); 238 queryService.shutdownNow();
239 + componentConfigService.unregisterProperties(getClass(), false);
232 log.info("Stopped"); 240 log.info("Stopped");
233 } 241 }
234 242
243 + @Modified
244 + protected void modified(ComponentContext context) {
245 + Dictionary<?, ?> properties = context != null ? context.getProperties() : new Properties();
246 +
247 + String strQueryPeriod = Tools.get(properties, "queryPeriod");
248 + String strResponseCode = Tools.get(properties, "maxRespCode");
249 + try {
250 + byte newMaxRespCode = Byte.parseByte(strResponseCode);
251 + if (maxRespCode != newMaxRespCode) {
252 + maxRespCode = newMaxRespCode;
253 + queryPacket = buildQueryPacket();
254 + }
255 +
256 + int newQueryPeriod = Integer.parseInt(strQueryPeriod);
257 + if (newQueryPeriod != queryPeriod) {
258 + queryPeriod = newQueryPeriod;
259 + restartQueryTask();
260 + }
261 +
262 + } catch (NumberFormatException e) {
263 + log.warn("Error parsing config input", e);
264 + }
265 +
266 + log.info("queryPeriod set to {}", queryPeriod);
267 + log.info("maxRespCode set to {}", maxRespCode);
268 + }
269 +
270 + private void restartQueryTask() {
271 + if (queryTask != null) {
272 + queryTask.cancel(true);
273 + }
274 + queryPacket = buildQueryPacket();
275 + queryTask = queryService.scheduleWithFixedDelay(
276 + SafeRecurringTask.wrap(this::querySubscribers),
277 + 0,
278 + queryPeriod,
279 + TimeUnit.SECONDS);
280 + }
281 +
235 private void processFilterObjective(DeviceId devId, Port port, boolean remove) { 282 private void processFilterObjective(DeviceId devId, Port port, boolean remove) {
236 283
237 //TODO migrate to packet requests when packet service uses filtering objectives 284 //TODO migrate to packet requests when packet service uses filtering objectives
......
...@@ -44,6 +44,11 @@ public final class ConfigProperty { ...@@ -44,6 +44,11 @@ public final class ConfigProperty {
44 STRING, 44 STRING,
45 45
46 /** 46 /**
47 + * Indicates the value is a byte.
48 + */
49 + BYTE,
50 +
51 + /**
47 * Indicates the value is an integer. 52 * Indicates the value is an integer.
48 */ 53 */
49 INTEGER, 54 INTEGER,
...@@ -194,6 +199,16 @@ public final class ConfigProperty { ...@@ -194,6 +199,16 @@ public final class ConfigProperty {
194 } 199 }
195 200
196 /** 201 /**
202 + * Returns the property value as a byte.
203 + *
204 + * @return byte value
205 + */
206 + public byte asByte() {
207 + checkState(type == Type.BYTE, "Value is not a byte");
208 + return Byte.parseByte(value);
209 + }
210 +
211 + /**
197 * Returns the property value as an integer. 212 * Returns the property value as an integer.
198 * 213 *
199 * @return integer value 214 * @return integer value
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
15 */ 15 */
16 package org.onlab.packet; 16 package org.onlab.packet;
17 17
18 +import org.slf4j.Logger;
19 +
18 import java.nio.ByteBuffer; 20 import java.nio.ByteBuffer;
19 import java.util.ArrayList; 21 import java.util.ArrayList;
20 import java.util.Arrays; 22 import java.util.Arrays;
...@@ -22,8 +24,6 @@ import java.util.HashMap; ...@@ -22,8 +24,6 @@ import java.util.HashMap;
22 import java.util.List; 24 import java.util.List;
23 import java.util.Map; 25 import java.util.Map;
24 26
25 -import org.slf4j.Logger;
26 -
27 import static com.google.common.base.MoreObjects.toStringHelper; 27 import static com.google.common.base.MoreObjects.toStringHelper;
28 import static com.google.common.base.Preconditions.checkNotNull; 28 import static com.google.common.base.Preconditions.checkNotNull;
29 import static org.onlab.packet.PacketUtils.checkInput; 29 import static org.onlab.packet.PacketUtils.checkInput;
...@@ -33,7 +33,7 @@ import static org.slf4j.LoggerFactory.getLogger; ...@@ -33,7 +33,7 @@ import static org.slf4j.LoggerFactory.getLogger;
33 * Implements IGMP control packet format. 33 * Implements IGMP control packet format.
34 */ 34 */
35 public class IGMP extends BasePacket { 35 public class IGMP extends BasePacket {
36 - private final Logger log = getLogger(getClass()); 36 + private static final Logger log = getLogger(IGMP.class);
37 37
38 public static final byte TYPE_IGMPV3_MEMBERSHIP_QUERY = 0x11; 38 public static final byte TYPE_IGMPV3_MEMBERSHIP_QUERY = 0x11;
39 public static final byte TYPE_IGMPV1_MEMBERSHIP_REPORT = 0x12; 39 public static final byte TYPE_IGMPV1_MEMBERSHIP_REPORT = 0x12;
...@@ -169,6 +169,8 @@ public class IGMP extends BasePacket { ...@@ -169,6 +169,8 @@ public class IGMP extends BasePacket {
169 // Must calculate checksum 169 // Must calculate checksum
170 bb.putShort((short) 0); 170 bb.putShort((short) 0);
171 171
172 +
173 +
172 switch (this.igmpType) { 174 switch (this.igmpType) {
173 175
174 case IGMP.TYPE_IGMPV3_MEMBERSHIP_REPORT: 176 case IGMP.TYPE_IGMPV3_MEMBERSHIP_REPORT:
...@@ -191,6 +193,21 @@ public class IGMP extends BasePacket { ...@@ -191,6 +193,21 @@ public class IGMP extends BasePacket {
191 } 193 }
192 194
193 int size = bb.position(); 195 int size = bb.position();
196 +
197 + // compute checksum if needed
198 + if (this.checksum == 0) {
199 + bb.rewind();
200 + int accumulation = 0;
201 + for (int i = 0; i < size * 2; ++i) {
202 + accumulation += 0xffff & bb.getShort();
203 + }
204 + accumulation = (accumulation >> 16 & 0xffff)
205 + + (accumulation & 0xffff);
206 + this.checksum = (short) (~accumulation & 0xffff);
207 + bb.putShort(2, this.checksum);
208 + }
209 +
210 +
194 bb.position(0); 211 bb.position(0);
195 byte[] rdata = new byte[size]; 212 byte[] rdata = new byte[size];
196 bb.get(rdata, 0, size); 213 bb.get(rdata, 0, size);
...@@ -238,7 +255,7 @@ public class IGMP extends BasePacket { ...@@ -238,7 +255,7 @@ public class IGMP extends BasePacket {
238 igmp.igmpType = bb.get(); 255 igmp.igmpType = bb.get();
239 igmp.resField = bb.get(); 256 igmp.resField = bb.get();
240 igmp.checksum = bb.getShort(); 257 igmp.checksum = bb.getShort();
241 - int len = MINIMUM_HEADER_LEN; 258 +
242 String msg; 259 String msg;
243 260
244 switch (igmp.igmpType) { 261 switch (igmp.igmpType) {
......