Moving Source from connect point to HostId in MulticastHandling
Change-Id: Ie8f678e150b7ee388680b8d8f27df0bce60ec01f
diff --git a/apps/mcast/api/src/main/java/org/onosproject/mcast/api/McastRoute.java b/apps/mcast/api/src/main/java/org/onosproject/mcast/api/McastRoute.java
index 9d5afeb..7fe1a90 100644
--- a/apps/mcast/api/src/main/java/org/onosproject/mcast/api/McastRoute.java
+++ b/apps/mcast/api/src/main/java/org/onosproject/mcast/api/McastRoute.java
@@ -57,9 +57,10 @@
/**
* Creates the McastRoute object. The source Ip can be null if this route is intent for ASM.
+ *
* @param source source Ip. Null if ASM route. Will translate in Optional.empty.
- * @param group the multicast group
- * @param type the route type.
+ * @param group the multicast group
+ * @param type the route type.
*/
public McastRoute(IpAddress source, IpAddress group, Type type) {
checkNotNull(group, "Multicast route must specify a group address");
diff --git a/apps/mcast/api/src/main/java/org/onosproject/mcast/api/McastRouteData.java b/apps/mcast/api/src/main/java/org/onosproject/mcast/api/McastRouteData.java
index e95c417..ce81ea9 100644
--- a/apps/mcast/api/src/main/java/org/onosproject/mcast/api/McastRouteData.java
+++ b/apps/mcast/api/src/main/java/org/onosproject/mcast/api/McastRouteData.java
@@ -17,7 +17,6 @@
import com.google.common.annotations.Beta;
import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.HostId;
@@ -38,7 +37,7 @@
@Beta
public final class McastRouteData {
- private final ConcurrentHashMap<ConnectPoint, Boolean> sources = new ConcurrentHashMap<>();
+ private final ConcurrentHashMap<HostId, Set<ConnectPoint>> sources = new ConcurrentHashMap<>();
private final ConcurrentHashMap<HostId, Set<ConnectPoint>> sinks = new ConcurrentHashMap<>();
private McastRouteData() {
@@ -49,13 +48,41 @@
*
* @return set of sources
*/
- public Set<ConnectPoint> sources() {
- return ImmutableSet.copyOf(sources.keySet());
+ public Map<HostId, Set<ConnectPoint>> sources() {
+ return ImmutableMap.copyOf(sources);
}
/**
* Sources contained in the associated route.
*
+ * @return map of hostIds and associated sources
+ */
+ public Set<ConnectPoint> allSources() {
+ return sources.values().stream().flatMap(Collection::stream).collect(Collectors.toSet());
+ }
+
+ /**
+ * Sources contained in the associated route for the given host.
+ *
+ * @param hostId the host
+ * @return set of sources
+ */
+ public Set<ConnectPoint> sources(HostId hostId) {
+ return sources.get(hostId);
+ }
+
+ /**
+ * Sources contained in the associated route that are not bound to any host.
+ *
+ * @return set of sources
+ */
+ public Set<ConnectPoint> nonHostSources() {
+ return sources.get(HostId.NONE);
+ }
+
+ /**
+ * Sinks contained in the associated route.
+ *
* @return map of hostIds and associated sinks
*/
public Map<HostId, Set<ConnectPoint>> sinks() {
@@ -91,13 +118,34 @@
}
/**
- * Add the sources for the associated route.
+ * Adds sources for a given host Id. If the Host Id is {@link HostId#NONE} the sources are intended to be
+ * used at all times independently of the attached host.
*
- * @param sources set of sources
+ * @param hostId the host
+ * @param sources the sources
*/
- public void addSources(Set<ConnectPoint> sources) {
+ public void addSources(HostId hostId, Set<ConnectPoint> sources) {
+ checkNotNull(hostId);
checkArgument(!sources.contains(null));
- sources.forEach(source -> this.sources.put(source, true));
+ //if existing we add to current set, otherwise we put them all
+ this.sources.compute(hostId, (host, existingSources) -> {
+ if (existingSources != null) {
+ existingSources.addAll(sources);
+ return existingSources;
+ } else {
+ return sources;
+ }
+ });
+ }
+
+ /**
+ * Adds sources for this route that are not associated directly with a given host.
+ *
+ * @param sources the sources
+ */
+ public void addNonHostSources(Set<ConnectPoint> sources) {
+ checkArgument(!sources.contains(null));
+ addSources(HostId.NONE, sources);
}
/**
@@ -108,13 +156,31 @@
}
/**
- * Removes the given sources contained in the associated route.
+ * Removes the given source contained in the associated route.
*
+ * @param source the source to remove
+ */
+ public void removeSource(HostId source) {
+ checkNotNull(source);
+ sources.remove(source);
+ }
+
+ /**
+ * Removes all the given sources for the given host for this route.
+ *
+ * @param hostId the host
* @param sources the sources to remove
*/
- public void removeSources(Set<ConnectPoint> sources) {
+ public void removeSources(HostId hostId, Set<ConnectPoint> sources) {
+ checkNotNull(hostId);
checkArgument(!sources.contains(null));
- sources.forEach(this.sources::remove);
+ //if existing we remove from current set, otherwise just skip them
+ this.sources.compute(hostId, (host, existingSources) -> {
+ if (existingSources != null) {
+ existingSources.removeAll(sources);
+ }
+ return existingSources;
+ });
}
/**
@@ -128,11 +194,14 @@
checkNotNull(hostId);
checkArgument(!sinks.contains(null));
//if existing we add to current set, otherwise we put them all
- if (this.sinks.containsKey(hostId)) {
- this.sinks.get(hostId).addAll(sinks);
- } else {
- this.sinks.put(hostId, sinks);
- }
+ this.sinks.compute(hostId, (host, existingSinks) -> {
+ if (existingSinks != null) {
+ existingSinks.addAll(sinks);
+ return existingSinks;
+ } else {
+ return sinks;
+ }
+ });
}
/**
@@ -142,7 +211,7 @@
*/
public void addNonHostSinks(Set<ConnectPoint> sinks) {
checkArgument(!sinks.contains(null));
- this.sinks.put(HostId.NONE, sinks);
+ this.addSinks(HostId.NONE, sinks);
}
/**
@@ -172,9 +241,12 @@
checkNotNull(hostId);
checkArgument(!sinks.contains(null));
//if existing we remove from current set, otherwise just skip them
- if (this.sinks.containsKey(hostId)) {
- this.sinks.get(hostId).removeAll(sinks);
- }
+ this.sinks.compute(hostId, (host, existingSinks) -> {
+ if (existingSinks != null) {
+ existingSinks.removeAll(sinks);
+ }
+ return existingSinks;
+ });
}
/**
diff --git a/apps/mcast/api/src/main/java/org/onosproject/mcast/api/McastRouteUpdate.java b/apps/mcast/api/src/main/java/org/onosproject/mcast/api/McastRouteUpdate.java
index 4333465..a117cc4 100644
--- a/apps/mcast/api/src/main/java/org/onosproject/mcast/api/McastRouteUpdate.java
+++ b/apps/mcast/api/src/main/java/org/onosproject/mcast/api/McastRouteUpdate.java
@@ -37,12 +37,14 @@
private static final String SINK_NOT_NULL = "Sink cannot be null";
private final McastRoute route;
- private final Set<ConnectPoint> sources;
+ private final Map<HostId, Set<ConnectPoint>> sources;
private final Map<HostId, Set<ConnectPoint>> sinks;
- private McastRouteUpdate(McastRoute route, Set<ConnectPoint> source, Map<HostId, Set<ConnectPoint>> sinks) {
+ private McastRouteUpdate(McastRoute route,
+ Map<HostId, Set<ConnectPoint>> sources,
+ Map<HostId, Set<ConnectPoint>> sinks) {
this.route = checkNotNull(route, ROUTE_NOT_NULL);
- this.sources = checkNotNull(source, SOURCE_NOT_NULL);
+ this.sources = checkNotNull(sources, SOURCE_NOT_NULL);
this.sinks = checkNotNull(sinks, SINK_NOT_NULL);
}
@@ -55,7 +57,7 @@
* @return the McastRouteUpdate object.
*/
public static McastRouteUpdate mcastRouteUpdate(McastRoute route,
- Set<ConnectPoint> sources,
+ Map<HostId, Set<ConnectPoint>> sources,
Map<HostId, Set<ConnectPoint>> sinks) {
return new McastRouteUpdate(route, sources, sinks);
}
@@ -72,9 +74,9 @@
/**
* The sources.
*
- * @return an optional connect point
+ * @return a set of connect points
*/
- public Set<ConnectPoint> sources() {
+ public Map<HostId, Set<ConnectPoint>> sources() {
return sources;
}
diff --git a/apps/mcast/api/src/main/java/org/onosproject/mcast/api/McastStore.java b/apps/mcast/api/src/main/java/org/onosproject/mcast/api/McastStore.java
index aa429b2..484f32ec 100644
--- a/apps/mcast/api/src/main/java/org/onosproject/mcast/api/McastStore.java
+++ b/apps/mcast/api/src/main/java/org/onosproject/mcast/api/McastStore.java
@@ -43,10 +43,22 @@
void removeRoute(McastRoute route);
/**
- * Add to the store with source information for the given route.
+ * Updates the store with a host based source information for a given route. There may be
+ * multiple source connect points for the given host.
*
- * @param route a Multicast route
- * @param sources a set of sources
+ * @param route a Multicast route
+ * @param hostId the host source
+ * @param connectPoints the sources connect point
+ */
+ void storeSource(McastRoute route, HostId hostId, Set<ConnectPoint> connectPoints);
+
+ /**
+ * Updates the store with source information for a given route.
+ * The source stored with this method are not tied with any host.
+ * Traffic will be sent from all of them.
+ *
+ * @param route a Multicast route
+ * @param sources set of specific connect points
*/
void storeSources(McastRoute route, Set<ConnectPoint> sources);
@@ -59,12 +71,20 @@
/**
* Removes from the store the source information for the given route.
- * value.
*
- * @param route a Multicast route
- * @param sources a set of sources
+ * @param route a Multicast route
+ * @param source a source
*/
- void removeSources(McastRoute route, Set<ConnectPoint> sources);
+ void removeSource(McastRoute route, HostId source);
+
+ /**
+ * Removes a set of source connect points for a given host the route.
+ *
+ * @param route the multicast route
+ * @param hostId a source host
+ * @param connectPoints a given set of connect points to remove
+ */
+ void removeSources(McastRoute route, HostId hostId, Set<ConnectPoint> connectPoints);
/**
* Updates the store with a host based sink information for a given route. There may be
@@ -127,6 +147,15 @@
Set<ConnectPoint> sourcesFor(McastRoute route);
/**
+ * Obtains the sources for a given host for a given Multicast route.
+ *
+ * @param route a Multicast route
+ * @param hostId the host
+ * @return a set of sources
+ */
+ Set<ConnectPoint> sourcesFor(McastRoute route, HostId hostId);
+
+ /**
* Obtains the sinks for a Multicast route.
*
* @param route a Multicast route
diff --git a/apps/mcast/api/src/main/java/org/onosproject/mcast/api/MulticastRouteService.java b/apps/mcast/api/src/main/java/org/onosproject/mcast/api/MulticastRouteService.java
index bcee070..bd32363 100644
--- a/apps/mcast/api/src/main/java/org/onosproject/mcast/api/MulticastRouteService.java
+++ b/apps/mcast/api/src/main/java/org/onosproject/mcast/api/MulticastRouteService.java
@@ -61,11 +61,33 @@
Set<McastRoute> getRoute(IpAddress groupIp, IpAddress sourceIp);
/**
- * Adds a set of sources connect points to the route from where the
+ * Adds a host as a source to the route from where the
* data stream is originating.
*
- * @param route the Multicast route
- * @param sources a set of sources
+ * @param route the Multicast route
+ * @param source a source host
+ */
+ void addSource(McastRoute route, HostId source);
+
+
+ /**
+ * Adds a set of source connect points for a given host source to the route to
+ * which a data stream should be sent to.
+ *
+ * @param route a Multicast route
+ * @param hostId a source host
+ * @param connectPoints the source for the specific host
+ */
+ void addSources(McastRoute route, HostId hostId, Set<ConnectPoint> connectPoints);
+
+ /**
+ * Adds a set of sources to the route from which a data stream should be
+ * sent to. If this method is used the connect points will all be
+ * used as different sources for that Mcast Tree. For dual-homed sources
+ * please use {@link #addSource(McastRoute route, HostId hostId) addSource}.
+ *
+ * @param route a Multicast route
+ * @param sources a set of source connect points
*/
void addSources(McastRoute route, Set<ConnectPoint> sources);
@@ -77,12 +99,12 @@
void removeSources(McastRoute route);
/**
- * Removes a set of sources connect points from the route.
+ * Removes a source host from the route.
*
- * @param route the Multicast route
- * @param sources a set of sources
+ * @param route the Multicast route
+ * @param source a host source
*/
- void removeSources(McastRoute route, Set<ConnectPoint> sources);
+ void removeSource(McastRoute route, HostId source);
/**
* Adds a sink to the route to which a data stream should be
@@ -112,7 +134,7 @@
* @param route a Multicast route
* @param sinks a set of sink connect point
*/
- void addSink(McastRoute route, Set<ConnectPoint> sinks);
+ void addSinks(McastRoute route, Set<ConnectPoint> sinks);
/**
* Removes all the sinks from the route.
@@ -157,6 +179,15 @@
Set<ConnectPoint> sources(McastRoute route);
/**
+ * Find the set of connect points for a given source for this route.
+ *
+ * @param route a Multicast route
+ * @param hostId the host
+ * @return a list of connect points
+ */
+ Set<ConnectPoint> sources(McastRoute route, HostId hostId);
+
+ /**
* Find the list of sinks for this route.
*
* @param route a Multicast route
diff --git a/apps/mcast/cli/src/main/java/org/onosproject/mcast/cli/McastHostJoinCommand.java b/apps/mcast/cli/src/main/java/org/onosproject/mcast/cli/McastHostJoinCommand.java
index 629cb2a..7650649 100644
--- a/apps/mcast/cli/src/main/java/org/onosproject/mcast/cli/McastHostJoinCommand.java
+++ b/apps/mcast/cli/src/main/java/org/onosproject/mcast/cli/McastHostJoinCommand.java
@@ -21,13 +21,8 @@
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.mcast.api.McastRoute;
import org.onosproject.mcast.api.MulticastRouteService;
-import org.onosproject.net.ConnectPoint;
import org.onosproject.net.HostId;
-import java.util.Arrays;
-import java.util.Set;
-import java.util.stream.Collectors;
-
/**
* Installs a source, multicast group flow.
*/
@@ -52,8 +47,8 @@
String gAddr = null;
@Option(name = "-srcs", aliases = "--sources",
- description = "Ingress port of:XXXXXXXXXX/XX",
- valueToShowInHelp = "of:0000000000000001/1",
+ description = "Host sink format: MAC/VLAN",
+ valueToShowInHelp = "00:00:00:00:00:00/None",
multiValued = true)
String[] sources = null;
@@ -62,7 +57,7 @@
description = "Host sink format: MAC/VLAN",
valueToShowInHelp = "00:00:00:00:00:00/None",
multiValued = true)
- String[] hosts = null;
+ String[] sinks = null;
@Override
protected void execute() {
@@ -78,16 +73,14 @@
mcastRouteManager.add(mRoute);
if (sources != null) {
- Set<ConnectPoint> sourcesSet = Arrays.stream(sources)
- .map(ConnectPoint::deviceConnectPoint)
- .collect(Collectors.toSet());
- mcastRouteManager.addSources(mRoute, sourcesSet);
+ for (String hostId : sources) {
+ mcastRouteManager.addSource(mRoute, HostId.hostId(hostId));
+ }
}
- if (hosts != null) {
- for (String hostId : hosts) {
+ if (sinks != null) {
+ for (String hostId : sinks) {
mcastRouteManager.addSink(mRoute, HostId.hostId(hostId));
-
}
}
printMcastRoute(mRoute);
@@ -96,7 +89,7 @@
private void printMcastRoute(McastRoute mcastRoute) {
// If the source is present let's use it, otherwise we need to print *
print(FORMAT_MAPPING, mcastRoute.type(), mcastRoute.group(),
- mcastRoute.source().isPresent() ? mcastRoute.source().get() : "*");
+ mcastRoute.source().isPresent() ? mcastRoute.source().get() : "*");
}
}
diff --git a/apps/mcast/cli/src/main/java/org/onosproject/mcast/cli/McastShowHostCommand.java b/apps/mcast/cli/src/main/java/org/onosproject/mcast/cli/McastShowHostCommand.java
index 24ee11b..dbf2ca6 100644
--- a/apps/mcast/cli/src/main/java/org/onosproject/mcast/cli/McastShowHostCommand.java
+++ b/apps/mcast/cli/src/main/java/org/onosproject/mcast/cli/McastShowHostCommand.java
@@ -89,7 +89,7 @@
private void printRoute(MulticastRouteService mcastService, McastRoute route) {
Map<HostId, Set<ConnectPoint>> sinks = mcastService.routeData(route).sinks();
- Set<ConnectPoint> sources = mcastService.sources(route);
+ Map<HostId, Set<ConnectPoint>> sources = mcastService.routeData(route).sources();
String srcIp = "*";
if (route.source().isPresent()) {
srcIp = route.source().get().toString();
diff --git a/apps/mcast/cli/src/main/java/org/onosproject/mcast/cli/McastHostDeleteCommand.java b/apps/mcast/cli/src/main/java/org/onosproject/mcast/cli/McastSinkDeleteCommand.java
similarity index 89%
rename from apps/mcast/cli/src/main/java/org/onosproject/mcast/cli/McastHostDeleteCommand.java
rename to apps/mcast/cli/src/main/java/org/onosproject/mcast/cli/McastSinkDeleteCommand.java
index ca5959d..524fcb2 100644
--- a/apps/mcast/cli/src/main/java/org/onosproject/mcast/cli/McastHostDeleteCommand.java
+++ b/apps/mcast/cli/src/main/java/org/onosproject/mcast/cli/McastSinkDeleteCommand.java
@@ -26,9 +26,9 @@
/**
* Deletes a multicast route.
*/
-@Command(scope = "onos", name = "mcast-host-delete",
- description = "Delete a multicast route flow")
-public class McastHostDeleteCommand extends AbstractShellCommand {
+@Command(scope = "onos", name = "mcast-sink-delete",
+ description = "Delete a sink from multicast route flow. If no sin is specified removes the whole route.")
+public class McastSinkDeleteCommand extends AbstractShellCommand {
// Delete format for group line
private static final String D_FORMAT_MAPPING = "Deleted the mcast route: " +
@@ -50,7 +50,7 @@
required = true, multiValued = false)
String gAddr = null;
- @Option(name = "-h", aliases = "--host",
+ @Option(name = "-s", aliases = "--sinks",
description = "Host sink format: MAC/VLAN",
valueToShowInHelp = "00:00:00:00:00:00/None")
String host = null;
@@ -70,7 +70,7 @@
sAddrIp = IpAddress.valueOf(sAddr);
}
McastRoute mRoute = new McastRoute(sAddrIp, IpAddress.valueOf(gAddr),
- McastRoute.Type.STATIC);
+ McastRoute.Type.STATIC);
// If the user provides only sAddr and gAddr, we have to remove the route
if (host == null || host.isEmpty()) {
mcastRouteManager.remove(mRoute);
@@ -93,6 +93,6 @@
private void printMcastRoute(String format, McastRoute mcastRoute) {
// If the source is present let's use it, otherwise we need to print *
print(format, mcastRoute.type(), mcastRoute.group(),
- mcastRoute.source().isPresent() ? mcastRoute.source().get() : "*");
+ mcastRoute.source().isPresent() ? mcastRoute.source().get() : "*");
}
}
diff --git a/apps/mcast/cli/src/main/java/org/onosproject/mcast/cli/McastSourceDeleteCommand.java b/apps/mcast/cli/src/main/java/org/onosproject/mcast/cli/McastSourceDeleteCommand.java
index 0a6080c..d1f646f 100644
--- a/apps/mcast/cli/src/main/java/org/onosproject/mcast/cli/McastSourceDeleteCommand.java
+++ b/apps/mcast/cli/src/main/java/org/onosproject/mcast/cli/McastSourceDeleteCommand.java
@@ -21,11 +21,7 @@
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.mcast.api.McastRoute;
import org.onosproject.mcast.api.MulticastRouteService;
-import org.onosproject.net.ConnectPoint;
-
-import java.util.Arrays;
-import java.util.Set;
-import java.util.stream.Collectors;
+import org.onosproject.net.HostId;
/**
* Deletes a multicast route.
@@ -55,8 +51,8 @@
String gAddr = null;
@Option(name = "-src", aliases = "--connectPoint",
- description = "Source port of:XXXXXXXXXX/XX",
- valueToShowInHelp = "of:0000000000000001/1",
+ description = "Host sink format: MAC/VLAN",
+ valueToShowInHelp = "00:00:00:00:00:00/None",
multiValued = true)
String[] sourceList = null;
@@ -76,7 +72,7 @@
sAddrIp = IpAddress.valueOf(sAddr);
}
McastRoute mRoute = new McastRoute(sAddrIp, IpAddress.valueOf(gAddr),
- McastRoute.Type.STATIC);
+ McastRoute.Type.STATIC);
// No specific connect points, we have to remove everything
if (sourceList == null) {
mcastRouteManager.remove(mRoute);
@@ -88,16 +84,16 @@
print("Route is not present, store it first");
return;
}
- Set<ConnectPoint> sourcesSet = Arrays.stream(sourceList)
- .map(ConnectPoint::deviceConnectPoint)
- .collect(Collectors.toSet());
- mcastRouteManager.removeSources(mRoute, sourcesSet);
+ for (String hostId : sourceList) {
+ mcastRouteManager.removeSource(mRoute, HostId.hostId(hostId));
+
+ }
printMcastRoute(U_FORMAT_MAPPING, mRoute);
}
private void printMcastRoute(String format, McastRoute mcastRoute) {
// If the source is present let's use it, otherwise we need to print *
print(format, mcastRoute.type(), mcastRoute.group(),
- mcastRoute.source().isPresent() ? mcastRoute.source().get() : "*");
+ mcastRoute.source().isPresent() ? mcastRoute.source().get() : "*");
}
}
diff --git a/apps/mcast/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/apps/mcast/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
index 1525938..7bf0fcb 100644
--- a/apps/mcast/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/apps/mcast/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -21,7 +21,7 @@
<action class="org.onosproject.mcast.cli.McastHostJoinCommand"/>
<optional-completers>
<entry key="-gAddr" value-ref="mcastGroupCompleter"/>
- <entry key="-srcs" value-ref="connectpointCompleter"/>
+ <entry key="-srcs" value-ref="hostIdCompleter"/>
<entry key="-sinks" value-ref="hostIdCompleter"/>
</optional-completers>
</command>
@@ -32,18 +32,18 @@
</optional-completers>
</command>
<command>
- <action class="org.onosproject.mcast.cli.McastHostDeleteCommand"/>
+ <action class="org.onosproject.mcast.cli.McastSinkDeleteCommand"/>
<optional-completers>
<entry key="-gAddr" value-ref="mcastGroupCompleter"/>
<entry key="-cps" value-ref="connectpointCompleter"/>
- <entry key="-h" value-ref="hostIdCompleter"/>
+ <entry key="-s" value-ref="hostIdCompleter"/>
</optional-completers>
</command>
<command>
<action class="org.onosproject.mcast.cli.McastSourceDeleteCommand"/>
<optional-completers>
<entry key="-gAddr" value-ref="mcastGroupCompleter"/>
- <entry key="-src" value-ref="connectpointCompleter"/>
+ <entry key="-src" value-ref="hostIdCompleter"/>
</optional-completers>
</command>
<command>
diff --git a/apps/mcast/impl/src/main/java/org/onosproject/mcast/impl/DistributedMcastRoutesStore.java b/apps/mcast/impl/src/main/java/org/onosproject/mcast/impl/DistributedMcastRoutesStore.java
index 84e2131..c9baac3 100644
--- a/apps/mcast/impl/src/main/java/org/onosproject/mcast/impl/DistributedMcastRoutesStore.java
+++ b/apps/mcast/impl/src/main/java/org/onosproject/mcast/impl/DistributedMcastRoutesStore.java
@@ -17,7 +17,6 @@
import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Sets;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
@@ -111,15 +110,25 @@
mcastRoutes.remove(route);
}
+
@Override
- public void storeSources(McastRoute route, Set<ConnectPoint> sources) {
+ public void storeSource(McastRoute route, HostId hostId, Set<ConnectPoint> connectPoints) {
mcastRoutes.compute(route, (k, v) -> {
- v.addSources(sources);
+ v.addSources(hostId, connectPoints);
return v;
});
}
@Override
+ public void storeSources(McastRoute route, Set<ConnectPoint> sources) {
+ mcastRoutes.compute(route, (k, v) -> {
+ v.addSources(HostId.NONE, sources);
+ return v;
+ });
+ }
+
+
+ @Override
public void removeSources(McastRoute route) {
mcastRoutes.compute(route, (k, v) -> {
v.removeSources();
@@ -129,15 +138,23 @@
}
@Override
- public void removeSources(McastRoute route, Set<ConnectPoint> sources) {
+ public void removeSource(McastRoute route, HostId source) {
mcastRoutes.compute(route, (k, v) -> {
- v.removeSources(sources);
+ v.removeSource(source);
// Since there are no sources, we should remove the route
return v.sources().isEmpty() ? null : v;
});
}
@Override
+ public void removeSources(McastRoute route, HostId hostId, Set<ConnectPoint> sources) {
+ mcastRoutes.compute(route, (k, v) -> {
+ v.removeSources(hostId, sources);
+ return v;
+ });
+ }
+
+ @Override
public void addSink(McastRoute route, HostId hostId, Set<ConnectPoint> sinks) {
mcastRoutes.compute(route, (k, v) -> {
v.addSinks(hostId, sinks);
@@ -189,7 +206,14 @@
@Override
public Set<ConnectPoint> sourcesFor(McastRoute route) {
McastRouteData data = mcastRoutes.getOrDefault(route, null);
- return data == null ? ImmutableSet.of() : ImmutableSet.copyOf(data.sources());
+ return data == null ? ImmutableSet.of() : ImmutableSet.copyOf(data.sources().values().stream()
+ .flatMap(Collection::stream).collect(Collectors.toSet()));
+ }
+
+ @Override
+ public Set<ConnectPoint> sourcesFor(McastRoute route, HostId hostId) {
+ McastRouteData data = mcastRoutes.getOrDefault(route, null);
+ return data == null ? ImmutableSet.of() : ImmutableSet.copyOf(data.sources(hostId));
}
@Override
@@ -227,27 +251,18 @@
switch (event.type()) {
case INSERT:
checkNotNull(newData);
- McastEvent.Type type;
- if (!newData.sources().isEmpty() || !newData.sinks().isEmpty()) {
- type = McastEvent.Type.SOURCES_ADDED;
- } else if (!newData.sinks().isEmpty()) {
- type = McastEvent.Type.SINKS_ADDED;
- } else {
- type = McastEvent.Type.ROUTE_ADDED;
- }
- notifyDelegate(new McastEvent(type, null,
+ notifyDelegate(new McastEvent(McastEvent.Type.ROUTE_ADDED, null,
mcastRouteUpdate(route, newData.sources(), newData.sinks())));
break;
case UPDATE:
checkNotNull(newData);
checkNotNull(oldData);
- if (!Sets.difference(newData.sources(), oldData.sources()).isEmpty()) {
+ if (newData.allSources().size() > oldData.allSources().size()) {
notifyDelegate(new McastEvent(McastEvent.Type.SOURCES_ADDED,
mcastRouteUpdate(route, oldData.sources(), oldData.sinks()),
mcastRouteUpdate(route, newData.sources(), newData.sinks())));
- }
- if (!Sets.difference(oldData.sources(), newData.sources()).isEmpty()) {
+ } else if (newData.allSources().size() < oldData.allSources().size()) {
notifyDelegate(new McastEvent(McastEvent.Type.SOURCES_REMOVED,
mcastRouteUpdate(route, oldData.sources(), oldData.sinks()),
mcastRouteUpdate(route, newData.sources(), newData.sinks())));
diff --git a/apps/mcast/impl/src/main/java/org/onosproject/mcast/impl/MulticastRouteManager.java b/apps/mcast/impl/src/main/java/org/onosproject/mcast/impl/MulticastRouteManager.java
index 055d8de..9f15b6c 100644
--- a/apps/mcast/impl/src/main/java/org/onosproject/mcast/impl/MulticastRouteManager.java
+++ b/apps/mcast/impl/src/main/java/org/onosproject/mcast/impl/MulticastRouteManager.java
@@ -113,16 +113,40 @@
final Optional<IpAddress> source = Optional.ofNullable(sourceIp);
return store.getRoutes().stream()
.filter(route -> route.group().equals(groupIp) &&
- Objects.equal(route.source(), source))
+ Objects.equal(route.source(), source))
.collect(Collectors.toSet());
}
@Override
- public void addSources(McastRoute route, Set<ConnectPoint> connectPoints) {
+ public void addSource(McastRoute route, HostId source) {
checkNotNull(route, "Route cannot be null");
- checkNotNull(connectPoints, "Source cannot be null");
+ checkNotNull(source, "Source cannot be null");
if (checkRoute(route)) {
- store.storeSources(route, connectPoints);
+ Set<ConnectPoint> sources = new HashSet<>();
+ Host host = hostService.getHost(source);
+ if (host != null) {
+ sources.addAll(host.locations());
+ }
+ store.storeSource(route, source, sources);
+ }
+ }
+
+ @Override
+ public void addSources(McastRoute route, HostId hostId, Set<ConnectPoint> connectPoints) {
+ checkNotNull(route, "Route cannot be null");
+ checkNotNull(hostId, "HostId cannot be null");
+ checkNotNull(connectPoints, "Sources cannot be null");
+ if (checkRoute(route)) {
+ store.storeSource(route, hostId, connectPoints);
+ }
+ }
+
+ @Override
+ public void addSources(McastRoute route, Set<ConnectPoint> sources) {
+ checkNotNull(route, "Route cannot be null");
+ checkNotNull(sources, "sources cannot be null");
+ if (checkRoute(route)) {
+ store.storeSources(route, sources);
}
}
@@ -135,11 +159,11 @@
}
@Override
- public void removeSources(McastRoute route, Set<ConnectPoint> sources) {
+ public void removeSource(McastRoute route, HostId source) {
checkNotNull(route, "Route cannot be null");
- checkNotNull(sources, "Source cannot be null");
+ checkNotNull(source, "Source cannot be null");
if (checkRoute(route)) {
- store.removeSources(route, sources);
+ store.removeSource(route, source);
}
}
@@ -149,8 +173,7 @@
Set<ConnectPoint> sinks = new HashSet<>();
Host host = hostService.getHost(hostId);
if (host != null) {
- host.locations().forEach(hostLocation -> sinks.add(
- ConnectPoint.deviceConnectPoint(hostLocation.deviceId() + "/" + hostLocation.port())));
+ sinks.addAll(host.locations());
}
store.addSink(route, hostId, sinks);
}
@@ -166,7 +189,7 @@
}
@Override
- public void addSink(McastRoute route, Set<ConnectPoint> sinks) {
+ public void addSinks(McastRoute route, Set<ConnectPoint> sinks) {
checkNotNull(route, "Route cannot be null");
checkNotNull(sinks, "Sinks cannot be null");
if (checkRoute(route)) {
@@ -212,6 +235,12 @@
}
@Override
+ public Set<ConnectPoint> sources(McastRoute route, HostId hostId) {
+ checkNotNull(route, "Route cannot be null");
+ return checkRoute(route) ? store.sourcesFor(route, hostId) : ImmutableSet.of();
+ }
+
+ @Override
public Set<ConnectPoint> sinks(McastRoute route) {
checkNotNull(route, "Route cannot be null");
return checkRoute(route) ? store.sinksFor(route) : ImmutableSet.of();
@@ -252,33 +281,55 @@
public void event(HostEvent event) {
HostId hostId = event.subject().id();
log.debug("Host event: {}", event);
+ Set<McastRoute> routesForSource = routesForSource(hostId);
+ Set<McastRoute> routesForSink = routesForSink(hostId);
switch (event.type()) {
case HOST_ADDED:
//the host is added, if it already comes with some locations let's use them
- eventAddSinks(hostId, event.subject().locations());
+ if (!routesForSource.isEmpty()) {
+ eventAddSources(hostId, event.subject().locations(), routesForSource);
+ }
+ if (!routesForSink.isEmpty()) {
+ eventAddSinks(hostId, event.subject().locations(), routesForSink);
+ }
break;
case HOST_MOVED:
//both subjects must be null or the system is in an incoherent state
if ((event.prevSubject() != null && event.subject() != null)) {
//we compute the difference between old locations and new ones and remove the previous
- Set<HostLocation> removedSinks = Sets.difference(event.prevSubject().locations(),
+ Set<HostLocation> removedConnectPoint = Sets.difference(event.prevSubject().locations(),
event.subject().locations()).immutableCopy();
- if (!removedSinks.isEmpty()) {
- eventRemoveSinks(hostId, removedSinks);
+ if (!removedConnectPoint.isEmpty()) {
+ if (!routesForSource.isEmpty()) {
+ eventRemoveSources(hostId, removedConnectPoint, routesForSource);
+ }
+ if (!routesForSink.isEmpty()) {
+ eventRemoveSinks(hostId, removedConnectPoint, routesForSink);
+ }
}
- Set<HostLocation> addedSinks = Sets.difference(event.subject().locations(),
+ Set<HostLocation> addedConnectPoints = Sets.difference(event.subject().locations(),
event.prevSubject().locations()).immutableCopy();
//if the host now has some new locations we add them to the sinks set
- if (!addedSinks.isEmpty()) {
- eventAddSinks(hostId, addedSinks);
+ if (!addedConnectPoints.isEmpty()) {
+ if (!routesForSource.isEmpty()) {
+ eventAddSources(hostId, addedConnectPoints, routesForSource);
+ }
+ if (!routesForSink.isEmpty()) {
+ eventAddSinks(hostId, addedConnectPoints, routesForSink);
+ }
}
}
break;
case HOST_REMOVED:
- // Removing all the sinks for that specific host
+ // Removing all the connect points for that specific host
// even if the locations are 0 we keep
// the host information in the route in case it shows up again
- eventRemoveSinks(event.subject().id(), event.subject().locations());
+ if (!routesForSource.isEmpty()) {
+ eventRemoveSources(hostId, event.subject().locations(), routesForSource);
+ }
+ if (!routesForSink.isEmpty()) {
+ eventRemoveSinks(hostId, event.subject().locations(), routesForSink);
+ }
break;
case HOST_UPDATED:
default:
@@ -287,25 +338,52 @@
}
}
- //Adds sinks for a given host event
- private void eventRemoveSinks(HostId hostId, Set<HostLocation> removedSinks) {
+ //Finds the route for which a host is source
+ private Set<McastRoute> routesForSource(HostId hostId) {
+ // Filter by host id
+ return store.getRoutes().stream().filter(mcastRoute -> store.getRouteData(mcastRoute)
+ .sources().containsKey(hostId)).collect(Collectors.toSet());
+ }
+
+ //Finds the route for which a host is sink
+ private Set<McastRoute> routesForSink(HostId hostId) {
+ return store.getRoutes().stream().filter(mcastRoute -> store.getRouteData(mcastRoute)
+ .sinks().containsKey(hostId)).collect(Collectors.toSet());
+ }
+
+ //Removes sources for a given host event
+ private void eventRemoveSources(HostId hostId, Set<HostLocation> removedSources, Set<McastRoute> routesForSource) {
+ Set<ConnectPoint> sources = new HashSet<>();
+ // Build sink using host location
+ sources.addAll(removedSources);
+ // Remove from each route the provided sinks
+ routesForSource.forEach(route -> store.removeSources(route, hostId, sources));
+ }
+
+ //Adds the sources for a given host event
+ private void eventAddSources(HostId hostId, Set<HostLocation> addedSources, Set<McastRoute> routesForSource) {
+ Set<ConnectPoint> sources = new HashSet<>();
+ // Build source using host location
+ sources.addAll(addedSources);
+ // Add to each route the provided sources
+ routesForSource.forEach(route -> store.storeSource(route, hostId, sources));
+ }
+
+ //Remove sinks for a given host event
+ private void eventRemoveSinks(HostId hostId, Set<HostLocation> removedSinks, Set<McastRoute> routesForSinks) {
Set<ConnectPoint> sinks = new HashSet<>();
// Build sink using host location
sinks.addAll(removedSinks);
- // Filter by host id and then remove from each route the provided sinks
- store.getRoutes().stream().filter(mcastRoute -> store.getRouteData(mcastRoute)
- .sinks().get(hostId) != null)
- .forEach(route -> store.removeSinks(route, hostId, sinks));
+ // Remove from each route the provided sinks
+ routesForSinks.forEach(route -> store.removeSinks(route, hostId, sinks));
}
- //Removes the sinks for a given host event
- private void eventAddSinks(HostId hostId, Set<HostLocation> addedSinks) {
+ //Adds the sinks for a given host event
+ private void eventAddSinks(HostId hostId, Set<HostLocation> addedSinks, Set<McastRoute> routesForSinks) {
Set<ConnectPoint> sinks = new HashSet<>();
// Build sink using host location
sinks.addAll(addedSinks);
- // Filter by host id and then add to each route the provided sinks
- store.getRoutes().stream().filter(mcastRoute -> store.getRouteData(mcastRoute)
- .sinks().get(hostId) != null)
- .forEach(route -> store.addSink(route, hostId, sinks));
+ // Add to each route the provided sinks
+ routesForSinks.forEach(route -> store.addSink(route, hostId, sinks));
}
}
diff --git a/apps/mcast/web/src/main/java/org/onosproject/mcast/web/McastHostRouteCodec.java b/apps/mcast/web/src/main/java/org/onosproject/mcast/web/McastHostRouteCodec.java
index cb41e34..4629293 100644
--- a/apps/mcast/web/src/main/java/org/onosproject/mcast/web/McastHostRouteCodec.java
+++ b/apps/mcast/web/src/main/java/org/onosproject/mcast/web/McastHostRouteCodec.java
@@ -56,10 +56,15 @@
root.put(SOURCE, "*");
}
- ArrayNode sources = context.mapper().createArrayNode();
- context.getService(MulticastRouteService.class).sources(route).forEach(source -> {
- sources.add(source.toString());
+ ObjectNode sources = context.mapper().createObjectNode();
+ context.getService(MulticastRouteService.class).routeData(route).sources().forEach((k, v) -> {
+ ArrayNode node = context.mapper().createArrayNode();
+ v.forEach(source -> {
+ node.add(source.toString());
+ });
+ sources.putPOJO(k.toString(), node);
});
+
root.putPOJO(SOURCES, sources);
ObjectNode sinks = context.mapper().createObjectNode();
diff --git a/apps/mcast/web/src/main/java/org/onosproject/mcast/web/McastRouteWebResource.java b/apps/mcast/web/src/main/java/org/onosproject/mcast/web/McastRouteWebResource.java
index ffe6e65..e4ff608 100644
--- a/apps/mcast/web/src/main/java/org/onosproject/mcast/web/McastRouteWebResource.java
+++ b/apps/mcast/web/src/main/java/org/onosproject/mcast/web/McastRouteWebResource.java
@@ -19,7 +19,6 @@
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.annotations.Beta;
-import com.google.common.collect.ImmutableSet;
import org.onlab.packet.IpAddress;
import org.onosproject.mcast.api.McastRoute;
import org.onosproject.mcast.api.MulticastRouteService;
@@ -115,12 +114,15 @@
@PathParam("srcIp") String srcIp) {
Optional<McastRoute> route = getMcastRoute(group, srcIp);
if (route.isPresent()) {
- get(MulticastRouteService.class).sources(route.get());
- ArrayNode node = this.mapper().createArrayNode();
- get(MulticastRouteService.class).sources(route.get()).forEach(source -> {
- node.add(source.toString());
+ ObjectNode sources = this.mapper().createObjectNode();
+ get(MulticastRouteService.class).routeData(route.get()).sources().forEach((k, v) -> {
+ ArrayNode node = this.mapper().createArrayNode();
+ v.forEach(source -> {
+ node.add(source.toString());
+ });
+ sources.putPOJO(k.toString(), node);
});
- ObjectNode root = this.mapper().createObjectNode().putPOJO(SOURCES, node);
+ ObjectNode root = this.mapper().createObjectNode().putPOJO(SOURCES, sources);
return ok(root).build();
}
return Response.noContent().build();
@@ -140,7 +142,6 @@
@PathParam("srcIp") String srcIp) {
Optional<McastRoute> route = getMcastRoute(group, srcIp);
if (route.isPresent()) {
- get(MulticastRouteService.class).sources(route.get());
ObjectNode sinks = this.mapper().createObjectNode();
get(MulticastRouteService.class).routeData(route.get()).sinks().forEach((k, v) -> {
ArrayNode node = this.mapper().createArrayNode();
@@ -156,6 +157,33 @@
}
/**
+ * Get all source connect points for a given sink host in a multicast route.
+ *
+ * @param group group IP address
+ * @param srcIp source IP address
+ * @param hostId host Id
+ * @return 200 OK with array of all sources for multicast route
+ */
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("sources/{group}/{srcIp}/{hostId}")
+ public Response getHostSources(@PathParam("group") String group,
+ @PathParam("srcIp") String srcIp,
+ @PathParam("hostId") String hostId) {
+ Optional<McastRoute> route = getMcastRoute(group, srcIp);
+ if (route.isPresent()) {
+ ArrayNode node = this.mapper().createArrayNode();
+ get(MulticastRouteService.class).sources(route.get(), HostId.hostId(hostId))
+ .forEach(source -> {
+ node.add(source.toString());
+ });
+ ObjectNode root = this.mapper().createObjectNode().putPOJO(SOURCES, node);
+ return ok(root).build();
+ }
+ return Response.noContent().build();
+ }
+
+ /**
* Get all sink connect points for a given sink host in a multicast route.
*
* @param group group IP address
@@ -171,7 +199,6 @@
@PathParam("hostId") String hostId) {
Optional<McastRoute> route = getMcastRoute(group, srcIp);
if (route.isPresent()) {
- get(MulticastRouteService.class).sources(route.get());
ArrayNode node = this.mapper().createArrayNode();
get(MulticastRouteService.class).sinks(route.get(), HostId.hostId(hostId))
.forEach(source -> {
@@ -204,9 +231,9 @@
McastRoute route = codec(McastRoute.class).decode((ObjectNode) routeJson, this);
service.add(route);
- Set<ConnectPoint> sources = new HashSet<>();
+ Set<HostId> sources = new HashSet<>();
routeJson.path(SOURCES).elements().forEachRemaining(src -> {
- sources.add(ConnectPoint.deviceConnectPoint(src.asText()));
+ sources.add(HostId.hostId(src.asText()));
});
Set<HostId> sinks = new HashSet<>();
routeJson.path(SINKS).elements().forEachRemaining(sink -> {
@@ -214,7 +241,9 @@
});
if (!sources.isEmpty()) {
- service.addSources(route, sources);
+ sources.forEach(source -> {
+ service.addSource(route, source);
+ });
}
if (!sinks.isEmpty()) {
sinks.forEach(sink -> {
@@ -248,9 +277,9 @@
McastRoute route = codec(McastRoute.class).decode(jsonTree, this);
service.add(route);
- Set<ConnectPoint> sources = new HashSet<>();
+ Set<HostId> sources = new HashSet<>();
jsonTree.path(SOURCES).elements().forEachRemaining(src -> {
- sources.add(ConnectPoint.deviceConnectPoint(src.asText()));
+ sources.add(HostId.hostId(src.asText()));
});
Set<HostId> sinks = new HashSet<>();
jsonTree.path(SINKS).elements().forEachRemaining(sink -> {
@@ -258,7 +287,9 @@
});
if (!sources.isEmpty()) {
- service.addSources(route, sources);
+ sources.forEach(source -> {
+ service.addSource(route, source);
+ });
}
if (!sinks.isEmpty()) {
sinks.forEach(sink -> {
@@ -298,12 +329,14 @@
ArrayNode jsonTree;
try {
jsonTree = (ArrayNode) mapper().readTree(stream).get(SOURCES);
- Set<ConnectPoint> sources = new HashSet<>();
+ Set<HostId> sources = new HashSet<>();
jsonTree.elements().forEachRemaining(src -> {
- sources.add(ConnectPoint.deviceConnectPoint(src.asText()));
+ sources.add(HostId.hostId(src.asText()));
});
if (!sources.isEmpty()) {
- service.addSources(route.get(), sources);
+ sources.forEach(src -> {
+ service.addSource(route.get(), src);
+ });
}
} catch (IOException e) {
throw new IllegalArgumentException(e);
@@ -354,6 +387,45 @@
return Response.noContent().build();
}
+ /**
+ * Adds a new set of connect points for an existing host source in a given multicast route.
+ *
+ * @param group group IP address
+ * @param srcIp source IP address
+ * @param hostId the host Id
+ * @param stream source connect points JSON
+ * @return status of the request - CREATED if the JSON is correct,
+ * BAD_REQUEST if the JSON is invalid
+ * @onos.rsModel McastHostSourcesAdd
+ */
+ @POST
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("source/{group}/{srcIp}/{hostId}")
+ public Response addHostSource(@PathParam("group") String group,
+ @PathParam("srcIp") String srcIp,
+ @PathParam("hostId") String hostId,
+ InputStream stream) {
+ MulticastRouteService service = get(MulticastRouteService.class);
+ Optional<McastRoute> route = getMcastRoute(group, srcIp);
+ if (route.isPresent()) {
+ ArrayNode jsonTree;
+ try {
+ jsonTree = (ArrayNode) mapper().readTree(stream).get(SOURCES);
+ Set<ConnectPoint> sources = new HashSet<>();
+ jsonTree.elements().forEachRemaining(src -> {
+ sources.add(ConnectPoint.deviceConnectPoint(src.asText()));
+ });
+ if (!sources.isEmpty()) {
+ service.addSources(route.get(), HostId.hostId(hostId), sources);
+ }
+ } catch (IOException e) {
+ throw new IllegalArgumentException(e);
+ }
+ return Response.ok().build();
+ }
+ return Response.noContent().build();
+ }
/**
* Adds a new sink for an existing host in a given multicast route.
@@ -467,23 +539,23 @@
}
/**
- * Deletes a source connect point for a specific route.
+ * Deletes a source hostId for a specific route.
* If the sources are empty the entire route is removed.
*
- * @param group group IP address
- * @param srcIp source IP address
- * @param srcCp source connect point
+ * @param group group IP address
+ * @param srcIp source IP address
+ * @param hostId source host id
* @return 204 NO CONTENT
*/
@DELETE
@Consumes(MediaType.APPLICATION_JSON)
- @Path("sources/{group}/{srcIp}/{srcCp}")
+ @Path("sources/{group}/{srcIp}/{hostId}")
public Response deleteSource(@PathParam("group") String group,
@PathParam("srcIp") String srcIp,
- @PathParam("srcCp") String srcCp) {
+ @PathParam("hostId") String hostId) {
Optional<McastRoute> route = getMcastRoute(group, srcIp);
route.ifPresent(mcastRoute -> get(MulticastRouteService.class)
- .removeSources(mcastRoute, ImmutableSet.of(ConnectPoint.deviceConnectPoint(srcCp))));
+ .removeSource(mcastRoute, HostId.hostId(hostId)));
return Response.noContent().build();
}
diff --git a/apps/mcast/web/src/main/resources/definitions/McastHostSourcesAdd.json b/apps/mcast/web/src/main/resources/definitions/McastHostSourcesAdd.json
new file mode 100644
index 0000000..07a51a6
--- /dev/null
+++ b/apps/mcast/web/src/main/resources/definitions/McastHostSourcesAdd.json
@@ -0,0 +1,22 @@
+{
+ "type": "object",
+ "title": "sources",
+ "required": [
+ "sources"
+ ],
+ "properties": {
+ "sources": {
+ "type": "array",
+ "xml": {
+ "name": "sources",
+ "wrapped": true
+ },
+ "items": {
+ "type": "string",
+ "example": "of:0000000000000206/8",
+ "description": "A source connect point for a host in the route"
+ },
+ "description": "Source connect points for a host in the route"
+ }
+ }
+}
\ No newline at end of file
diff --git a/apps/mcast/web/src/main/resources/definitions/McastRoute.json b/apps/mcast/web/src/main/resources/definitions/McastRoute.json
index 006ed70..513997f 100644
--- a/apps/mcast/web/src/main/resources/definitions/McastRoute.json
+++ b/apps/mcast/web/src/main/resources/definitions/McastRoute.json
@@ -28,10 +28,10 @@
},
"items": {
"type": "string",
- "example": "of:0000000000000206/8",
- "description": "A source connect point for the route"
+ "example": "00:CC:00:00:00:02/None",
+ "description": "A host source for the route"
},
- "description": "Source connect points for the route"
+ "description": "Host source for the route"
},
"sinks": {
"type": "array",
diff --git a/apps/mcast/web/src/main/resources/definitions/McastRouteBulk.json b/apps/mcast/web/src/main/resources/definitions/McastRouteBulk.json
index f32cc4f..1f5f741 100644
--- a/apps/mcast/web/src/main/resources/definitions/McastRouteBulk.json
+++ b/apps/mcast/web/src/main/resources/definitions/McastRouteBulk.json
@@ -27,10 +27,10 @@
},
"items": {
"type": "string",
- "example": "of:0000000000000206/8",
- "description": "A source connect point for the route"
+ "example": "00:CC:00:00:00:02/None",
+ "description": "A host source for the route"
},
- "description": "Source connect points for the route"
+ "description": "Host source for the route"
},
"sinks": {
"type": "array",
diff --git a/apps/mcast/web/src/main/resources/definitions/McastSourcesAdd.json b/apps/mcast/web/src/main/resources/definitions/McastSourcesAdd.json
index 72910a9..d45ed19 100644
--- a/apps/mcast/web/src/main/resources/definitions/McastSourcesAdd.json
+++ b/apps/mcast/web/src/main/resources/definitions/McastSourcesAdd.json
@@ -13,10 +13,10 @@
},
"items": {
"type": "string",
- "example": "of:0000000000000206/8",
- "description": "A source connect point for the route"
+ "example": "00:CC:00:00:00:02/None",
+ "description": "A host source for the route"
},
- "description": "Source connect points for the route"
+ "description": "Host source for the route"
}
}
}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastHandler.java
index 3b659bd..289778e 100644
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastHandler.java
+++ b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastHandler.java
@@ -183,7 +183,9 @@
// Get source, mcast group
// FIXME To be addressed with multiple sources support
final ConnectPoint source = mcastPrevUpdate.sources()
+ .values()
.stream()
+ .flatMap(Collection::stream)
.findFirst()
.orElse(null);
IpAddress mcastIp = mcastPrevUpdate.route().group();
diff --git a/apps/t3/src/main/java/org/onosproject/t3/impl/McastGenerator.java b/apps/t3/src/main/java/org/onosproject/t3/impl/McastGenerator.java
index 59d5ba6..a5022a2 100644
--- a/apps/t3/src/main/java/org/onosproject/t3/impl/McastGenerator.java
+++ b/apps/t3/src/main/java/org/onosproject/t3/impl/McastGenerator.java
@@ -63,25 +63,27 @@
mcastService.getRoutes().forEach(route -> {
McastRouteData routeData = mcastService.routeData(route);
IpAddress group = route.group();
- routeData.sources().forEach(source -> {
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder()
- .matchVlanId(vlanId)
- .matchInPort(source.port());
- if (group.isIp4()) {
- selector.matchEthDst(IPV4_ADDRESS)
- .matchIPDst(group.toIpPrefix())
- .matchEthType(EthType.EtherType.IPV4.ethType().toShort());
- } else {
- selector.matchEthDst(IPV6_ADDRESS)
- .matchIPv6Dst(group.toIpPrefix())
- .matchEthType(EthType.EtherType.IPV6.ethType().toShort());
- }
- try {
- yield(ImmutableSet.of(manager.trace(selector.build(), source)));
- } catch (InterruptedException e) {
- log.warn("Interrupted generator", e.getMessage());
- log.debug("exception", e);
- }
+ routeData.sources().forEach((host, sources) -> {
+ sources.forEach(source -> {
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder()
+ .matchVlanId(vlanId)
+ .matchInPort(source.port());
+ if (group.isIp4()) {
+ selector.matchEthDst(IPV4_ADDRESS)
+ .matchIPDst(group.toIpPrefix())
+ .matchEthType(EthType.EtherType.IPV4.ethType().toShort());
+ } else {
+ selector.matchEthDst(IPV6_ADDRESS)
+ .matchIPv6Dst(group.toIpPrefix())
+ .matchEthType(EthType.EtherType.IPV6.ethType().toShort());
+ }
+ try {
+ yield(ImmutableSet.of(manager.trace(selector.build(), source)));
+ } catch (InterruptedException e) {
+ log.warn("Interrupted generator", e.getMessage());
+ log.debug("exception", e);
+ }
+ });
});
});