Jonathan Hart
Committed by Gerrit Code Review

Fixes to the IGMP app to process group membership reports

Change-Id: I7a478011caadb8250f6a25b5fb5a820485e593b6
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.igmp;
import org.onlab.packet.IGMP;
import org.onosproject.net.ConnectPoint;
/**
* Process an IGMP Membership Report.
*/
public final class IGMPProcessMembership {
// Hide the default constructor.
private IGMPProcessMembership() {
}
/**
* Process the IGMP Membership report.
*
* @param igmp the deserialized IGMP message.
* @param receivedFrom the ConnectPoint this message came from.
*/
public static void processMembership(IGMP igmp, ConnectPoint receivedFrom) {
}
}
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.igmp;
import org.onlab.packet.IGMP;
import org.onosproject.net.ConnectPoint;
/**
* Process IGMP Query messages.
*/
public final class IGMPProcessQuery {
// Hide the default constructor.
private IGMPProcessQuery() {
}
/**
* Process the IGMP Membership Query message.
*
* @param igmp The deserialzed IGMP message
* @param receivedFrom the ConnectPoint this message came from.
*/
public static void processQuery(IGMP igmp, ConnectPoint receivedFrom) {
}
}
......@@ -24,6 +24,7 @@ import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.EthType;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IGMP;
import org.onlab.packet.IGMPMembership;
import org.onlab.packet.IPv4;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
......@@ -76,7 +77,7 @@ public class IgmpSnoop {
private static final String DEFAULT_MCAST_ADDR = "224.0.0.0/4";
@Property(name = "multicastAddress",
label = "Define the multicast base raneg to listen to")
label = "Define the multicast base range to listen to")
private String multicastAddress = DEFAULT_MCAST_ADDR;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
......@@ -194,6 +195,7 @@ public class IgmpSnoop {
}
private void processQuery(IGMP pkt, ConnectPoint location) {
// TODO is this the right thing to do for a query?
pkt.getGroups().forEach(group -> group.getSources().forEach(src -> {
McastRoute route = new McastRoute(src,
......@@ -205,6 +207,36 @@ public class IgmpSnoop {
}));
}
private void processMembership(IGMP pkt, ConnectPoint location) {
pkt.getGroups().forEach(group -> {
if (!(group instanceof IGMPMembership)) {
log.warn("Wrong group type in IGMP membership");
return;
}
IGMPMembership membership = (IGMPMembership) group;
McastRoute route = new McastRoute(IpAddress.valueOf("0.0.0.0"),
group.getGaddr(),
McastRoute.Type.IGMP);
if (membership.getRecordType() == IGMPMembership.MODE_IS_INCLUDE ||
membership.getRecordType() == IGMPMembership.CHANGE_TO_INCLUDE_MODE) {
multicastService.add(route);
multicastService.addSink(route, location);
} else if (membership.getRecordType() == IGMPMembership.MODE_IS_EXCLUDE ||
membership.getRecordType() == IGMPMembership.CHANGE_TO_EXCLUDE_MODE) {
multicastService.removeSink(route, location);
// TODO remove route if all sinks are gone
}
});
}
/**
* Packet processor responsible for handling IGMP packets.
*/
......@@ -259,7 +291,7 @@ public class IgmpSnoop {
switch (igmp.getIgmpType()) {
case IGMP.TYPE_IGMPV3_MEMBERSHIP_REPORT:
IGMPProcessMembership.processMembership(igmp, pkt.receivedFrom());
processMembership(igmp, pkt.receivedFrom());
break;
case IGMP.TYPE_IGMPV3_MEMBERSHIP_QUERY:
......@@ -269,12 +301,11 @@ public class IgmpSnoop {
case IGMP.TYPE_IGMPV1_MEMBERSHIP_REPORT:
case IGMP.TYPE_IGMPV2_MEMBERSHIP_REPORT:
case IGMP.TYPE_IGMPV2_LEAVE_GROUP:
log.debug("IGMP version 1 & 2 message types are not currently supported. Message type: " +
log.debug("IGMP version 1 & 2 message types are not currently supported. Message type: {}",
igmp.getIgmpType());
break;
default:
log.debug("Unkown IGMP message type: " + igmp.getIgmpType());
log.debug("Unknown IGMP message type: {}", igmp.getIgmpType());
break;
}
}
......@@ -312,7 +343,6 @@ public class IgmpSnoop {
log.warn("Unknown device event {}", event.type());
break;
}
}
@Override
......
......@@ -54,13 +54,11 @@ public class DistributedMcastStore extends AbstractStore<McastEvent, McastStoreD
mcastRib = storageService.<McastRoute, MulticastData>consistentMapBuilder()
.withName(MCASTRIB)
.withSerializer(Serializer.using(KryoNamespace.newBuilder()
.register(KryoNamespaces.BASIC)
.register(KryoNamespaces.MISC)
.register(KryoNamespaces.API)
.register(
MulticastData.class,
McastRoute.class,
McastRoute.Type.class,
ConnectPoint.class
McastRoute.Type.class
).build()))
//.withRelaxedReadConsistency()
.build();
......
......@@ -16,9 +16,9 @@
package org.onosproject.incubator.store.mcast.impl;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import org.onosproject.net.ConnectPoint;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
......@@ -37,13 +37,16 @@ public final class MulticastData {
private final AtomicBoolean isEmpty = new AtomicBoolean();
private MulticastData() {
this.sinks = Sets.newConcurrentHashSet();
// FIXME we have major problems trying to serialize these sets
//this.sinks = Sets.newConcurrentHashSet();
this.sinks = new HashSet<>();
isEmpty.set(true);
}
public MulticastData(ConnectPoint source) {
this.source.set(checkNotNull(source, "Multicast source cannot be null."));
this.sinks = Sets.newConcurrentHashSet();
//this.sinks = Sets.newConcurrentHashSet();
this.sinks = new HashSet<>();
isEmpty.set(false);
}
......
......@@ -20,6 +20,7 @@ import static org.onlab.packet.PacketUtils.checkBufferLength;
public class IGMPMembership extends IGMPGroup {
// TODO should be an enum
public static final byte MODE_IS_INCLUDE = 0x1;
public static final byte MODE_IS_EXCLUDE = 0x2;
public static final byte CHANGE_TO_INCLUDE_MODE = 0x3;
......@@ -50,6 +51,15 @@ public class IGMPMembership extends IGMPGroup {
}
/**
* Gets the IGMP record type.
*
* @return record type
*/
public byte getRecordType() {
return recordType;
}
/**
* Serialize this Membership Report.
*
* @param bb the ByteBuffer to write into, positioned at the next spot to be written to.
......